1

So, I am creating a script that checks the health check of a tool, and the first thing the script does is check if it can actually reach the URL specified or not in the first place (by check the HTTP code). I'm having a problem where if the URL is invalid it causes SocketError - getaddrinfo: nodename nor servname provided, or not known which throws an Internal Server error (500) (which is understandable)..

But instead of that, I would like to handle that error and instead return a custom "error" to the user.

I've been googling a solution for this for quite some time before posting this and I cannot find anything useful to my problem. :/

My script is using Sinatra and this is the main part that has to do with this issue:

def check_status(uri_str, is_verbose, limit = 10)
    response = RestClient.get "#{uri_str}" # This is line 35

    case response.code
        when 200...300
            @@services.each do |service|
                if service.is_matched?("#{uri_str}")
        @@tool_name = service.class.name.split('::').last.downcase
                    puts "This is the URL inside the 'if 
                    @@result = service.check_tool_specific("#{uri_str}", "#{verbose(is_verbose)}")
      end
            end

            if @@result.nil?
                return 'No results, something went wrong!'
            end

    return "{\"#{@@tool_name}\":{\"timestamp\":\"#{Time.now.strftime('%Y-%m-%d %T')}\",\"results\":#{@@result.to_json}}}"

  when Net::HTTPRedirection then
    puts "Response code in Net::HTTPRedirection: #{response.code}"
            location = response['location']
            check_status(location, limit - 1)
        else
            puts "It doesn't work!"
            puts "#{response.code}"
  end
end

Currently this is the error that I receive in console if the URL is invalid:

2016-10-11 15:46:32 - SocketError - getaddrinfo: nodename nor servname provided, or not known:
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `initialize'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `open'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `block in connect'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:878:in `connect'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:852:in `start'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rest-client-2.0.0/lib/restclient/request.rb:766:in `transmit'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rest-client-2.0.0/lib/restclient/request.rb:215:in `execute'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rest-client-2.0.0/lib/restclient/request.rb:52:in `execute'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rest-client-2.0.0/lib/restclient.rb:67:in `get'
    /Users/farahfa/temp/ruby-devtools-hc/devtools-hc.rb:35:in `check_status'
    /Users/farahfa/temp/ruby-devtools-hc/devtools-hc.rb:22:in `block in <class:DevMonit>'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1611:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1611:in `block in compile!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:in `[]'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:in `block (3 levels) in route!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:994:in `route_eval'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:in `block (2 levels) in route!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1015:in `block in process_route'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1013:in `catch'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1013:in `process_route'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:973:in `block in route!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:972:in `each'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:972:in `route!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1085:in `block in dispatch!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `block in invoke'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `catch'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `invoke'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1082:in `dispatch!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:907:in `block in call!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `block in invoke'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `catch'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in `invoke'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:907:in `call!'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:895:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb:16:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/nulllogger.rb:9:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/show_exceptions.rb:25:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:182:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:2013:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `block in call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1787:in `synchronize'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/tempfile_reaper.rb:15:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/lint.rb:49:in `_call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/lint.rb:37:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/showexceptions.rb:24:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/commonlogger.rb:33:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/sinatra-1.4.7/lib/sinatra/base.rb:219:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/chunked.rb:54:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/content_length.rb:15:in `call'
    /Users/farahfa/.rvm/gems/ruby-2.2.2@global/gems/rack-1.6.4/lib/rack/handler/webrick.rb:88:in `service'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:94:in `run'
    /Users/farahfa/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/webrick/server.rb:294:in `block in start_thread'

NOTE: Line 22 is just: check_status(url, is_verbose) which calls the function.

Any help and/or guidance is much appreciated!

Fadi
  • 1,329
  • 7
  • 22
  • 40
  • 1
    add `rescue SocketError => e; #do something with e.message` before `end` in your method and that should do, the `#do something with e.message` should be replaced with your logic to return something sensible to the user also read handling exceptions in ruby http://rubylearning.com/satishtalim/ruby_exceptions.html – bjhaid Oct 11 '16 at 20:01
  • Ah, didn't think about that.. Does SocketError return any kind of HTTP code? My idea was if my script can't reach the URL then it'll return the HTTP code in a JSON object, can this be done in this case? – Fadi Oct 11 '16 at 20:15
  • 1
    that error means it can't resolve the hostname, so it never left the client there's no HTTP code to return – bjhaid Oct 11 '16 at 20:15
  • Ah! That makes sense. – Fadi Oct 11 '16 at 20:19

1 Answers1

0

Since you are using version 2 of RestClient, The recommended way is to add rescue RestClient::ExceptionWithResponse => e #do something with e.response before end in your method.

You can see the full list of all exceptions that RestClient can raise here: https://github.com/rest-client/rest-client#exceptions-see-httpwwww3orgprotocolsrfc2616rfc2616-sec10html .

I would suggest to try and catch them all :)

Rada Bogdan
  • 342
  • 3
  • 9
  • This results in `ArgumentError - wrong number of arguments (0 for 1..2)` – Fadi Oct 11 '16 at 20:31
  • Edited answer. I was referring to the recommended way to add a rescue clause at the end of the method. And possible rescuing other exceptions if needed, you can check the other exceptions in the link from the answer. – Rada Bogdan Oct 13 '16 at 07:39