How do I get the contents of an http request in Ruby? - ruby-on-rails

In PHP I can do this:
$request = "http://www.example.com/someData";
$response = file_get_contents($request);
How would I do the same thing in Ruby (or some Rails method?)
I've been googling for a half an hour and coming up completely short.

The standard library package open-uri is what you're after:
require 'open-uri'
contents = open('http://www.example.com') {|io| io.read}
# or
contents = URI.parse('http://www.example.com').read

require 'net/http'
Net::HTTP.get(URI.parse('http://www.example.com/index.html'))
Not sure why I didn't find this earlier. Unless there's an better way, I'm going with this!

Using the net/http library as shown:
require 'net/http'
response = Net::HTTP.get_response('mysite.com','/api/v1/messages')
p response.body

In your view try
<%= request.inspect %>

Related

Open-Uri hanging/timing out

I am trying to use open-uri with Nokogiri
class Script
require 'nokogiri'
require 'open-uri'
open("http://www.ruby-lang.org/") {|f|
f.each_line {|line| p line}
}
end
It is timing out with the following error
in `initialize': execution expired (Net::OpenTimeout)
Any idea why this is happening?
The page you try to retrieve take time-out. It could be the slow response of the server which can be adjusted like below, or the site down.
url_object = open(url, "ssl_verify_mode"=>0, "allow_redirections"=>:safe, "read_timeout"=>Max_http_timeout/1000)
Refer to the doc for more explanation: https://docs.ruby-lang.org/en/2.0.0/OpenURI/OpenRead.html

Rails/Ruby equivalent of PHP file_get_contents

Would like to know the Rails/Ruby equivalent of the following PHP:
$data = json_decode(file_get_contents(URL_GOES_HERE))
The URL is an external resource that returns json data (Facebook's API).
I've tried:
data = JSON.parse(URL_GOES_HERE)
but I assume I still need the `file_get_contents' part? How do I do this in Rails 4?
Try this
require 'open-uri'
file = open(URL_GOES_HERE)
data = JSON.parse file.read

The most super simple example to start woking with NetHTTP

In Rail my final goal is to write a Net::HTTP client to connect to my REST API that is returning JSON and parse it, pass it to View , etc....
But first things first!
What is the simplest thing I can start with?
I am looking at this page:http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
and I get the impression that if I have one .rb file with these two lines of code in it, it should show me something?
require 'net/http'
Net::HTTP.get('example.com', '/index.html')
url = URI.parse("http://example.com")
req = Net::HTTP::Get.new(url.path)
#resp = Net::HTTP.new(url.host, url.port).start {|http| http.request(req)}
in a view
<%= "The call to example.com returned this: #{#resp}" %>
You could start testing with something like this:
require 'net/http'
response = Net::HTTP.get_response("www.google.com","/")
puts response.body
I'll recommend you take a look at the docs: Net::HTTPSession

Get redirect of a URL in Ruby

