HTTParty's parsed_response method returns a Hash if you get a response code 200 but otherwise it will return a String regardless if the webserver returns a XML response.
HTTParty.get(post_url).parsed_response.class # Depends on response code
Amazon will provide XML (explaining what went wrong) even on a 403.
Am I missing something?
HTTParty parses its #parsed_response based on what the HTTP response's Content-Type header is. Verify what the value is for that HTTP header. In your case, you'd want it to be application/xml.
In case anyone is still encountering this issue today, get can take a format parameter, which can help you ensure your HTTParty::Response object is a Hash:
url = HTTParty.get('http://domain.com', format: :json) # class is a Hash
Related
I have a program that sends an HTTP request and receive the answer.
http = Net::HTTP.new(server, port)
resp, data = http.post(path, url, headers)
After this I see resp with a value of #<Net::HTTPOK:0x00005643dd572980> and data empty, so I receive a
no implicit conversion of nil into String error afterwards when I use it.
I have never used Ruby so I'm a bit confused about what can be failing or how I can debug this. I capture network traffic and both the request and response are sent correctly, and the response contains the expected data.
Is there anything that can make data be empty? How can I debug this?
Per the documentation, the Net::HTTP post method returns an HTTPResponse object. Since there is only one object returned, only resp will be given a value.
You mentioned that "the response contains the expected data." I am wondering if you simply need to employ the body method. Does resp.body give you the data you are looking for?
See https://ruby-doc.org/stdlib-2.7.1/libdoc/net/http/rdoc/Net/HTTP.html#method-i-post
I have this Sinatra::Base code:
class Crush < Sinatra::Base
post '/upload' do
erb params.inspect
end
end
I am using Postman and its interface for uploading a file. So I send a POST request with form-data, where in the body of the request the name is hello and the value is a file test.txt which contains just a simple string hey there.
When I do params.inspect I get this long string
{"------WebKitFormBoundaryocOEEr26iZGSe75n\r\nContent-Disposition: form-data; name"=>"\"hello\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n\r\nhey there\r\n------WebKitFormBoundaryocOEEr26iZGSe75n--\r\n"}
So basically a long has with a single key and a single value. Reading most Sinatra tutorials (where the file is accepted from a form), there's a nice way Sinatra handles this using params[:file], but this doesn't seem to be the case when the file is coming straight from the body of an HTTP request.
I tried a non-modular approach too withou Sinatra::Base, thinking it's some parsing middle-ware missing, but got the same result.
Is there something I'm missing here? Must I go and make my own custom parser to get the content of this long hash? Or is there an easier way?
I figured it's Postman issue. When I switch from 'x-www-form-urlencoded' to 'form-data' in Postman, in the Header section, the field: Content-Type => application/x-www-form-urlencoded is NOT removed. So for those who encounter this problem, make sure you remove it manually.
hi where is the data in post call in koa without co-body or bodyparse or why this error
Error: invalid JSON, only supports object and array
at parse (d:\Proyectos\koaJsTest\node_modules\co-body\lib\json.js:56:13)
co-body performs this regex unless the "strict" option is set to false:
/^[\x20\x09\x0a\x0d]*(\[|\{)/
Perhaps your json is making it to co-body as a URL-encoded string?
Its either going to be the format of the JSON that you are uploading if you are setting the Content-Type to application/json.
Otherwise, may be using the wrong Content-Type. For example if you were uploading files where the Content-Type should be multipart/form-data but you accidentally set the Content-Type to application/json when it should you would see this error.
This has tripped me up in the past.
I am using an API which is returning the wrong mime type, it's coming out as text/html rather than application/json.
Some of the responses are application/json so I know that the problem is due to mime type.
But for the text/html (which returns valid json with the wrong mime type) httparty will only parse this into a string rather than a hash.
Is there a way to parse this string into a hash?
I've tried using require 'json' but using JSON.parse comes up with an unexpected key error.
If you're extending a class with HTTParty try adding
format :json
to the class
also make sure you're parsing the body of the response and not the response object.
JSON.parse(get(self.class.get("some_url","some_params").body)
Without code or API URL I can only guess. Perhaps the API can respond in multiple ways and you need the appropriate Accept header.
class Foo
include HTTParty
headers 'Accept' => 'application/json'
end
I'm building some kind of proxy.
When I call some url in a rack application, I forward that request to an other url.
The request I forward is a POST with a file and some parameters.
I want to add more parameters.
But the file can be quite big. So I send it with Net::HTTP#body_stream instead of Net::HTTP#body.
I get my request as a Rack::Request object and I create my Net::HTTP object with that.
req = Net::HTTP::Post.new(request.path_info)
req.body_stream = request.body
req.content_type = request.content_type
req.content_length = request.content_length
http = Net::HTTP.new(#host, #port)
res = http.request(req)
I've tried several ways to add the proxy's parameters. But it seems nothing in Net::HTTP allows to add parameters to a body_stream request, only to a body one.
Is there a simpler way to proxy a rack request like that ? Or a clean way to add my parameters to my request ?
Well.. as i see it, this is a normal behaviour. I'll explain why. If you only have access to a Rack::Request,(i guess that) your middleware does not parse the response (you do not include something like ActionController::ParamsParser), so you don't have access to a hash of parameters, but to a StringIo. This StringIO corresponds to a stream like:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="param1"
value1
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
What you are trying to do with the Net::HTTP class is to: (1). parse the request into a hash of parameters; (2). merge the parameters hash with your own parameters; (3). recreate the request. The problem is that Net::HTTP library can't do (1), since it is a client library, not a server one.
Therefore, you can not escape parsing some how your request before adding the new parameters.
Possible solutions:
Insert ActionController::ParamsParser before your middleware. After that, you may use the excellent rest-client lib to do something like:
RestClient.post ('http://your_server' + request.path_info), :params => params.merge(your_params)
You can attempt to make a wrapper on the StringIO object, and add, at the end of stream,your own parameters. However, this is not trivial nor advisable.
Might be one year too late, but I had the same issue verifying Paypal IPNs. I wanted to forward back the IPN request to Paypal for verification but needed to add :cmd => '_notify-validate'.
Instead of modifying the body stream, or body, I appended it as part of the URL path, like so:
reply_request = Net::HTTP::Post.new(url.path + '?cmd=_notify-validate')
It seems a bit of a hack, but I think it's worth it if you aren't going to use it for anything else.