14

I am using RestClient to make a network call in the ruby class. I am getting a SocketError whenever I am not connected to the internet. I have added a rescue block to catch the exception still I am not able to do so.

the error message is: SocketError (Failed to open TCP connection to api.something.com:443 (getaddrinfo: Name or service not known))

module MyProject
  class Client
    def get_object(url, params={})
      response = RestClient.get(url, {params: params})
    rescue SocketError => e
      puts "In Socket errror"
    rescue => e
      puts (e.class.inspect)
    end
  end
end

The broad rescue gets called and print SocketError, but why the previous rescue SocketError is not triggered!

Do you see something that I am missing?

aks
  • 8,796
  • 11
  • 50
  • 78
  • I think rest client is also handling the exception and passing to us, original exception was SocketError – Vishal G Nov 24 '16 at 06:33
  • 1
    Have a look at this https://github.com/rest-client/rest-client/blob/master/lib/restclient/exceptions.rb#L103 – Vishal G Nov 24 '16 at 06:37
  • @WishZone In their docs they say that they do not handle few errors including `SocketError`, still if they are doing, do we have a way to catch them? I am also adding the backtrace above. – aks Nov 24 '16 at 06:43
  • Yes just seen that they are passing this exception to us as it is , I think your code should work if not then you have to go for Exception => e That is daddy class of all execptions – Vishal G Nov 24 '16 at 06:49
  • 1
    The same happens to me, not when my internet connection is disabled, but for a typo in the url - on purpose during testing. I mistyped some.url.de as some.url.der during testing - any non-existing url in a nested resource will bring up a SocketError for me, a non-existing page for an existing url will give a normal 404, that I can catch with rest-client. To catch the resulting exception, I tried to go up thru rest-client exceptions inheritances to the top (from RestClient::RequestFailed to RuntimeError class), not one of them catches SocketError. Maybe that helps a bit to find a solution? – AOphagen Feb 01 '17 at 17:02
  • Could it be a module namespacing issue? Could you try `::SocketError` maybe, in case `SocketError` is also defined somewhere in your `MyProject` module? – Keith Bennett Dec 11 '17 at 06:15
  • This is a bug in ruby. – nroose May 17 '20 at 05:20

1 Answers1

9

There are a couple of exceptions you'll need to rescue in case you want to fail gracefully.

require 'rest-client'
def get_object(url, params={})
  response = RestClient.get(url, {params: params})
rescue RestClient::ResourceNotFound => e
  p e.class
rescue SocketError => e
  p e.class
rescue Errno::ECONNREFUSED => e
  p e.class
end

get_object('https://www.google.com/missing')
get_object('https://dasdkajsdlaadsasd.com')
get_object('dasdkajsdlaadsasd.com')
get_object('invalid')
get_object('127.0.0.1')

Because you can have problems regarding the uri being a 404 destination, or be a domain that doesn't existing, an IP, and so on.

As you can see above, you can have different scenarios that you may encounter when dealing with connecting to a remote uri. The code above rescue from the most common scenarios.

The first one the URL is missing, which is handled by RestClient itself.

The the following three below are invalid domains, which will fail with SocketError (basically a DNS error in this case).

Finally in the last call we try to connect to an IP that has no server running on it - therefore it throws an ERRNO::ECONNREFUSED

Jonathan Duarte
  • 753
  • 5
  • 9
  • 1
    This is information that is vaguely related but does not even attempt to address the very clear specific question. – nroose May 17 '20 at 05:22