If you’ve needed the numeric HTTP status code from a connection created with either open-uri’s or rest-open-uri’s open method, you’ve probably noticed that OpenURI::HTTPError is raised on any thing other than a 2xx or 1xx status code and that the docs don’t really lay out how to get to the status code in that error. Some of you may have hacked up a the_error.to_s[0..2] solution, but that is bad and terrible. Don’t do it. Here’s the right way. (Good luck remembering it after a few weeks away, however.)
require 'open-uri' # or 'rest-open-uri'
begin
io_thing = open(some_http_uri)
# The text of the status code is in [1]
the_status = io_thing.status[0]
rescue OpenURI::HTTPError => the_error
# some clean up work goes here and then..
the_status = the_error.io.status[0] # => 3xx, 4xx, or 5xx
# the_error.message is the numeric code and text in a string
puts "Whoops got a bad status code #{the_error.message}"
end
do_something_with_status(the_status)
There you go. You’ll notice that neither open-uri nor rest-open-uri use the Net:HTTP response classes like it claims you should in these cases, but you can map to them with the numeric status codes. All you need are the CODE_CLASS_TO_OBJ and CODE_TO_OBJ hashes defined in Net::HTTPResponse. The latter hash is probably preferable.
Update: Edited for stupidity.
2 Comments
Actually, this isn’t exactly correct – open-uri and rest-open-uri swallow 301, 302, 303, and 307 status codes, follow the redirection w/o exception, and tell you they received a 200.
This is causing some breakage in rfeedparser, as I’ve detailed here:
http://rubyforge.org/tracker/index.php?func=detail&aid=13073&group_id=3309&atid=12738
Re: Jesse Newland
You can set :redirect=>false like: uri.read(:redirect=>false)
This is kinda needed to be able to handle 301 properly, since you are supposed to update your references whenever you find a permanent redirect like that. At least, this is the only decent way of achieving this that I’ve come across.
Thanks for your post Jeff!