Converting a cURL request to a Ruby post request - ruby

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"}]

Related

Is there any way to directly run our ruby codes from puppet console?

I am new to both Ruby Language and Puppet. I want to run a ruby code which is a converted form of a cURL, from my puppet console.
I am putting the cURL and the converted ruby below.
curl -k -u stg_admin:password -sS -X POST https://www.something.com
As you can see, this is a very basic cURL, and the converted ruby code is-
require 'net/http'
require 'uri'
require 'openssl'
uri = URI.parse("https://www.something.com")
request = Net::HTTP::Post.new(uri)
request.basic_auth("stg_admin", "password")
req_options = {
use_ssl: uri.scheme == "https",
verify_mode: OpenSSL::SSL::VERIFY_NONE,
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
# response.code
# response.body
I know how to exec cURL directly in my puppet class, but my question is "is there any way to call my ruby code directly in puppet's init.pp?"
I'll be greatfull for any suggestion.

Using Ruby's Net/HTTP module, can I ever send raw JSON data?

I've been doing a lot of research on the topic of sending JSON data through Ruby HTTP requests, compared to sending data and requests through Fiddler. My primary goal is to find a way to send a nested hash of data in an HTTP request using Ruby.
In Fiddler, you can specify a JSON in the request body and add the header "Content-Type: application/json".
In Ruby, using Net/HTTP, I'd like to do the same thing if it's possible. I have a hunch that it isn't possible, because the only way to add JSON data to an http request in Ruby is by using set_form_data, which expects data in a hash. This is fine in most cases, but this function does not properly handle nested hashes (see the comments in this article).
Any suggestions?
Although using something like Faraday is often a lot more pleasant, it's still doable with the Net::HTTP library:
require 'uri'
require 'json'
require 'net/http'
url = URI.parse("http://example.com/endpoint")
http = Net::HTTP.new(url.host, url.port)
content = { test: 'content' }
http.post(
url.path,
JSON.dump(content),
'Content-type' => 'application/json',
'Accept' => 'text/json, application/json'
)
After reading tadman's answer above, I looked more closely at adding data directly to the body of the HTTP request. In the end, I did exactly that:
require 'uri'
require 'json'
require 'net/http'
jsonbody = '{
"id":50071,"name":"qatest123456","pricings":[
{"id":"dsb","name":"DSB","entity_type":"Other","price":6},
{"id":"tokens","name":"Tokens","entity_type":"All","price":500}
]
}'
# Prepare request
url = server + "/v1/entities"
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.set_debug_output( $stdout )
request = Net::HTTP::Put.new(uri )
request.body = jsonbody
request.set_content_type("application/json")
# Send request
response = http.request(request)
If you ever want to debug the HTTP request being sent out, use this code, verbatim: http.set_debug_output( $stdout ). This is probably the easiest way to debug HTTP requests being sent through Ruby and it's very clear what is going on :)

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

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"}

Ruby POST request with cookies?

I have a Ruby script that sends a POST request with a cookie using:
curl.exe -H "Cookie: SomeCookie=#{cookie}" -d "SomaData=#{data}" http://somesite.com/post
I tried to rewrite this into native Ruby using Net::HTTP, but this code doesn't work:
Net::HTTP.post_form(URI('http://somesite.com/post'),
{'SomeData' => '#{data}',
'Cookie' => 'SomeCookie=#{cookie}'} )
How do I solve this problem?
I'am using MRI Ruby 1.9.3 on Windows 7.
Why not look into using Curb? It's a Ruby interface to libcurl, and has an interface that's closer to cURL than Net::HTTP.
This is from the documentation:
http = Curl.get("http://www.google.com/")
puts http.body_str
http = Curl.post("http://www.google.com/", {:foo => "bar"})
puts http.body_str
http = Curl.get("http://www.google.com/") do|http|
http.headers['Cookie'] = 'foo=1;bar=2'
end
puts http.body_str

Imdb api with Ruby

I am trying to use the imdb API. I tried to search for Fargo, but when I run it, all I get is a black screen:
require 'net/http'
uri = URI.parse("http://imdbapi.org/")
response = Net::HTTP.post_form(uri, {"q" => "Fargo"})
Can anyone tell me what is wrong or provide an example on how to retrieve the data from Fargo with a json in ruby from that api?
Simple way:
require 'json'
require 'open-uri'
json = JSON.parse(open("http://imdbapi.org?q=Fargo") { |x| x.read }).first
To get individual element:
json['title']
#=> Fargo
This simple code below show us how to get a basic json data from imdb api:
require "net/http"
require "uri"
uri = URI.parse("http://imdbapi.org/?title=Fargo&type=json")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
puts response.body
I use a verb GET in the REST way.

Resources