Adding timeout to Net::HTTP.get_response

Eric PughApril 24, 2008

One of the parts of Ruby that show’s the languages lack of maturity is the Net::HTTP module. There are a lot of magic techniques that people have learned to make it work, and some methods work one way, and others differently. For example, if you want to put a timeout on a GET request (which you SHOULD have!), then you have to use two different techniques for Net::HTTP.get and Net::HTTP.get_response. The difference between these two methods is that get_response is a class method that returns an Net::HTTPResponse object while get is an instance method that returns a string. And get_response doesn’t support passing in timeouts of any kind!

ARGH. Apparently no one has really tried to put a timeout on get_response because the only post I could find was this one. And the code just looked very complex and more hackish then I liked. In the solution I came up with, I am looking for favicon files at various websites. And if a website doesn’t actually exist (due to bad data!) then it can take ~160 seconds to timeout!

require 'net/http'
require 'uri'

url = URI.parse("http://SOMESITE/favicon.ico")

# url = URI.parse('http://www.medicalrobotics.com')

http = Net::HTTP.new(url.host, url.port)

http.read_timeout = 5
http.open_timeout = 5
resp = http.start() {|http|
http.get(url.path)
}
puts resp.kind_of? Net::HTTPResponse
puts resp.code
puts resp.body

By wrapping my call to http.get in an http.start{} block, I get the timeout ability of http.get with the return of an HTTPResponse that Net::HTTP.get_response normally provides.

Update 1/22/2015:

I’ve now received two emails from different folks thanking me for this blog post in the past 12 months. That makes me a very happy blogger!




More blog articles:


Let's do a project together!

We provide tailored search, discovery and analytics solutions using Solr and Elasticsearch. Learn more about our service offerings