Setting Request Headers in Ruby - 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**

Related

Ruby Restclient different double point or astrophobe and is order important

i am new to ruby RestClient. i have search many example of this restclient and in docruby. For me is important while using ruby restclient, to get the data very fast.
But some are not answers, this is why i would like to question to you all.
i am working on this ruby restclient example Code:
restClient = RestClient::Request.new(
:method => :get,
:url => url,
:verify_ssl => true, #required using https
:content_type => :json,
:accept => :json,
:headers => {
:Authorization => "Bearer #{token}",
}
)
result = restClient.execute()
My first question is what is different of using double point and astrophobe?
restClient = RestClient::Request.new(
:method => :get,
:method => 'get',
...
)
Second question is, is sequences/order in Code important like first url then method or method then url and so on?
restClient = RestClient::Request.new(
:url => :url,
:method => :get,
...
)
#or
restClient = RestClient::Request.new(
:method => :get,
:url => :url,
...
)
third question is, about accept to put in headers. some put accept and content-type in headers and some not, what is different?
restClient = RestClient::Request.new(
:content_type => 'application/json',
:accept => 'application/json',
#or
:headers => {
'hello-token' => "Bearer #{token}",
'content_type'=> 'application/json',
'ACCEPT' => 'application/json'
}
)
What is different of using double point and astrophobe?
:get is a Symbol, 'get' is a String.
It depends on the implementation of the gem if the gem is able to process both. Because the RestClient documentation uses a Symbol in its examples I would recommend doing the same.
But actually – at least in its current version - it doesn' make a difference because the gem translate the argument internally into a string anyway (see initialize and normalize_method)
is sequences/order in Code important
In theory, a hash is an unordered data structure. Therefore the order should not be important in this case. But keep in mind that Ruby's implementation of a hash is actually preserving the order in which the keys are inserted when iterating the hash.
Accept headers
I didn't find any example in the gem's documentation in which they used the first version. Did you actually try both versions? I would be surprised when both worked. Therefore I suggest using the header: version.

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.

Rest-Client: how to post multipart/form-data?

I have to implement the curl POST request below listed, in Ruby, using Rest-Client.
I have to:
send params in header;
send params (that do not contain a file) as multipart/form-data:
$ curl -X POST -i -H "Authorization: Bearer 2687787877876666686b213e92aa3ec7e1afeeb560000000001" \
https://api.somewhere.com/endpoint -F sku_id=608399
How can I translate the curl request using the RestClient rubygem?
Reading documentation (multipart paragraph): https://github.com/rest-client/rest-client
I coded as:
#access_token = 2687787877876666686b213e92aa3ec7e1afeeb560000000001
url = 'https://api.somewhere.com/endpoint'
req = { authorization: "Bearer #{#access_token}"}
RestClient.post url, req, {:sku_id => 608399, :multipart => true}
But I get a server error; is the Ruby code above correct?
Thanks a lot,
Giorgio
Since I had trouble understanding the example Dmitry showed, here is an example for creating a Multipart request to upload an image:
response = RestClient.post 'https://yourhost.com/endpoint',
{:u_id => 123, :file => File.new('User/you/D/cat.png', 'rb'), :multipart => true},
{:auth_token => xyz5twblah, :cookies => {'_cookie_session_name' => cookie}}
It's code not valid for RestClient implementation.
headers should follow after payload.
module RestClient
def self.post(url, payload, headers={}, &block)
...
end
end
UPDATE
#access_token should be a string "2687787877876666686b213e92aa3ec7e1afeeb560000000001"
then
RestClient.log = 'stdout'
RestClient.post url, {:sku_id => 608399, :multipart => true}, req
and log
RestClient.post "https://api.somewhere.com/endpoint", "--330686\r\nContent-Disposition: form-data; name=\"sku_id\"\r\n\r\n608399\r\n--330686--\r\n", "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"Bearer 2687787877876666686b213e92aa3ec7e1afeeb560000000001", "Content-Length"=>"79", "Content-Type"=>"multipart/form-data; boundary=330686"

Correct syntax for get requests with rest-client

Right now I can make a request as follows:
user = 'xxx'
token = 'xxx'
survey_id = 'xxx'
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php?Request=getLegacyResponseData&User=#{user}&Token=#{token}&Version=2.0&SurveyID=#{survey_id}&Format=XML"
But there should be some nicer way to do this. I've tried things like:
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :Request => 'getLegacyResponseData', :User => user, :Token => token, :Version => '2.0', :SurveyID => survey_id, :Format => 'XML'</code>
and variations thereof (strings instead of symbols for keys, including { and }, making the keys lower case, etc.) but none of the combinations I tried seemed to work. What's the correct syntax here?
I tried the first suggestion below. It didn't work. For the record, this works:
surveys_from_api = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php?Request=getSurveys&User=#{user}&Token=#{token}&Version=#{version}&Format=JSON"
but this doesn't:
surveys_from_api = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :params => {:Request => 'getSurveys', :User => user, :Token => token, :Version => version, :Format => 'JSON'}
(where I've set version = '2.0').
You need to specify query strings parameters with the symbol :params. Otherwise they will be used as headers.
Example with params:
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :params => {:Request => 'getLegacyResponseData', :User => user, :Token => token, :Version => '2.0', :SurveyID => survey_id, :Format => 'XML'}
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 :-)
In rest-client api docs I see that headers is a Hash and if you want to provide both - headers and params, then you need to use a :params key inside the headers Hash. e.g.
headers = { h1 => v1, h2 => v2, :params => {my params} }
What you really need is URI.encode_www_form() method.
uri = URI("https://survey.qualtrics.com/WRAPI/ControlPanel/api.php")
request_params = {
Request: 'getLegacyResponseData',
...
}
uri.query = URI.encode_www_form(request_params)
response = RestClient.get(uri.to_s)

How do I do basic authentication with RestClient?

Does anyone know how to do basic authentication with RestClient?
I need to create a private repository on GitHub through their RESTful API.
The easiest way is to embed the details in the URL:
RestClient.get "http://username:password#example.com"
Here is an example of working code where I support optional basicauth but don't require the user and password be embedded in the URL:
def get_collection(path)
response = RestClient::Request.new(
:method => :get,
:url => "#{#my_url}/#{path}",
:user => #my_user,
:password => #my_pass,
:headers => { :accept => :json, :content_type => :json }
).execute
results = JSON.parse(response.to_str)
end
Do note if #my_user and #mypass are not instantiated, it works fine without basicauth.
From the source it looks like you can just specify user and password as part of your request object.
Have you tried something like:
r = Request.new({:user => "username", :password => "password"})
Also if you look down in the Shell section of the ReadMe it has an example of specifying it as part of restshell.
$ restclient https://example.com user pass
>> delete '/private/resource'
This works and follows RFC 7617 for Http Basic Authentication:
RestClient::Request.execute(
method: :post,
url: "https://example.com",
headers: { "Authorization" => "Basic " + Base64::encode64(auth_details) },
payload: { "foo" => "bar"}
)
def auth_details
ENV.fetch("HTTP_AUTH_USERNAME") + ":" + ENV.fetch("HTTP_AUTH_PASSWORD")
end
Thanks to Kelsey Hannan:
RestClient.get("https://example.com",
{
Authorization: "Basic #{Base64::encode64('guest:guest')}"
}
)
RestClient.post("https://example.com",
{ }.to_json,
{
Authorization: "Basic #{Base64::encode64('guest:guest')}"
}
)

Resources