Using RestClient instead of curl -- how do I do that? - ruby

I am trying to use RestClient to do the following which is currently in Curl:
curl -H "Content-Type: application/json" -X POST --data '{"contacts" : [1111],"text" : "Testing"}' https://api.sendhub.com/v1/messages/?username=NUMBER\&api_key=APIKEY
I don't see in the docs for RestClient how to perform the equivalent as "--data" above as well as passing -H (Header) information.
I tried the following:
url = "https://api.sendhub.com/v1/messages/?username=#{NUMBER}\&api_key=#{APIKEY}"
smspacket = "{'contacts':[#{contact_id}], 'text' : ' #{text} ' }"
RestClient.post url , smspacket, :content_type => 'application/json'
But this give me a Bad Request error.

I presume this is probably very late, but for the record and since I was hanging around with my own question.
Your problem weren't really with the use or not of the :to_json method, since it will output a string anyway. The body request has to be a string.
According to http://json.org strings in json have to be defined with " and not with ', even if in javascript we mostly used to write json this way. Same if you use no quote at all for keys.
This is probably why you received a bad request.
pry(main)> {"test": "test"}.to_json
"{\"test\":\"test\"}"
pry(main)> JSON.parse(RestClient.post('http://httpbin.org/post', "{'test': 'test'}", {content_type: :json, accept: :json}).body)["json"]
nil
pry(main)> JSON.parse(RestClient.post('http://httpbin.org/post', '{test: "test"}', {content_type: :json, accept: :json}).body)["json"]
nil
pry(main)> JSON.parse(RestClient.post('http://httpbin.org/post', '{"test": "test"}', {content_type: :json, accept: :json}).body)["json"]
{"test"=>"test"}

Related

Rspec Failure/Error Content-type expected:"json" got:"text/html"

