rubyjsoncurlcurb

POST JSON data with Curl Multi from ruby


I am using the curb gem to do a Curl Multi post using JSON data. However I am unable to actually get the parameters to get posted and have been unable to figure out how to properly configure the parameters.

urls = [
  { 
    :url => "http://localhost:5000/", 
    :method => :post, 
    :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}, 
    :post_fields => {'field1' => 'value1', 'k' => 'j'}
  }
]

Curl::Multi.http(urls) do |easy, code, method|
  puts "#{easy.body_str.inspect}, #{method.inspect}, #{code.inspect}"
end

=>

"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n<title>400 Bad Request</title>\n<h1>Bad Request</h1>\n<p>The browser (or proxy) sent a request that this server could not understand.</p>\n", :post, nil

Solution

  • Do that:

    urls = [
      { 
        :url => "http://localhost:5000/", 
        :method => :post, 
        :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}, 
        :post_fields => {},
        :post_body => {'field1' => 'value1', 'k' => 'j'}.to_json,
      }
    ]
    

    The problem: curb doesn't know that you are sending a JSON data. Curb don't read and interprets the contents of :headers. As you can see here, curb transforms your hash into a string separated by "&", which is the default for a normal (non-json) http data sending (eg.: "field1=value1&k=j"). When the server (Rails) read and interprets the header explicity saying that the data is in JSON format, it tries to decode and the result is the same exception that you get when you do that: JSON.parse("field1=value1&k=j").

    To solve this, you need to send "post_fields" as an empty hash, and send your actual data by using "post_body". Also, you need to convert your hash to json manually with to_json.

    I don't know if they (the curb project owners) know this problem, but I suggest you to warning them about it.