How do I use RestClient to post as URL params? - ruby

I am posting to an API which accepts CURL as follows:
curl -v -X POST "https://url.com" -d 'input=frustrated&user_key=3b9ccb48e734fce6b982a9c1c2cef301'
I have tried the following with an error:
data = {'user_key' => "#{ENV['USER_KEY']}", 'input' => "#{text}", 'client_name'=>> "#{client_name}"}
talkresponse = JSON.parse(RestClient.post url_talk_bot, {:params => data})
for some reason, the data is fine for all except for 'input' which always gets an error as an array which triggers an error since a string is expected. Note below how the input params is an array.
{"user_key"=>"3b9ccb48e734fce6b982a9c1c2cef301", "input"=>"[\"frustrated how do I post to params, worked fine before\"]", "client_name"=>"14155086888"}
/mnt/task/__gems__/gems/rest_client-1.7.3/lib/restclient/abstract_response.rb:48:in `return!': 401 Unauthorized (RestClient::Unauthorized)

I have run into similar issues when using RestClient.post.
So much so, that I stopped using .post and started using .execute
RestClient.post uri, {:params => data}
becomes
RestClient.execute({ :method => :post, :url => uri, :headers => {api_key: '123', authorization: Base64::encode("#{user}:#{password}"}, :payload: body})

Related

In ruby with sinatra, How to get I response with get method on rest client?

I use ruby with sinatra and I used rest-client on import for payment.
I got token that string typed through post method on specific url: '... /users/getToken'.
Using this token, I wanna get payments information with get method on this url:
get_url = 'https://api/iamport.kr/payments/'+imp_uid
the detail codes are below,
def get_paymentsdetails(token, imp_uid)
get_url = 'https://api.iamport.kr/payments/'+imp_uid
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
json = JSON.parse(response, :symbolize_names => true)
# json = JSON.parse(response.to_json, {:symbolize_names => true})
return json
end
However, I got 401 unauthorized error on this part of code.
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
After I access get_url with specific imp_uid, I got this page,{"code":-1,"message":"Unauthorized","response":null}
I checked parameter token and imp_uid of get_paymentsdetails function have valid string values,, so How can I access response parameter??
I think that there are some problems on response = RestClient.get get_url.... code.
Thanks.
Method 'get' from the 'RestClient' class return some object with attributes. So response have few values. Which of them do you need? Access to them you can get by their names, its described here.
In your case, after response = RestClient.get get_url... you should have variable response and ability to call response.headers, response.code or response.body.
But im afraid that you have some problems with autorization, which means that imp_uid or token is not correct. Thats why remote server sended to you responce with http-code 401 (Unauthorized). If it is so you should try to check your imp_uid and token. If everything is correct try to reach support of iamport.kr .

Add data fields to a rest-client request in Ruby

I am having trouble making a request to the uber api using the rest-client gem. I believe the issue is that I am trying to pass the required information as parameters in the url instead of data field. The example curl request has that parameters after -d, but I don't know how to implement that with rest-client. Thanks for the help.
This request works in the console:
curl -v -H "Authorization: Bearer " + session[:request_token] \
-H "Content-Type: application/json" -X POST -d \ '{"start_latitude":"37.334381","start_longitude":"-121.89432","end_latitude":"37.77703","end_longitude":"-122.419571","product_id":"a1111c8c-c720-46c3-8534-2fcdd730040d"}' \
https://sandbox-api.uber.com/v1/requests
Request from my controller that gets an error of 406, not acceptable response.
#uber_ride = JSON.load(RestClient::Request.execute(
:method => :post,
:url => "https://sandbox-api.uber.com/v1/sandbox/requests/product_id=#{#uberx_id}?start_latitude=#{lat_start}&start_longitude=#{lng_start}&end_latitude=#{lat_end}&end_longitude=#{lng_end}",
:headers => {'Authorization' => 'Bearer ' + session[:request_token], 'content_type' => 'application/json'}
))
I tried adding an additional field for data but that give a 404 Resource Not Found error.
#uber_ride = JSON.load(RestClient::Request.execute(
:method => :post,
:url => "https://sandbox-api.uber.com/v1/sandbox/requests/",
:data => {'start_latitude' => lat_start, 'start_longitude' => lng_start, 'end_latitude' => lat_end, 'end_longitude' => lng_end, 'product_id' => #uberx_id},
:headers => {'Authorization' => 'Bearer ' + session[:request_token]},
:content_type => :json
))
I finally got it working. Thanks #mudasobwa for the recommendation of changing data => to payload =>. I also had to add single quotes around the payload object so the rest-client gem wouldn't convert it out of json. ex: '{}'. Lastly, I had to change how I specified the content-type and specify it in :headers, as :content_type, NOT 'Content-Type'. See below for the final request that is now working. It's a bit messy with the variables being .to_s, but after 5 hours this is the only call I could get working.
#uber_ride = (RestClient::Request.execute(
:method => :post,
:url => "https://sandbox-api.uber.com/v1/requests",
:payload => '{"start_latitude":' + lat_start.to_s + ',"start_longitude":' + lng_start.to_s + ',"end_latitude":' + lat_end.to_s + ',"end_longitude":' + lng_end.to_s + ',"product_id":"' + #uberx_id.to_s + '"}',
:headers => {'Authorization' => 'Bearer ' + session[:request_token], :content_type => 'application/json'}
))
Happy to hear any feedback on how I could clean this up.

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
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.

Setting Request Headers in Ruby

I have the rest client gem and I am defining a request like this:
url = 'http://someurl'
request = {"data" => data}.to_json
response = RestClient.post(url,request,:content_type => :json, :accept => :json)
However I need to set the HTTP header to something. For example an API key. Which could be done in curl as:
curl -XHEAD -H x-auth-user: myusername -H x-auth-key: mykey "url"
Whats the best way to do this in ruby? Using this gem? Or can I do it manually to have more control.
The third parameter is the headers hash.
You can do what you want by:
response = RestClient.post(
url,
request,
:content_type => :json, :accept => :json, :'x-auth-key' => "mykey")
You can also do this
RestClient::Request.execute(
:method => :get or :post,
:url => your_url,
:headers => {key => value}
)
I had the same problem with Rest-Client (1.7.2) I need to put both params and HTTP headers.
I solved with this syntax:
params = {id: id, device: device, status: status}
headers = {myheader: "giorgio"}
RestClient.put url, params, headers
I hate RestClient :-)
If PUT isn't allowed we can pass it in the header of POST. Headers in bold. This worked for me:
act_resp = RestClient.post url, req_param, **:content_type => :json, :method => :put**

Ruby Multi-part Form Upload with RestClient

I'm working on a ruby application, and am trying to upload a file to box.net. I have it working with the curl call
curl https://www.box.com/api/2.0/files/data -H "Authorization: BoxAuth api_key=<API_KEY>&auth_token=<AUTH_TOKEN>" -F folder_id=0 -F filename=#test.txt --trace ~/Desktop/log.txt
I've tried to translate this into ruby, and have tried the following
request = RestClient::Request.new(:method => :post,:url => "https://www.box.com/api/2.0/files/data",:authorization => "BoxAuth api_key=<API_KEY>&auth_token=<AUTH_TOKEN>",:filename => "test.txt", :payload => { :multipart => true, :file => File.new("test.txt"))
request.execute
but I keep getting back a "401: Unauthorized" response. I've also tried using the box-api gem, but that seems to only work with version 1.0 of the API, and I'm trying to interface with 2.0.
Try to use :headers => {:authorization => "BoxAuth api_key=<API_KEY>&auth_token=<AUTH_TOKEN>"} in the call. That should fix the missing authorization header.
Complete request would then be:
request = RestClient::Request.new(:method => :post,:url => "https://www.box.com/api/2.0/files/data",:headers => {:authorization => "BoxAuth api_key=<API_KEY>&auth_token=<AUTH_TOKEN>"},:filename => "test.txt", :payload => { :multipart => true, :file => File.new("test.txt")})

Resources