I'm currently getting the following error when I run my rspec test
Failure/Error: expect(last_response.header['Content-Type']).to eq('application/json')
expected: "application/json"
got: "text/html"
(compared using ==)
I specify the content type in the method here
get '/restart/?' do
content_type :json
# token authentication
need_token!
# restart operation
exit_process
status 200
JSON.pretty_generate({ 'ok' => true, 'message' => 'Restarting ...' })
end
And when I run the curl get command I get the following out showing the Content-Type: application/json
curl -X GET -H X-AUTH-TOKEN:$TOKEN --url localhost:8080/restart -I
HTTP/1.1 200 OK
Content-Type: application/json
X-Content-Type-Options: nosniff
Vary: Accept-Encoding
Content-Length: 85
Why is rspec test returning "text/hmtl"?
Aloha!
I was working on a similar test recently! I can see a little difference in your approach defining the (sinatra) route. I have specified the Content-Type using headers and it looks like this:
headers['Content-Type'] = 'application/pdf'
Then in my test (I'm using RSpec) I'm doing this:
expect(last_response.header['Content-Type']).to eq('application/pdf')
Just simply put the headers in request
request.headers['Content-Type'] = "application/json"
Or you can modify according to requirements

Reproduce curl request in ruby

I have next curl request:
curl -X POST -H "Content-Type: application/json" -H "charset: UTF-8" -H "Cache-Control: no-cache" -d '{"destId":684}' https://viatorapi.viator.com/service/search/products?apiKey=VIATOR_API_KEY
This curl request is working correct. If I will try to move apiKey parameter to data hash, I'm getting an error that apiKey is missing. For example
curl -X POST -H "Content-Type: application/json" -H "charset: UTF-8" -H "Cache-Control: no-cache" -d '{"destId":684, "apiKey":VIATOR_API_KEY}' https://viatorapi.viator.com/service/search/products
I can't understand what is the difference between this two requests.
Obviously, instead of VIATOR_API_KEY I'm using real value.
And now I'm trying to reproduce this curl request in ruby.
require 'uri'
require 'net/http'
require 'json'
API_KEY = ENV['VIATOR_API_KEY']
BASE_URL = "http://viatorapi.viator.com/service"
path = "/search/products"
# Full reference
uri = URI.parse "#{BASE_URL}#{path}?apiKey=#{API_KEY}"
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.initialize_http_header({"Content-type" => "application/json", "charset" => "UTF-8", "Cache-Control" => "no-cache"})
request.set_form_data('destId' => 684)
response = http.request(request)
puts response.body
if response.code == "200"
# Do something
end
Now I'm getting 415 error Unsupported Media Type.
Any ideas what could be the problem?
UPDATE
I've figured out what it has been due to.
Before setting data parameters request.set_form_data('destId' => 684)
request header is
{"content-type"=>["application/json"], "charset"=>["UTF-8"], "cache-control"=>["no-cache"]}
after
{"content-type"=>["application/x-www-form-urlencoded"], "charset"=>["UTF-8"], "cache-control"=>["no-cache"]}
So, somehow it set_form_data changed content-type
I think that you can use the gem Typhoeus is a curl wrapper is quite easy to translate curl request, here is the example for your request
require 'typhoeus'
request = Typhoeus::Request.new(
"https://viatorapi.viator.com/service/search/products",
method: :post,
params: { apiKey: "VIATOR_API_KEY" },
body: { destId: 684},
headers: { 'Content-Type' => "application/json", charset: "UTF-8",'Cache-Control' => "no-cache" }
)
request.on_complete do |response|
if response.success?
# hell yeah
elsif response.timed_out?
# aw hell no
log("got a time out")
elsif response.code == 0
# Could not get an http response, something's wrong.
log(response.return_message)
else
# Received a non-successful http response.
log("HTTP request failed: " + response.code.to_s)
end
end
request.run
#curl -X POST -H "Content-Type: application/json" -H "charset: UTF-8" -H "Cache-Control: no-cache" -d '{"destId":684}' https://viatorapi.viator.com/service/search/products?apiKey=VIATOR_API_KEY
executing:
irb(main):112:0' => #<Typhoeus::Response:0x007fd46396b920 #options={:httpauth_avail=>0, :total_time=>0.933899, :starttransfer_time=>0.93374, :appconnect_time=>0.52442, :pretransfer_time=>0.5244530000000001, :connect_time=>0.25838099999999997, :namelookup_time=>0.000657, :redirect_time=>0.0, :effective_url=>"https://viatorapi.viator.com/service/search/products?apiKey=VIATOR_API_KEY", :primary_ip=>"54.165.220.73", :response_code=>200, :request_size=>269, :redirect_count=>0, :return_code=>:ok, :response_headers=>"HTTP/1.1 200 OK\r\nDate: Thu, 28 Apr 2016 17:24:23 GMT\r\nContent-Type: application/json;charset=ISO-8859-1\r\nContent-Length: 372\r\nVary: Accept-Encoding\r\n\r\n", :response_body=>"{\"errorReference\":\"~21084218484370761736807418\",\"data\":null,\"dateStamp\":\"2016-04-28T10:24:23+0000\",\"errorType\":\"EXCEPTION\",\"errorMessage\":[\"API ACCESS DENIED!!! Api Key 'VIATOR_API_KEY' is invalid or missing\"],\"errorName\":\"Exception\",\"success\":false,\"totalCount\":1,\"vmid\":\"331004\",\"errorMessageText\":[\"API ACCESS DENIED!!! Api Key 'VIATOR_API_KEY' is invalid or missing\"]}", :debug_info=>#<Ethon::Easy::DebugInfo:0x007fd463988ca0 #messages=[]>}, #request=#<Typhoeus::Request:0x007fd464810f98 #base_url="https://viatorapi.viator.com/service/search/products", #original_options={:method=>:post, :params=>{:apiKey=>"VIATOR_API_KEY"}, :body=>{:destId=>684}, :headers=>{"Content-Type"=>"application/json", :charset=>"UTF-8", "Cache-Control"=>"no-cache"}}, #options={:method=>:post, :params=>{:apiKey=>"VIATOR_API_KEY"}, :body=>{:destId=>684}, :headers=>{"User-Agent"=>"Typhoeus - https://github.com/typhoeus/typhoeus", "Content-Type"=>"application/json", :charset=>"UTF-8", "Cache-Control"=>"no-cache"}, :maxredirs=>50}, #response=#<Typhoeus::Response:0x007fd46396b920 ...>, #on_headers=[], #on_complete=[#<Proc:0x007fd464810e58#/Users/toni/learn/ruby/stackoverflow/scripting/typhoeus_request.rb:11>], #on_success=[]>, #handled_response=nil>
irb(main):113:0>
a little bit pretty
irb(main):039:0> require 'yaml'
=> true
irb(main):043:0> puts request.response.to_yaml
--- &3 !ruby/object:Typhoeus::Response
options:
:httpauth_avail: 0
:total_time: 0.6263529999999999
:starttransfer_time: 0.6262380000000001
:appconnect_time: 0.264124
:pretransfer_time: 0.264161
:connect_time: 0.131438
:namelookup_time: 0.00059
:redirect_time: 0.0
:effective_url: https://viatorapi.viator.com/service/search/products?apiKey=VIATOR_API_KEY
:primary_ip: 54.165.220.73
:response_code: 200
:request_size: 269
:redirect_count: 0
:return_code: :ok
:response_headers: "HTTP/1.1 200 OK\r\nDate: Fri, 29 Apr 2016 06:25:36 GMT\r\nContent-Type:
application/json;charset=ISO-8859-1\r\nContent-Length: 371\r\nVary: Accept-Encoding\r\n\r\n"
:response_body: '{"errorReference":"~2155052986177618334013969","data":null,"dateStamp":"2016-04-28T23:25:36+0000","errorType":"EXCEPTION","errorMessage":["API
ACCESS DENIED!!! Api Key ''VIATOR_API_KEY'' is invalid or missing"],"errorName":"Exception","success":false,"totalCount":1,"vmid":"331009","errorMessageText":["API
ACCESS DENIED!!! Api Key ''VIATOR_API_KEY'' is invalid or missing"]}'
:debug_info: !ruby/object:Ethon::Easy::DebugInfo
messages: []
request: !ruby/object:Typhoeus::Request
base_url: https://viatorapi.viator.com/service/search/products
original_options:
:method: :post
:params: &1
:apiKey: VIATOR_API_KEY
:body: &2
:destId: 684
:headers:
Content-Type: application/json
:charset: UTF-8
Cache-Control: no-cache
options:
:method: :post
:params: *1
:body: *2
:headers:
User-Agent: Typhoeus - https://github.com/typhoeus/typhoeus
Content-Type: application/json
:charset: UTF-8
Cache-Control: no-cache
:maxredirs: 50
on_complete:
- !ruby/object:Proc {}
on_headers: []
response: *3
on_success: []
handled_response:
=> nil
I couldn't find the API documentation for that site, but it appears that the endpoint expects apiKey to be a url query parameter and not in the payload.
If you want to stick to pure Ruby and Net::HTTP then I recommend requests, a wrapper on Net::HTTP that makes it very easy to send requests.

Converting a cURL request to a Ruby post request

I am trying to convert a quick cURL hack I did a while back to a Ruby equivavalent. Coming up short.
I am downloading data from an open JSON API from
http://api.turfgame.com/v4/users
with the following cURL command
curl -s -X POST -H "Content-Type: application/json" -d '[{"name": "tbone"}]' api.turfgame.com/v4/users
My feeble attempts has come up short. What I have so far that's not working is
require 'net/http'
require 'rubygems'
require 'json'
require 'uri'
url = "http://api.turfgame.com/v4/users"
uri = URI.parse(url)
data = {"name" => "tbone"}
headers = {"Content-Type" => "application/json"}
http = Net::HTTP.new(uri.host,uri.port)
response = http.post(uri.path,data.to_json,headers)
puts response.code
puts response.body
The error message I'm getting is
400
{"errorMessage":"Invalid JSON string","errorCode":195887105}
I'm guessing I'm not sending the request properly, but how?
Any pointers most welcome! Thanks
Your curl request has this content [{"name": "tbone"}] (an array with a hash inside), but in your Ruby version you just send the hash {"name" => "tbone"} without the wrapping array.
Change your data to:
data = [{"name" => "tbone"}]

How do I PUT a file with Typheous?

I am trying to send a file via a HTTP PUT request. Curl allows this like:
http://curl.haxx.se/docs/httpscripting.html#PUT
What's the correct way of doing this with Typheous?
FWIW this is what I think was the complete (but not necessarily shortest) answer to the question.
Curl allows the uploading of files w/ PUT; the invocation is:
$ curl --upload-file filename url
where url may be something like:
http://someurl/script.php?var=value&anothervar=val&...
Typhoeus provides the same functionality, but the right way to pass url, params and their values as well as the file body is buried in the ethon docs:
request = Typhoeus::Request.new(
url, :method => :put, :params => params_hash,
:body => File.open(filename) { |io| io.read })
Use request object to get response, etc.
You couldn't have looked very hard:
Examples:
Make put request.
Typhoeus.put("www.example.com")
Parameters:
base_url (String) — The url to request.
options (options) (defaults to: {}) — The options.
Options Hash (options):
:params (Hash) — Params hash which is attached to the base_url.
:body (Hash) — Body hash which becomes a PUT request body.
http://rubydoc.info/github/typhoeus/typhoeus/Typhoeus/Request/Actions#put-instance_method

Writing to Jira6 API via Ruby (error 415)

I am pretty new to ruby. To be honest its my first try doing a ruby script with an http connection. I am lost at one point. Sending data via POST to Jira6. Here is the code I use
# If issues_id.count != 0 make a transition of the issues
if issue_id.count > 0
issue_id.each do |id|
transition_data = '{"transition": {"id": "666"}}'
Net::HTTP.start(jira_domain, jira_port) do |http|
ap jira_transition + id + jira_transition_query
request = Net::HTTP::Post.new(jira_transition + id + jira_transition_query)
request.basic_auth jira_user, jira_pass
request["Content-Type"] = "application/json"
ap transition_data
request.set_form_data('data' => '{"transition": {"id": "841"}}');
response = http.request(request)
ap response.code
ap response
end
end
end
testing this results in the following error:
#<Net::HTTPUnsupportedMediaType 415 Unsupported Media Type readbody=true> error.
when I try the same with curl, it works just fine
curl -D- -u external_user:external_pass -X POST --data '{"transition": {"id": "841"}}' -H "Content-Type: application/json" http://jira.demo.com:80/rest/api/2/issue/17399/transitions\?expand\=transitions.fields
Just to be sure I don't get the same crap answers like on google groups:
Yes I reseted the issue after a sucessfull try :-)
Yes the transitionId 841 is correct :-)
Can someone please send me in the right direction howto send the data to Jira6 REST-API? I think its a marginal error, but I do not recognize it.
Thank you very very much.
I recommend you try the jira-ruby gem
I ran into the same issue. For some reason, you can not use 'request["Content-Type"] = "application/json"'. You must create a new header variable and then pass it as a second argument to Post.new. Then use request.body to include the update params.
if issue_id.count > 0
issue_id.each do |id|
transition_data = '{"transition": {"id": "666"}}'
Net::HTTP.start(jira_domain, jira_port) do |http|
ap jira_transition + id + jira_transition_query
header = {'Content-Type': 'application/json'}
request = Net::HTTP::Post.new(jira_transition + id + jira_transition_query, header)
request.basic_auth jira_user, jira_pass
#request["Content-Type"] = "application/json"
ap transition_data
#request.set_form_data('data' => '{"transition": {"id": "841"}}');
params = {transistion: {id: 841}}
request.body = params.to_json
response = http.request(request)
ap response.code
ap response
end
end
end

Resources