1

Please help me understand, what i'm doing wrong? I need to make POST request to api from my rails app, i tried to do it firstly with gem "faraday" and then with "net/http". Response from server the same. Account creates, but gives error:

Net::HTTPBadResponse (wrong header line format)

class Connect
 require 'uri'
 require 'net/http'
 require 'net/https'
 require 'faraday'

 def initialize(email, password, account)
   @base_url = "https://example.com"
   @client_id = ENV["client_id"]
   @client_secret = ENV["client_secret"]
   @email = email
   @password = password
   @account = account
 end

 # method with net/http
 def create_account

   @toSend = {
     first_name: @account[:first_name],
     last_name: @account[:last_name],
     client_id: @client_id,
     client_secret: @client_secret,
     email: @email,
     password: @password
   }.to_json

  uri = URI.parse("#{@base_url}/endclient/api/account")
  https = Net::HTTP.new(uri.host,uri.port)
  https.use_ssl = true
  req = Net::HTTP::Post.new(
    uri.path,
    initheader = {
                   'Content-Type' =>'application/json',
                   'Accept' =>'application/json'
    }
  )
  req.body = "#{@toSend}"
  res = https.request(req)
 end

 # faraday method
 def make_account

  conn = Faraday.new(:url => "#{@base_url}") do |faraday|
    faraday.response :logger                  
    faraday.adapter  Faraday.default_adapter
  end

  params = { first_name: @account[:first_name],
    last_name: @account[:last_name],
    client_id: @client_id,
    client_secret: @client_secret,
    email: @email,
    password: @password
   }.to_json

  response = conn.post do |req|
    req.url '/endclient/api/account'
    req.headers['Content-Type'] = 'application/json'
    req.headers['Accept'] = 'application/json'
    req.body = params
  end
 end
end

Done this request with success via Postman, so endpoint of the api is working.

Please help me understand what's wrong with headers ? Thanks in advance!

UPDATE:

May be problem in this ?

Cannot render console with content type application/jsonAllowed content  types: [#<Mime::Type:0x00000003661658 @synonyms=["application/xhtml+xml"], @symbol=:html, @string="text/html">, #<Mime::Type:0x00000003660fc8 @synonyms=[], @symbol=:text, @string="text/plain">, #<Mime::Type:0x0000000365ca68 @synonyms=[], @symbol=:url_encoded_form, @string="application/x-www-form-urlencoded">]
Paul Ro
  • 148
  • 1
  • 7
  • For your net/http method try this `req.body = @toSend.to_query` instead of `req.body = "#{@toSend}"`. let me know if it works. – Harry Bomrah Nov 26 '15 at 08:42
  • @HarryBomrah, thanks for your answer, i tried this, it gives me error `ArgumentError (wrong number of arguments (0 for 1)` – Paul Ro Nov 26 '15 at 08:52
  • Which line ? Did u change anything else? – Harry Bomrah Nov 26 '15 at 08:54
  • @HarryBomrah In this line `req.body = @toSend.to_query`, nope , change nothing. – Paul Ro Nov 26 '15 at 09:00
  • remove `to_json` from your `@toSend = {...}.to_json` – Harry Bomrah Nov 26 '15 at 09:04
  • @HarryBomrah, response as html, 404 page . – Paul Ro Nov 26 '15 at 09:31
  • Check your paths then. not finding the page. – Harry Bomrah Nov 26 '15 at 09:39
  • @HarryBomrah It's third party API response, i think in this case, to_query method make API response like that. Without to_query method, account creates, but gives error `Net::HTTPBadResponse (wrong header line format)` , i think API returns headers in wrong form, that is why Rails not like it. – Paul Ro Nov 26 '15 at 09:45
  • Ok try two more things. 1. remove `to_json` and instead of `res.body = "#{@toSend}"` use this `req.set_form_data(@toSend)` 2. remove `'Accept' =>'application/json'` from your initheader. just keep content-type – Harry Bomrah Nov 26 '15 at 09:51
  • @HarryBomrah, no luck, it gives back the same 404 html page. – Paul Ro Nov 26 '15 at 09:55
  • Well then i think there is a problem on API side. Try checking your API and check logs, maybe you ll find something. I cant do much without code in my hands. – Harry Bomrah Nov 26 '15 at 10:02
  • @HarryBomrah, i understand, thank you for your help anyway! – Paul Ro Nov 26 '15 at 10:15

2 Answers2

0

If you want a http lib that easily mixes into a class/module than I would recommend httparty over Faraday or just plain old Net::HTTP.

require 'httparty' # Requires go at the top of the file. Not in class body.

class MyApiClient
  include HTTParty
  base_uri 'test.example.com'
  # Tells Httparty to send JSON for all requests.
  format :json 

  # @see https://robots.thoughtbot.com/ruby-2-keyword-arguments
  def initialize(client_id: ENV["client_id"], client_secret: ENV["client_secret"])
    @options = { 
      body: { 
        client_id: client_id, 
        client_secret: client_secret
      } 
    }
  end

  # @return [HTTParty::Response]
  def create_account(first_name:, last_name:, email:, password:)
    # ActiveSupport method that creates a copy so that we don't 
    # alter the instance options as a side effect.
    opts = @options.deep_dup 
    opts[:body].merge!(
      email: email, 
      password: password,
      first_name: first_name,
      last_name: last_name
    )
    self.class.post('/endclient/api/account', opts)
  end
end

The nice thing is that httparty will do all the work with parsing the parameters to and from JSON and sending the correct headers. It also takes care of the dull work of building URI's.

Note that the method signature is slightly different:

client = MyApiClient.new
response = client.create_account(
  first_name: 'John',
  last_name: 'Doe',
  email: 'john.doe@example.com',
  password: 'abcd1234'
)
max
  • 96,212
  • 14
  • 104
  • 165
  • On a side note your API should probably not be taking the client id and secret on every request. Clients should authenticate first and trade for a token which is then sent with each request. But how to build a token based auth is kind of out of scope here. – max Nov 26 '15 at 12:43
  • thank you for your answer. HTTParty is good. We found the error, this was wrong headers from third party API nginx. – Paul Ro Dec 03 '15 at 07:45
0

There was a problem on API side, wrong symbols in header.

Paul Ro
  • 148
  • 1
  • 7