Postman post request works ok but exported Ruby Don - ruby-on-rails

Post request work in Postman but the same code exported in Ruby doesn't work. It is a request
Content-Type= application/x-www-form-urlencoded with body
content-type = 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
I need to send a confirmation to payU for IDN. The request works ok if it is send from Postman but not working ok when I ran the same code from ruby. (their server's answer is "Invalid account code" which is equivalent with no parameters received by payU.)
Request makes a post requests to
https://sandbox.payu.ro/order/idn.php
with header:
Content-Type:application/x-www-form-urlencoded
with
body: multipart/form-date and the parameters:
MERCHANT=GOISTEST
ORDER_REF=304911
ORDER_AMOUNT=35.70
ORDER_CURRENCY=RON
IDN_DATE=2019-05-26 07:50:39
ORDER_HASH=b27e42645e9c52b81fab955eb7309f70
The Postman request result is
<EPAYMENT>304911|7|Order already confirmed|2019-05-26 08:57:52|5c25acc698cb607a2af3676fdbaabf7b</EPAYMENT>
If you export in Ruby and run it you get an error for Error EOF
but if you add:
http.use_ssl = true
then the request is done and response is:
"Invalid account code"
I would need the request to work in ruby!
This is the code exported by postman to Ruby:
The Postman request result is
<EPAYMENT>304911|7|Order already confirmed|2019-05-26 08:57:52|5c25acc698cb607a2af3676fdbaabf7b</EPAYMENT>
If you export in Ruby and run it you get an error for Error EOF
but if you add:
http.use_ssl = true
then the request is done and response is:
"Invalid account code"
This is the server's answer when you do not send the parameters at all!
"What more can I do? "

In the end I found out from that
http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#label-Setting+Headers
that
request["content-type"] = 'multipart/form-data; boundary=----NEW_BOUNDARY'
is not working but
request.content_type = 'multipart/form-data; boundary=----NEW_BOUNDARY'
works.
I could make finnaly the post after many hours of debugging.

Related

Error when POST ing through Ruby. Postman works fine

I have a strange issue when trying to POST to a third party website.
When testing using Postman, I get a correct response. However, when trying the same POST via Ruby code, I get a cryptic HTML response page from the website. HTTP Response code is 200. It's just that the website's internal logic throws an error, which should'nt happen if I'm sending the exact same request via code than the request I'm sending via Postman.
Url is: http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias
The POST can be generated in the browser when choosing month ("mes") and day ("dia") in the dropboxes shown in that webpage. I have also inspected the network call in this case in the browser console and can find nothing funny.
My code comes straight from the one generated by Postman. I have also tried HTTParty gem with the same error response
require 'uri'
require 'net/http'
url = URI("http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["cache-control"] = 'no-cache'
request["content-type"] = 'application/x-www-form-urlencoded'
request["postman-token"] = '3ba1963c-2874-89c2-5e4d-e5be2c13a560'
request.body = "mes=05&anho=2016"
response = http.request(request)
puts response.read_body
A correct response should show an HTML table filled with values. Instead I'm getting an HTML error page.
Any help figuring out the issue would be appreciated.
Edit: the HTML response is not really relevant, since it is a business logic error, not an HTTP error, but here it is:
The thing is: this internal logic error is being triggered because something is different when sending the POST request via code than when sending it via Postman, and I can't figure out what.
"\r\n\r\n.:: Pagina de Errores
::.\r\n\r\n\r\n\r\nBODY
{font-style:normal;font-size:10pt;font-family:Verdana,Arial,Helvetica,sans-serif;}\r\nH1
{font-size:16pt;color:Navy;}\r\nA {color:Navy;}\r\n.msg
{font-style:bold;font-size:14pt;}\r\n.error
{font-style:bold;font-size:14pt;color:Red;}\r\n.datos
{font-size:12pt;}\r\n.soluc {font-size:12pt;}\r\n\r\n\r\nLa aplicación
ha retornado el siguiente problema :\r\n\r\n\r\n\r\n\r\n\r\nAcción a realizar :\r\n\r\n\r\nPor favor intentente nuevamente
realizar la operación, si el problema persiste, avisar a
nuestro webmaster
o\r\ncomunicarse con Atenci\xF3n a Usuarios.\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n(function(){var
f5_cspm={f5_p:'NEHEKPGFEEIGMFMPAJJJKDPGKDEIIJJIDBONLBJECPDLCCOBKCPONGDHNEIJOKPPCGMBMAGEAADECGEHHJAAAPLKAANKMODHPLFBCJKHMMCPOAKONNKGFELHONBMHBIO',setCharAt:function(str,index,chr){if(index>str.length-1)return
str;return
str.substr(0,index)+chr+str.substr(index+1);},get_byte:function(str,i){var
s=(i/16)|0;i=(i&15);s=s*32;return((str.charCodeAt(i+16+s)-65)<<4)|(str.charCodeAt(i+s)-65);},set_byte:function(str,i,b){var
s=(i/16)|0;i=(i&15);s=s*32;str=f5_cspm.setCharAt(str,(i+16+s),String.fromCharCode((b>>4)+65));str=f5_cspm.setCharAt(str,(i+s),String.fromCharCode((b&15)+65));return
str;},set_latency:function(str,latency){latency=latency&0xffff;str=f5_cspm.set_byte(str,40,(latency>>8));str=f5_cspm.set_byte(str,41,(latency&0xff));str=f5_cspm.set_byte(str,35,2);return
str;},wait_perf_data:function(){try{var
wp=window.performance.timing;if(wp.loadEventEnd>0){var
res=wp.loadEventEnd-wp.navigationStart;if(res<60001){var
cookie_val=f5_cspm.set_latency(f5_cspm.f5_p,res);window.document.cookie='f5avr1032272937aaaaaaaaaaaaaaaa='+encodeURIComponent(cookie_val)+';path=/';}\nreturn;}}\ncatch(err){return;}\nsetTimeout(f5_cspm.wait_perf_data,100);return;},go:function(){var
chunk=window.document.cookie.split(/\s*;\s*/);for(var
i=0;i"
You need to probably use a GET request to get the table. The server is not responding on the POST request because it has not been configured to respond to it.
The solution is to use:
uri = URI('http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias')
request = Net::HTTP::Get.new(uri)
instead of the code with Post.new

HTTP request: 400 error

For a project I'm working on in Rails, I'm using AlchemyData news API. I'm currently trying to run an HTTP request in pry, which looks like below (I replaced my own API key with the substitute my_api_key, and for clarity, a > indicates what I've entered and => what was returned to me):
> uri = URI.parse("https://gateway-a.watsonplatform.net/calls/data/GetNews?apikey=MY_API_KEY&outputMode=json&start=now-24h&end=now&q.enriched.url.title=A[Kim^Kardashian]&q.enriched.url.docSentiment.type=positive")
=> #<URI::HTTPS https://gateway-a.watsonplatform.net/calls/data/GetNews?apikey=MY_API_KEY&outputMode=json&start=now-24h&end=now&q.enriched.url.title=A[Kim^Kardashian]&q.enriched.url.docSentiment.type=positive>
> http = Net::HTTP.new(uri.host, uri.port)
=> #<Net::HTTP gateway-a.watsonplatform.net:443 open=false>
> response = http.request(Net::HTTP::Get.new(uri.request_uri))
=> #<Net::HTTPBadRequest 400 Bad Request readbody=true>
I'm not understanding why I keep getting a "400 Bad Request" error. From my understanding, that is (usually) returned when there is an error with the url, but when I run mine it works perfectly. Is there something wrong with my syntax or is there a different error? If so, what is it? How can I fix this?
Fixed this by using an HTTP gem (https://github.com/httprb/http) and using that to handle my HTTP request, like so:
result = HTTP.get("my_url_here")

Issues sending a POST via Net::HTTP to a Battle.Net Community API End-Point (OAuth 2)

Versions:
Ruby 2.2.4
Rails 4.2
Omniauth-oauth2 1.3.1
Omniauth-bnet 1.1.0
Issue:
Trying to complete the authorization and token request process to Blizzard's Battle Net Community API. While I can get the authorization_code returned, when I attempt to construct a POST back to the token endpoint it keeps telling me that its an invalid request/internal server error or just returns back the following object: <Net::HTTPFound 302 Found readbody=true> which has a blank string for a response body. Details for how Blizzard recommends handling the OAuth 2 process are located here: Battle.net OAuth 2 Guide. The omniauth-bnet gem is the one Blizzard suggested but doesn't seem to handle the entire OAuth authorization and token process but I'll freely admit I'm brand new when it comes to anything OAuth related so I could be wrong.
Any help you all can provide would be very welcome!
Controller Code:
def index
client_id = ENV[BNET_CLIENT_ID]
client_secret = ENV[BNECT_CLIENT_SECRET]
uri = URI('https://us.battle.net/auth/token?
redirect_uri=https%3A%2F%2f127%2f0%2f0%2f1%3A3001%2Fauth%2Fbnet%2Fcallback
&grant_type=authorization_code
&code=' + params["code"])
req = Net::HTTP::Post.new(uri)
req.basic_auth(client_id, client_secret)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') {|http| http.request(req)}
#bnet_response = res.body
end
Process:
Click link on index.html page which triggers the authorization process to start by sending a GET request to https://us.battle.net/oauth/authorize?client_id=&client_secret=&redirect_uri=&response_type=code
BNet API accepts the request and redirects user to Battle.Net Login screen
User authorizes app and is redirected (via redirect_uri) back to the index page with query parameters for the authorization_code
My app SHOULD make a POST request using the controller code above and the response should contain the actual access token.
This is just some hastily cobbled together code while I'm trying to get this working. I'll clean it up once I get over this little speed bump. I wouldn't hardcode the URI and such normally, just getting frustrated with things.
Things I've tried:
Using Rest-Client : There's a callback redirect that it can't handle apparently
Testing Postman : When using their OAuth 2 Authorization it works just fine, also works fine if I use Postman to get the authorization code (GET) and token (POST), so I'm assuming things work on the Blizz side and my code just sucks.
config/routes.rb
Rails.application.routes.draw do
root to: 'pages#index'
get '/auth/:provider/callback', to: 'pages#index'
end
I'm not familiar with the Battle.net API, however reading your process it seems you are getting an authorization code back from the redirect in the form of a query parameter (accessed by params[:code]) correct?
You also mention that this works using Postman indicating the flaw must be somewhere in the code.
I would suggest using the following snippet and let me know if it works. I would encourage using puts url after url = ... code to ensure the URI looks exactly as you want it (and has the correct code, client id, secret, redirect_uri).
require 'uri'
require 'net/http'
# Remember to change the redirect uri to match yours
redirect_uri = 'https://my-domain-name.com/auth/bnet/callback'
# Double check the environment variable names for BNET ID / Secret
url = URI("https://us.battle.net/oauth/token?redirect_uri=#{redirect_uri}&code=#{params[:code]}" \
"&grant_type=authorization_code&scope=wow.profile&client_id=#{ENV['BNET_CLIENT_ID']}" \
"&client_secret=#{ENV['BNET_CLIENT_SECRET']}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body
Ensure your domain is accessible over https as this seems to be required.

YouTube API: Delete video HTTP request from Ruby not working

I am trying to delete a video on YouTube from a Ruby on Rails application. I am following these instructions, from the YouTube API docs:
DELETE /feeds/api/users/default/uploads/VIDEO_ID HTTP/1.1
Host: gdata.youtube.com
Content-Type: application/atom+xml
Authorization: Bearer ACCESS_TOKEN
GData-Version: 2
X-GData-Key: key=DEVELOPER_KEY
I am not very familiar with Ruby's Net::HTTP class, but it seems that no matter what I try I cannot get the request to work properly. I have looked carefully at the many other StackOverflow questions regarding deleting videos from YouTube, but none that I could find address this particular problem. My code is below, where I've replaced the user name, video ID, access token, and developer key.
url = URI.parse("https://gdata.youtube.com/feeds/api/users/[USER_NAME]/uploads/[VIDEO_ID]")
post_args = { 'Host' => 'gdata.youtube.com', 'GData-Version' => '2', 'Content-Type' => 'application/atom+xml', 'Authorization' => "Bearer [ACCESS_TOKEN]", 'X-GData-Key' => 'key=[DEVELOPER_KEY]' }
req = Net::HTTP::Delete.new(url.path)
req.set_form_data(post_args)
httpreq = Net::HTTP.new(url.host, url.port)
httpreq.use_ssl = true
resp = httpreq.start {|http| http.request(req) }
Checking the response, I get an Error 400 (Bad Request) from YouTube. The response simply says "Your client has issued a malformed or illegal request. That's all we know".
Is there something wrong with the request I'm making? I've checked it against the template time and time again and I can't see anything wrong with it. I know that my access token and developer key are working because I can make other requests like video uploads just fine.
I printed the debug output from the HTTP request, and as far as I can tell it looks fine:
<- "DELETE /feeds/api/users/[USER_NAME]/uploads/[VIDEO_ID] HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nContent-Type: application/x-www-form-urlencoded\r\nHost: gdata.youtube.com\r\nContent-Length: 275\r\n\r\n"
<- "Host=gdata.youtube.com&GData-Version=2&Content-Type=application%2Fatom%2Bxml&Authorization=Bearer+[ACCESS_TOKEN]&X-GData-Key=key%3D[DEVELOPER_KEY]"
The only thing I could see as a possible problem was that in the first line of the request, the "Content-Type" is set to "application/x-www-form-urlencoded". Again, not being an expert on HTTP requests I'm not sure what the difference is between the Content-Type set in the first line and the Content-Type that I explicitly set as "application/atom+xml" which appears on the second line of the request. After some digging, though, I found out that the set_form_data method automatically sets the content type as "application/x-www-form-urlencoded", so I tried adding the following line to my code:
req.content_type = 'application/atom+xml'
right after the line
req.set_form_data(post_args)
When I do this, I do see a corresponding change in the request:
<- "DELETE /feeds/api/users/[USER_ID]/uploads/[VIDEO_ID] HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nContent-Type: application/atom+xml\r\nHost: gdata.youtube.com\r\nContent-Length: 275\r\n\r\n"
<- "Host=gdata.youtube.com&GData-Version=2&Content-Type=application%2Fatom%2Bxml&Authorization=Bearer+[ACCESS_TOKEN]&X-GData-Key=key%3D[DEVELOPER_KEY]"
However, I still get the exact same response from YouTube. Error 400, bad request. What the heck is going on here??
Of course, 10 minutes after asking my question, I find out the answer. I did not understand the distinction between the HTTP header fields and form arguments, which I don't feel so bad about since it's not explained anywhere either in the Ruby documentation on Net::HTTP or in the YouTube API. The reason I was confused was because for uploading a video, you can provide all the values like Authorization and Content-Type as form data, so the above approach from my question works fine. For deleting a video, you have to provide those values as part of the header, not form data. At least, that is now my understanding.
Anyway, in case anyone ever runs into this problem, this solved it for me:
req = Net::HTTP::Delete.new(url.path)
req['GData-Version'] = '2' # this syntax sets header fields & values
req['Authorization'] = "..."
req['X-GData-Key'] = "..."
req.content_type = 'application/atom+xml'
httpreq = Net::HTTP.new(url.host, url.port)
httpreq.use_ssl = true
resp = httpreq.start {|http| http.request(req) }
Another case where one explanatory sentence from the authors of the documentation would have saved two hours of wasted time. If I had a nickel...

403 Developer Inactive on an HTTP pull

I am trying to query some XML from a hotel database using Ruby, and am getting the results:
403 Developer Inactive
I used the code:
require 'net/http'
url = URI.parse('URL of the HTTP query')
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
puts res.body
I would give the actual URL, but it contains the API key/etc...so I really cannot divulge it.
Is there anything wrong with the code or might it be on the company needing to activate the key?
Thanks
403 is the HTTP status code FORBIDDEN, which leads me to believe you have a problem authenticating your API request, maybe because of a wrong key or something.

Resources