Adding timeout to Net::HTTP.get_response

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 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’s 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://www.opensourceconnections.com/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.

Leave a Reply