According to Facebook graph API we can request a user profile picture with this (example):
https://graph.facebook.com/1489686594/picture
But the real image URL of the previous link is:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs356.snc4/41721_1489686594_527_q.jpg
If you type the first link on your browser, it will redirect you to the second link.
Is there any way to get the full URL (second link) with Ruby/Rails, by only knowing the first URL?
(This is a repeat of this question, but for Ruby)
This was already answered correctly, but there's a much simpler way:
res = Net::HTTP.get_response(URI('https://graph.facebook.com/1489686594/picture'))
res['location']
You can use Net::Http and read the Location: header from the response
require 'net/http'
require 'uri'
url = URI.parse('http://www.example.com/index.html')
res = Net::HTTP.start(url.host, url.port) {|http|
http.get('/index.html')
}
res['location']
You've got HTTPS URLs there, so you will handle that...
require 'net/http'
require 'net/https' if RUBY_VERSION < '1.9'
require 'uri'
u = URI.parse('https://graph.facebook.com/1489686594/picture')
h = Net::HTTP.new u.host, u.port
h.use_ssl = u.scheme == 'https'
head = h.start do |ua|
ua.head u.path
end
puts head['location']
I know this is an old question, but I'll add this answer for posterity:
Most of the solutions I've seen only follow a single redirect. In my case, I had to follow multiple redirects to get the actual final destination URL. I used Curl (via the Curb gem) like so:
result = Curl::Easy.perform(url) do |curl|
curl.head = true
curl.follow_location = true
end
result.last_effective_url
You can check the response status code and get the final URL recursively using something like get_final_redirect_url method:
require 'net/http'
def get_final_redirect_url(url, limit = 10)
uri = URI.parse(url)
response = ::Net::HTTP.get_response(uri)
if response.class == Net::HTTPOK
return uri
else
redirect_location = response['location']
location_uri = URI.parse(redirect_location)
if location_uri.host.nil?
redirect_location = uri.scheme + '://' + uri.host + redirect_location
end
warn "redirected to #{redirect_location}"
get_final_redirect_url(redirect_location, limit - 1)
end
end
I was facing the same issue. I solved it and built a gem final_redirect_url around it, so that everyone can benefit from it.
You can find the details on uses here.
Yeah, "Location" response header tell you the actual image URL.
However, if you use the picture as the user's profile image on your site, I recommend you to use "https://graph.facebook.com/:user_id/picture" style URL instead of actual image URL.
Otherwise, your users will see lots of "not found" images, or outdated profile images in the future.
You just put "https://graph.facebook.com/:user_id/picture" as the "src" attribute of "img" tag.
They browser gets the updated image of the user.
ps.
I have such troubles on my site with Twitter & Yahoo! OpenID now..
If you want a solution that:
does not use gems
follows all redirects
works also with url-shortening services
require 'net/http'
require 'uri'
def follow_redirections(url)
response = Net::HTTP.get_response(URI(url))
until response['location'].nil?
response = Net::HTTP.get_response(URI(response['location']))
end
response.uri.to_s
end
# EXAMPLE USAGE
follow_redirections("https://graph.facebook.com/1489686594/picture")
# => https://static.xx.fbcdn.net/rsrc.php/v3/yo/r/UlIqmHJn-SK.gif

What's the best way to use SOAP with Ruby?

