Ruby: How to Send a JSON Post Request Using Curb

Ruby: How do I send a JSON POST request using Curb?

The correct way of doing this is to simply add the content after the URL:

c = Curl::Easy.http_post("https://example.com", json_string_goes_here   
) do |curl|
curl.headers['Accept'] = 'application/json'
curl.headers['Content-Type'] = 'application/json'
curl.headers['Api-Version'] = '2.2'
end

This will set the json_string to be the request body.

POST JSON data with Curl Multi from ruby

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.

Sending JSON via cURL POST request to Sinatra

I got it...no need to fool around with params. I can get the JSON payload as a hash by doing the following...

payload = JSON.parse(request.body.read)

Curl using ruby

To send JSON data with HTTPI/curb, just set your JSON string as the request body as follow:

require 'httpi'
require 'curb'
require 'json'
# ...

req.body = {"id"=>"12341234","fieldsRequested"=>["title","state","component"]}.to_json

# Then set your custom headers
req.headers = {"Accept" => "application/json", "Content-Type" => "application/json"}

Also do not enable the multipart_form_post option since multipart POST is not needed:

req.auth.gssnegotiate
resp = HTTPI.post req do |http|
http.use_ssl
end

Pass GET parameters with Ruby Curb

If you don't mind using ActiveSupport '~> 3.0', there's an easy workaround - to_query method, which converts hash to query string ready to be used in URL.

# active_support cherry-pick
require 'active_support/core_ext/object/to_query'

params = { :bla => 'blablabla' }

Curl::Easy.perform("http://foo.com/bar.xml?" + params.to_query) {|curl|
curl.set_some_headers_if_necessary
}

How to properly format json to send over using RestClient

You should put all your params in one params hash like this:

  params = {
recipient: { id: sender },
message: { text: text },
access_token: page_token
}

response = RestClient.post base_uri, params.to_json, content_type: 'application/json', accept: 'application/json'
p "this is the response #{response}"

How can I POST json data from android app to Ruby on Rails server

Welcome to S.O.!

So, there's a few things that need addressing here. For starters, in your controller:

# For creating an expense from the android app
def post_json_expense
Expense.new(expense_params)
end

So, first, calling Expense.new here will only create a new object, but it will not persist it to the database; you'll also need to call save to do that.

Next, you are not returning any sort of response back to the caller. Perhaps returning something like the id of the new Expense would be in order, or the expense itself. I'd suggest constructing the call like so:

# For creating an expense from the android app
def post_json_expense
expense = Expense.new(expense_params)
unless expense.save
# TODO: Return an error status with some useful details
# You can get some from expense.errors
return render status: 400, json: { error: true }
end
# Render a JSON representation of the expense on successful save
render json: expense.as_json
end

Next, on the client side, you are sending Content-type headers, which is good, but you could also send Accept headers, which clues the server as to what you expect to receive back:

public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
params.put("Accept", "application/json");
return params;
}

Finally, you have assigned the method to the POST route on your server:

post '/api' => 'expenses#post_json_expense'

But you are calling it as a PUT from your app:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, url, expenseObject, new Response.Listener<JSONObject>() {

So, there is no PUT route at that URL, hence why the request would always fail.

Cleaning up these issues should get you a successful response.

Personally, I find using a simple utility like curl often helps debug these sort of communication errors, when you don't know whether the issue is the fault of an app-side coding issue or a server-side coding issue (or both). You can eliminate the variables by using something like curl which you can be confident works, then debug from there.

Hope this helps you along!



Related Topics



Leave a reply



Submit