Rails: How to get the servers response HTTP headers? - ruby-on-rails

I want to autodetect the pingback-url of remote websites, so I need to parse the HTTP response headers sent by the remote server. I don't need and don't want the contents of the remote website, I'm only looking for something like this:
X-Pingback: http://www.techcrunch.com/xmlrpc.php
Similar to using curl:
curl -I "your url"
Is there a way to do this with rails? When using open-uri I can only get the contents but not the headers.
Thank you!
Ole

This is not a Rails specific question, but it can be solved with the core Ruby API.
require 'net/http'
url = URI.parse('http://www.google.ca/')
req = Net::HTTP::Head.new(url.path)
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
puts res['X-Pingback']
> "http://www.techcrunch.com/xmlrpc.php"

If you don't mind using a gem, you might try Patron, which is a ruby wrapper for the libcurl library. Usage might look something like this:
sess = Patron::Session.new
sess.timeout = 10
sess.base_url = "http://myserver.com:9900"
resp = sess.get( "your url" )
headers = resp.headers

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

Ruby Net::HTTP using SSL

I have a very simple API, that I would like to make a POST to using ruby and NOT using a GEM just the built in libraries net/http, uri, and openssl if needed.
Anyway, I am using the code below to make a very simple POST request but am getting some VERY strange results and was hoping someone else has seen this.
I have also tested the same request below in POSTMAN and NodeJS and BOTH work as expected, the only one I can not get to work is Ruby.
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://somesite.dev/devices")
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)
request["key"] = '1234567'
response = http.request(request)
puts response.read_body
The result is something I have not seen before: I am getting the header key twice... So the log to the API shows a query like this:
SELECT * FROM device where key = '1234567, 1234567' LIMIT ...
As stated above I can make the same request via POSTMAN or NodeJS and get the correct result.
NOTE: Because I have a local copy of the API I can test locally BUT it's not SSL it's all over http. When making the request locally it works just fine. So from what I can tell this issue only presents it self when SSL is introduced.
Any help would be amazing! Thanks!!
Ruby Version 2.2.1
The issue was with something I did not list in my initial question. The API was using AWS API Gateway, and HTTP_PROXY was enabled on the method causing this strange issue. After I removed HTTP_PROXY the issue cleared up and the above code worked!

Send JSON data as post method from rails controller to a web service

I am trying to send some json data from my controller written in rails to a java webservice.
On form submission i take all the input fields data do some procession on it and convert it into json object using to_json.
But how can i send it to java webservice
http://localhost:8080/exim/jsonToMapService?jsonData={"key":"value"}
You can use net/http. (as #Pierre wrote, you should create a class in lib folder, and put there your function)
url = URI.parse(service_url)
headers = {"host" => URL }
req = Net::HTTP::Post.new(url.path)
req["Content-Type"] = "application/json"
req["Accept"] = "application/json"
req.body = JSON.generate(some_data)
con = Net::HTTP.new(url.host, url.port)
# ssl for https
if full_url.include?("https")
con.use_ssl = true
con.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
res = con.start {|http| http.request(req) }
To do things like this I suggest using either RestClient or Faraday. Howeve I strongly suggest not doing the HTTP call in your controller.
Using RestClient, it would look like this:
RestClient.get('http://localhost:8080/exim/jsonToMapService', { key: :value })
You should create a class to extract this logic in the lib folder for example.
As #eightbitraptor mentioned it, when performing HTTP request like above, you should avoid blocking by performing them in a background process like Delayed Job, Resque or Sideqik.

Setting outgoing IP address in open-uri with RoR

I'm new to open-uri and trying to set an outgoing IP address using open-uri in ruby on rails. I used this post as a reference to get started. I'm porting an app from PHP where I could use CURLOPT_INTERFACE in curl_setopt. What's the best way to do this using open-uri in rails? (Doing this from the controller - not command line.)
If there's not a way to do this - any suggestions on an alternative to open-uri? My goal is to take in and parse JSON data.
What I understand from your questions is you want to hit another server from a specific IP which suggests you have a server with couple of addresses.
What I can suggest you is try to execute curl directly and do what you want to do or use a wrapper for it.
Doesn't look like open-uri can do this. But with net/https it's fairly easy.
require 'net/https'
require 'json'
uri = URI('https://jsonvat.com/')
http = Net::HTTP.new(uri.host, uri.port)
http.local_host = '1.2.3.4'
http.use_ssl = true
request = Net::HTTP::Get.new('/')
request.content_type = 'application/json'
request.initialize_http_header('Content-Type' => 'application/json')
response = http.request(request)
json = JSON.parse(response.body)
Probably you don't need the "require" lines inside Rails Controllers.
You can specify the outgoing IP address with the http.local_host line.
https://stackoverflow.com/a/24896074/1371731
https://yukimotopress.github.io/http

Using Ruby on Rails to POST JSON/XML data to a web service

I built a web service in using Spring framework in Java and have it run on a tc server on localhost. I tested the web service using curl and it works. In other words, this curl command will post a new transaction to the web service.
curl -X POST -H 'Accept:application/json' -H 'Content-Type: application/json' http://localhost:8080/BarcodePayment/transactions/ --data '{"id":5,"amount":5.0,"paid":true}'
Now, I am building a web app using RoR and would like to do something similar. How can I build that? Basically, the RoR web app will be a client that posts to the web service.
Searching SO and the web, I found some helpful links but I cannot get it to work. For example, from this post, he/she uses net/http.
I tried but it doesn't work. In my controller, I have
require 'net/http'
require "uri"
def post_webservice
#transaction = Transaction.find(params[:id])
#transaction.update_attribute(:checkout_started, true);
# do a post service to localhost:8080/BarcodePayment/transactions
# use net/http
url = URI.parse('http://localhost:8080/BarcodePayment/transactions/')
response = Net::HTTP::Post.new(url_path)
request.content_type = 'application/json'
request.body = '{"id":5,"amount":5.0,"paid":true}'
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request) }
assert_equal '201 Created', response.get_fields('Status')[0]
end
It returns with error:
undefined local variable or method `url_path' for #<TransactionsController:0x0000010287ed28>
The sample code I am using is from here
I am not attached to net/http and I don't mind using other tools as long as I can accomplish the same task easily.
Thanks much!
url = URI.parse('http://localhost:8080/BarcodePayment/transactions/')
response = Net::HTTP::Post.new(url_path)
Your problem is exactly what the interpreter told you it is: url_path is undeclared. what you want is to call the #path method on the url variable you declared in the previous line.
url = URI.parse('http://localhost:8080/BarcodePayment/transactions/')
response = Net::HTTP::Post.new(url.path)
should work.

Resources