Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What’s the best way to handle exceptions from Net::HTTP?

Tags:

ruby

What’s the best way to rescue exceptions from Net::HTTP?

Exceptions thrown are described in Ruby’s socket.c, like Errno::ETIMEDOUT, Errno::ECONNRESET, and Errno::ECONNREFUSED. The base class to all of these is SystemCallError, but it feels weird to write code like the following because SystemCallError seems so far removed from making an HTTP call:

begin   response = Net::HTTP.get_response(uri)   response.code == "200" rescue SystemCallError   false end 

Is it just me? Is there a better way to handle this beyond fixing Net::HTTP to handle the Errno exceptions that would likely pop up and encapsulate them in a parent HttpRequestException?

like image 706
Edward Ocampo-Gooding Avatar asked Mar 20 '11 19:03

Edward Ocampo-Gooding


People also ask

How do you handle exceptions in C#?

Use a try block around the statements that might throw exceptions. Once an exception occurs in the try block, the flow of control jumps to the first associated exception handler that is present anywhere in the call stack. In C#, the catch keyword is used to define an exception handler.

Where should exceptions be handled?

You should handle the exception at the lowest possible level. If method can't handle the exception properly you should throw it.

How do you handle exceptions in API?

You can customize how Web API handles exceptions by writing an exception filter. An exception filter is executed when a controller method throws any unhandled exception that is not an HttpResponseException exception.


2 Answers

I agree it is an absolute pain to handle all the potential exceptions. Look at this to see an example:

Working with Net::HTTP can be a pain. It's got about 40 different ways to do any one task, and about 50 exceptions it can throw.

Just for the love of google, here's what I've got for the "right way" of catching any exception that Net::HTTP can throw at you:

begin   response = Net::HTTP.post_form(...) # or any Net::HTTP call rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,        Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e   ... end 

Why not just rescue Exception => e? That's a bad habit to get into, as it hides any problems in your actual code (like SyntaxErrors, whiny nils, etc). Of course, this would all be much easier if the possible errors had a common ancestor.

The issues I've been seeing in dealing with Net::HTTP have made me wonder if it wouldn't be worth it to write a new HTTP client library. One that was easier to mock out in tests, and didn't have all these ugly little facets.

What I've done, and seen most people do, is move away from Net::HTTP and move to 3rd party HTTP libraries such as:

httparty and faraday

like image 124
Mike Lewis Avatar answered Oct 14 '22 06:10

Mike Lewis


I experienced the same problem, and after a lot of research, I realized the best way to to handle all exceptions Net::HTTP methods would throw is to rescue from StandardError.

As pointed by Mike Lewis's answer, Tammer Saleh blog post proposes rescuing from a lot exceptions, but it is still flaw. There are some exceptions he does not rescue from, like Errno::EHOSTUNREACH, Errno::ECONNREFUSED, and possible some socket exceptions.

So, as I found out in tenderlove's translation of an old ruby-dev thread, the best solution is rescuing from StandardError, unfortunately:

begin   response = Net::HTTP.get_response(uri) rescue StandardError   false end 

It is awful, but if you want your system does not break because of these other exceptions, use this approach.

like image 41
Hugo Tavares Avatar answered Oct 14 '22 06:10

Hugo Tavares