Blog

Adding timeout to Net::HTTP.get_response

One of the parts of Ruby that shows 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 = 5http.open_timeout = 5resp = http.start() {|http|http.get(url.path)}puts resp.kind_of? Net::HTTPResponseputs resp.codeputs 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!

Update 7/22/2018:

Thanks Cameron for your nice email. Re-reading this blog post reminded me about a fix to an AngularJS app that had very long timeouts making the app slow!