A client of mine has asked me to integrate a 3rd party API into their Rails app. The only problem is that the API uses SOAP. Ruby has basically dropped SOAP in favor of REST. They provide a Java adapter that apparently works with the Java-Ruby bridge, but we'd like to keep it all in Ruby, if possible. I looked into soap4r, but it seems to have a slightly bad reputation.
So what's the best way to integrate SOAP calls into a Rails app?
I built Savon to make interacting with SOAP webservices via Ruby as easy as possible.
I'd recommend you check it out.
We used the built in soap/wsdlDriver class, which is actually SOAP4R.
It's dog slow, but really simple. The SOAP4R that you get from gems/etc is just an updated version of the same thing.
Example code:
require 'soap/wsdlDriver'
client = SOAP::WSDLDriverFactory.new( 'http://example.com/service.wsdl' ).create_rpc_driver
result = client.doStuff();
That's about it
We switched from Handsoap to Savon.
Here is a series of blog posts comparing the two client libraries.
I also recommend Savon. I spent too many hours trying to deal with Soap4R, without results. Big lack of functionality, no doc.
Savon is the answer for me.
Try SOAP4R
SOAP4R
Getting Started with SOAP4R
And I just heard about this on the Rails Envy Podcast (ep 31):
WS-Deathstar SOAP walkthrough
Just got my stuff working within 3 hours using Savon.
The Getting Started documentation on Savon's homepage was really easy to follow - and actually matched what I was seeing (not always the case)
Kent Sibilev from Datanoise had also ported the Rails ActionWebService library to Rails 2.1 (and above).
This allows you to expose your own Ruby-based SOAP services.
He even has a scaffold/test mode which allows you to test your services using a browser.
I have used HTTP call like below to call a SOAP method,
require 'net/http'
class MyHelper
def initialize(server, port, username, password)
#server = server
#port = port
#username = username
#password = password
puts "Initialised My Helper using #{#server}:#{#port} username=#{#username}"
end
def post_job(job_name)
puts "Posting job #{job_name} to update order service"
job_xml ="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"http://test.com/Test/CreateUpdateOrders/1.0\">
<soapenv:Header/>
<soapenv:Body>
<ns:CreateTestUpdateOrdersReq>
<ContractGroup>ITE2</ContractGroup>
<ProductID>topo</ProductID>
<PublicationReference>#{job_name}</PublicationReference>
</ns:CreateTestUpdateOrdersReq>
</soapenv:Body>
</soapenv:Envelope>"
#http = Net::HTTP.new(#server, #port)
puts "server: " + #server + "port : " + #port
request = Net::HTTP::Post.new(('/XISOAPAdapter/MessageServlet?/Test/CreateUpdateOrders/1.0'), initheader = {'Content-Type' => 'text/xml'})
request.basic_auth(#username, #password)
request.body = job_xml
response = #http.request(request)
puts "request was made to server " + #server
validate_response(response, "post_job_to_pega_updateorder job", '200')
end
private
def validate_response(response, operation, required_code)
if response.code != required_code
raise "#{operation} operation failed. Response was [#{response.inspect} #{response.to_hash.inspect} #{response.body}]"
end
end
end
/*
test = MyHelper.new("mysvr.test.test.com","8102","myusername","mypassword")
test.post_job("test_201601281419")
*/
Hope it helps. Cheers.
I have used SOAP in Ruby when i've had to make a fake SOAP server for my acceptance tests. I don't know if this was the best way to approach the problem, but it worked for me.
I have used Sinatra gem (I wrote about creating mocking endpoints with Sinatra here) for server and also Nokogiri for XML stuff (SOAP is working with XML).
So, for the beginning I have create two files (e.g. config.rb and responses.rb) in which I have put the predefined answers that SOAP server will return.
In config.rb I have put the WSDL file, but as a string.
##wsdl = '<wsdl:definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
.......
</wsdl:definitions>'
In responses.rb I have put samples for responses that SOAP server will return for different scenarios.
##login_failure = "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<LoginResponse xmlns="http://tempuri.org/">
<LoginResult xmlns:a="http://schemas.datacontract.org/2004/07/WEBMethodsObjects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Error>Invalid username and password</a:Error>
<a:ObjectInformation i:nil="true"/>
<a:Response>false</a:Response>
</LoginResult>
</LoginResponse>
</s:Body>
</s:Envelope>"
So now let me show you how I have actually created the server.
require 'sinatra'
require 'json'
require 'nokogiri'
require_relative 'config/config.rb'
require_relative 'config/responses.rb'
after do
# cors
headers({
"Access-Control-Allow-Origin" => "*",
"Access-Control-Allow-Methods" => "POST",
"Access-Control-Allow-Headers" => "content-type",
})
# json
content_type :json
end
#when accessing the /HaWebMethods route the server will return either the WSDL file, either and XSD (I don't know exactly how to explain this but it is a WSDL dependency)
get "/HAWebMethods/" do
case request.query_string
when 'xsd=xsd0'
status 200
body = ##xsd0
when 'wsdl'
status 200
body = ##wsdl
end
end
post '/HAWebMethods/soap' do
request_payload = request.body.read
request_payload = Nokogiri::XML request_payload
request_payload.remove_namespaces!
if request_payload.css('Body').text != ''
if request_payload.css('Login').text != ''
if request_payload.css('email').text == some username && request_payload.css('password').text == some password
status 200
body = ##login_success
else
status 200
body = ##login_failure
end
end
end
end
I hope you'll find this helpful!
I was having the same issue, switched to Savon and then just tested it on an open WSDL (I used http://www.webservicex.net/geoipservice.asmx?WSDL) and so far so good!
https://github.com/savonrb/savon

Resources