Ruby Net:HTTP::Get weird behavior with JSON - ruby-on-rails

I am using Net::HTTP for sending GET request to an API Server to fetch some data based on some configurations as below:
# method to fetch shirt sample details from api server
def fetch_shirt_sample(shirt, query_params)
path = "http://myapiserver.com/shirts/#{shirt.id}/shirt_sample"
url = URI.parse(path)
req = Net::HTTP::Get.new(url.path + '?' + query_params)
res = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }
JSON.parse(res.body)
end
What is wrong or weird I found is above method works for following query params:
"&name=medium_shirt&color=red&configs=[\"full_length\",\"no_collar\",\"casual\"]"
but doesn't even send GET request for following query params:
"&name=medium_shirt&color=red&configs=[\"full_length\",\"15\",\"43\",\"30\"]"
Could anyone help me to understand what is wrong in the above setup?

Related

Make http POST request that return xml response and parsing XML fields

I want to make a http POST request that parse XML response and return the value of SessionId field that is inside XML. This is what I tried so far.
Ps: is there a way I can run this class from the console, in the way that I can see the response?
class Documents::CreateSession
def initialize()
#username = Rails.secrets.legal_doc.username
#password= Rails.secrets.legal_doc.password
end
def start
require "net/http"
require "uri"
uri = URI.parse("http://example.com/search")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data({"userid" => #username, "password" => #password})
response = http.request(request)
end
end
I think that you can run your code the way that you have it now. Start a console and do the following:
obj = Documents::CreateSession.new
obj.start
For debugging purposes, you could put a binding.pry in the start method before you make your request.

Ruby: failed to make a successful GET request

I am trying to send a http.get request to different websites. Here is the code I am using:
def makePing
begin
url = URI.parse(#URI)
req = Net::HTTP::Get.new(url.to_s)
res = Net::HTTP.start(url.host, url.port) {|http|
http.read_timeout = #request_timeout_limit
http.request(req)
}
# debugger
rescue Exception => echo
puts "Error is: Failed to open TCP connection to #{#URI}"
end
end
It returns the result of 200 for 'http://www.example.com'
but
for http://www.google.com or http://www.facebook.com
it returns
<Net::HTTPNotFound 404 Not Found readbody=true>
1-I am wondering why it happens like this?
2-How can I get the body of the response?
3- I expect that, the request get expired exactly after #request_timeout_limit, and it stop trying, but it is not working in this way?

Why Rails (current 4.0) fails to interpret nested JSON (from a HTTP POST)?

I am writing a simple client server application (using only JSON API) with Ruby (client) and Rails (server).
When trying to create a game from client, I am using:
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data({"tttgame" => {"name" => "Marius"}})
resp = http.request(request)
On server side (tttgames_controller.rb) I have:
# POST /tttgames
# POST /tttgames.json
def create
#tttgame = Tttgame.new(tttgame_params)
...
end
...
def tttgame_params
params.require(:tttgame).permit(:name)
end
Logs on server are:
Started POST "/tttgames.json" for 127.0.0.1 at 2013-10-05 12:58:44 +0300
Processing by TttgamesController#create as JSON
Parameters: {"tttgame"=>"{\"name\"=>\"Marius\"}"}
Completed 500 Internal Server Error in 0ms
NoMethodError (undefined method `stringify_keys' for "{\"name\"=>\"Marius\"}":String):
app/controllers/tttgames_controller.rb:33:in `create'
How can I fix this? All examples from the Internet are looking the same. Thanks!
Both methods set_form_data and post_form are encoding data using format x-www-form-urlencoded. Check here.
Examples that are provided do not contain nested hashes.
I have found here an example, under the REST methods section, which works very well.
Thus, in order to get on server a valid structure with nested hashes, the client should use square brackets:
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data({"tttgame[name]" => “Marius”)
resp = http.request(request)
or much simpler:
uri = URI.parse(url)
resp = Net::HTTP.post_form(uri, {"tttgame[name]" => “Marius”})
This will generate on server
Parameters: {"tttgame"=>{"name"=>"Marius"}}
You might want to do this instead. It's even more compact.
uri = URI.parse(url)
resp = Net::HTTP.post_form(uri, "tttgame" => {"name" => "Marius"})
From http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#label-POST+with+Multiple+Values
UPDATE: In addition, your String is not a valid JSON. It needs to be "{\"name\":\"Marius\"}" instead.
You need to parse that response, because right now it is a String ("{\"name\"=>\"Marius\"}") but you actually need a Hash ({"name" => "Marius"}).
Therefore #stringify_keys fails because it is a method that operates on a Hash.
So do a:
#tttgame = Tttgame.new(JSON.parse(tttgame_params))
instead. This will turn your serialized JSON response into a Hash from a String.

Rails 3 Post to external web service

Lets say I have a blog post that a user is creating and I want to send all of the data to an external web service as XML with a specific schema so it can be ingested into that web service.
I have been looking into the ActionDispatch::Request
And I read this Using Ruby on Rails to POST JSON/XML data to a web service post and answer
However I got an error saying content_type was not a valid method for request. So I changed that line to call the header method and create a header for content-type with the appropriate information
Ok... so now where to go?
This is my code so far:
url= URI.parse('http://10.29.3.47:8080/ingest')
response = Net::HTTP::Post.new(url.path)
request.headers["Content-Type"] = 'application/json'
request.body = 'all of my xml data and schema which is far too long to type here'
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
assert_equal '201 Created', response.get_fields('Status')
I get an error saying that request.body is also not a valid method call, but when I look at the API the only thing matching body is "body()" which does not take arguments. So how do I pass the content of my post to the web service?
Thank you for the help!
You had response = Net::HTTP::Post.new(url.path) instead of request = Net::HTTP::Post.new(url.path) and you add headers with add_field.
require 'net/http'
require 'uri'
url= URI.parse('http://10.29.3.47:8080/ingest')
request = Net::HTTP::Post.new(url.path)
request.add_field 'Content-Type', 'application/json'
request.body = 'all of my xml data and schema which is far too long to type here'
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}

How to solve error with using NET::HTTP

I want to post some data using standard ruby class NET::HTTP.
I have controller from examples
def request
require "net/http"
require "uri"
uri = URI.parse("http://google.com/")
# Shortcut
response = Net::HTTP.get_response(uri)
# Will print response.body
Net::HTTP.get_print(uri)
# Full
http = Net::HTTP.new(uri.host, uri.port)
response = http.request(Net::HTTP::Get.new(uri.request_uri))
end
My application gives error -
undefined method `content_mime_type' for #<Net::HTTPMovedPermanently 301 Moved Permanently readbody=true>
Why this is happening ?
Problem might be that in the last line of your code, there are two requests happening. The code translates to:
response = http.request(<result>) where the <some result> part is the return value from the call Net::HTTP::Get.new(uri.request_uri)
I think you were trying to do this instead:
http.request(uri.request_uri)

Resources