Akash Panchal
Akash Panchal

Reputation: 305

How to handle timeout with net/http in ruby while sending requests to IPs from given IP range and skip IPs with timeout and move to next ones?

I want to handle timeout for IP range taken from console for which I make requests to IPs within taken range and getting timeout error. I want to make requests to all IPs and get responses from them. For IP that time out , want to skip it and move to next one. How to handle this so loop dont get exception and script sends request to all IPs that can give response handling timed out ones.

Attaching code here:

require 'net/http'
require 'uri'
require 'ipaddr'

puts "Origin IP:"
originip = gets()
(IPAddr.new("209.85.175.121")..IPAddr.new("209.85.175.150")).each do |address|
  req = Net::HTTP.get(URI.parse("http://#{address.to_s}"))
  puts req
end

Error:

C:/Ruby187/lib/ruby/1.8/net/http.rb:560:in `initialize': A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. - connect(2) (Errno::ETIMEDOUT)
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:560:in `open'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:560:in `connect'
        from C:/Ruby187/lib/ruby/1.8/timeout.rb:53:in `timeout'
        from C:/Ruby187/lib/ruby/1.8/timeout.rb:101:in `timeout'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:560:in `connect'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:553:in `do_start'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:542:in `start'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:379:in `get_response'
        from C:/Ruby187/lib/ruby/1.8/net/http.rb:356:in `get'
        from IP Range 2.rb:9
        from IP Range 2.rb:8:in `each'

Upvotes: 0

Views: 6318

Answers (2)

nkm
nkm

Reputation: 5914

Catch the exception using timeout,

require 'timeout'

(IPAddr.new("209.85.175.121")..IPAddr.new("209.85.175.150")).each do |address|
  begin
    req = Net::HTTP.get(URI.parse("http://#{address.to_s}"))
    puts req
  rescue Timeout::Error => exc
    puts "ERROR: #{exc.message}"
  rescue Errno::ETIMEDOUT => exc
    puts "ERROR: #{exc.message}"
  # uncomment the following two lines, if you are not able to track the exception type.
  #rescue Exception => exc
  #  puts "ERROR: #{exc.message}"
  end
end

Edit: When we rescue Timeout::Error, only those exceptions which belongs to Timeout::Error class will be caught. We need to catch the raised exception using their error class, updated the code accordingly.

Upvotes: 0

Jens Tinfors
Jens Tinfors

Reputation: 880

Just like Marc says. You should rescue the exception. Like so:

begin
  response = Net::HTTP.get(...)
rescue Errno::ECONNREFUSED => e
  # Do what you think needs to be done
end

Also, what you get back from the call to get() is a response, not a request.

Upvotes: 1

Related Questions