How to get the status after sending data to external server rails - ruby-on-rails

In my rails (3.2.13) app I send data to an external server using a form, then the external server process the data I sent and shows that the result is ok or not, I need to save that result or status to my rails app database, but I'm not sure about how to redirect to another page when the process in the external server is done.
I have a function to ask the server if the process of that data went ok using the reference or id that I sent in the first place using the form but as I said I don't know how to redirect after the process is finish...
please help me

You can use some core Ruby libraries to make a subsequent request on the same endpoint to determine the status code of your request. Try the following, cited in whole from Ruby Inside:
# Basic REST.
# Most REST APIs will set semantic values in response.body and response.code.
require "net/http"
http = Net::HTTP.new("api.restsite.com")
request = Net::HTTP::Post.new("/users")
request.set_form_data({"users[login]" => "quentin"})
response = http.request(request)
# Use nokogiri, hpricot, etc to parse response.body.
request = Net::HTTP::Get.new("/users/1")
response = http.request(request)
# As with POST, the data is in response.body.
request = Net::HTTP::Put.new("/users/1")
request.set_form_data({"users[login]" => "changed"})
response = http.request(request)
request = Net::HTTP::Delete.new("/users/1")
response = http.request(request)
Once you've instantiated a response object, you can operate on it in the following manner:
response.code #=> returns HTTP response code

Related

rails http request with file on body

I am using trello api to attach an image to a card. the documentation says
require 'uri'
require 'net/http'
url = URI("https://api.trello.com/1/cards/id/attachments")
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
After putting my key and my token, I tried to upload a file and the binary data goes in the url itself, not only it seems too ugly but it also doesn't work because the request is really too long. I've tried using multipart and rest client gems from in my code to upload and attach a file to a trello card but everytime I get errors like bad request or SSL errors, can anyone please give me a piece of code that really works? thanks
actually I am sending the image data via AJAX (I'm generating it from a charjs view), so the data sent is binary, it would be better if the solution upload an image from binary data.
Their documentation does indeed encourage you to add the whole encoded file object into the URL, which I also find ugly. I wonder if it will work to add it into the POST body instead? Try this:
request = Net::HTTP::Post.new(url)
request.set_form_data({file: put_encoded_file_contents_here})

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

Query server with PUT method

I will replace my command line
`curl -XPUT 'host:port/url' -d '{"val": "some_json"}'̀
by a Rails command, and get the result...
Somewhere like this :
response = call('put', 'host:port/url', '{"val" : "some_json"}')
Is there any predefined method to do this in Rails, or some gem ?
I know the command get of HTTP, but I will do a 'PUT' method.
Net::HTTP.get(URI.parse('host:port/url'))
Thanks for your replies
You can use Net::HTTP to send any standard http requests.
Here is a way, you can connect to any url ( http / https ), with any valid http methods with or without parameters.
def universal_connector(api_url, api_parameters={}, method="Get")
# Do raise Error, if url is invalid and Method is invalid
uri = URI(api_url)
req = eval("Net::HTTP::#{method.capitalize}.new('#{uri}')")
req.set_form_data(api_parameters)
Net::HTTP.start(uri.host, uri.port,:use_ssl => uri.scheme == 'https') do |http|
response = http.request(req)
return response.body
end
end
There are many alternatives available as well. Specifically, Faraday. Also, read this before making a choice.
#get is just a simple shortcut for the whole code (Net::HTTP Ruby library tends to be very verbose). However, Net::HTTP perfectly supports PUT requests.
Another alternative is to use an HTTP client as a wrapper. The most common alternatives are HTTParty and Faraday.
HTTParty.put('host:port/url', { body: {"val" : "some_json"} })
As a side note, please keep in mind that Rails is a framework, not a programming language. Your question is about how to perform an HTTP PUT request in Ruby, not Rails. It's important to understand the difference.

Trouble handling HTTP responses and parsing JSON data

I am using Ruby on Rails 3 and I would like to solve an issue with the following code where a web client application receive back some JSON data from a web service application that uses a Rack middleware in order to respond.
In the web client app model I have
response_parsed = JSON.parse(response.body)
if response_parsed["account"]
...
else
return response
end
In the above code the response.body come back from the web service app that uses a Rack middleware to respond to the web client:
accounts = Account.where(:id => ids)
[200, {'Content-Type' => 'application/json'}, accounts.to_json] # That is, response.body = accounts.to_json
Data transmission is ok, but I get the following error
TypeError
can't convert String into Integer
*Application Trace*
lib/accounts.rb:107:in `[]'
The line 107 corresponds to
if response_parsed["account"]
...
Where and what is the problem? How to solve that?
If I try to debug the respons.body I get
# Note: this is an array!
"[{\"account\":{\"firstname\":\"Semio\",\"lastname\":\"Iaven\"\"}}]"
If I'm saying something you already realize, forgive me.
It looks like your response is a one-element array with a hash in it as the first element. Because the response is an array, when you use the [] it is expecting a integer representing the index of the item in the array you'd like to access, and that is what the error message means--it expected that you'd tell it the integer value of the item you wanted, but instead you gave it a string.
If you instead do:
response_parsed[0]['account']
It seems like you'd get what you want.

Google Geocoding API request_denied

I am trying to geocode a batch of around 400 addresses using the Google Geocoding API through my rails app.
In one of my controllers I have these lines
require "net/http"
require "uri"
uri = URI.parse("http://maps.googleapis.com/maps/api/geocode/json?")
response = Net::HTTP.post_form(uri, {"address" => '5032-forbes-ave', 'sensor' => 'false'})
But I always get back ""status": "REQUEST_DENIED" from that.
Does anyone know why I am getting this, or if there is a way I can see exactly the HTTP request that is being sent so I can try to debug it?
Update: This is the request that I am trying to make, if I do this from my browser I get a normal response from the api: http://maps.googleapis.com/maps/api/geocode/json?address=5032-forbes-ave&sensor=false
You are POSTing the request but in your browser you are using GET.
So this work perfectly:
uri = URI.parse("http://maps.googleapis.com/maps/api/geocode/json?address=5032-forbes-ave&sensor=false")
response = Net::HTTP.get(uri)
The response is String itself and it contains some JSON (I'm not Google API's expert)

Resources