3

I'm using Ruby 1.9.3 and need to GET a URL. I have this working with Net::HTTP, however, if the site is down, Net::HTTP ends up hanging.

While searching the internet, I've seen many people faced similar problems, all with hacky solutions. However, many of those posts are quite old.

Requirements:

  • I'd prefer using Net::HTTP to installing a new gem.
  • I need both the Body and the Response Code. (e.g. 200)
  • I do not want to require open-uri, since that makes global changes and raises some security issues.
  • I need to GET a URL within X seconds, or return error.

Using Ruby 1.9.3, how can I GET a URL while setting a timeout?


To clarify, my existing code looks like:

Net::HTTP.get_response(URI.parse(url))

Trying to add:

Net::HTTP.open_timeout(1000)

Results in:

NoMethodError: undefined method `open_timeout' for Net::HTTP:Class
SRobertJames
  • 8,210
  • 14
  • 60
  • 107

2 Answers2

3

You can set the open_timeout attribute of the Net::HTTP object before making the connection.

uri = URI.parse(url)
Net::HTTP.new(uri.hostname, uri.port) do |http|
  http.open_timeout = 1000
  response = http.request_get(uri.request_uri)
end
Max
  • 21,123
  • 5
  • 49
  • 71
  • Max - I'm confused how to do this. I'm using the class method `get_request` on the `Net:HTTP` _class_; yet `open_timeout` is a method on `HTTPSession`. Does `open_timeout` control a global setting in some Singleton? – SRobertJames Jun 24 '14 at 16:13
  • `Net::HTTP` has a lot of confusing class methods that are basically shortcuts for creating `Net::HTTP` objects (see the source code for [`get_response`](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html#method-c-get_response)). See my edit for how to create a `Net::HTTP` object yourself. – Max Jun 24 '14 at 17:43
  • How do I get the result - the body and the http result code - using that code? – SRobertJames Jun 24 '14 at 18:19
  • Please read the documentation. `http.request_get` returns the same thing as `Net::HTTP.get_response` – Max Jun 24 '14 at 18:22
  • 2
    I tried it and `new` method does not work with blocks for me. I changed the `new` method to the `start` method and the whole thing worked normally. – Alexander.Iljushkin Oct 10 '14 at 07:37
2

I tried all the solutions here and on the other questions about this problem but I only got everything right with the following code, The open-uri gem is a wrapper for net::http. I needed a get that had to wait longer than the default timeout and read the response. The code is also simpler.

require 'open-uri'
open(url, :read_timeout => 5 * 60) do |response|
  if response.read[/Return: Ok/i]
    log "sending ok"
  else
    raise "error sending, no confirmation received"
  end
end
peter
  • 41,770
  • 5
  • 64
  • 108