31

I have a post happening to a rails application from a ruby script. The script creates a variable request as

request = Net::HTTP::Post.new(url.path)

which is then used as follows

request.content_type = "application/json"    
request.body =  JSON.generate( params )

response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}

There is quite a lot of processing happening on the server side, and I'm getting a Net::ReadTimeout error

I tried to specify a timeout period

request.read_timeout = 500

as per this stackoverflow answer but I got a

undefined method `read_timeout=' for #<Net::HTTP::Post POST> (NoMethodError)

error. I assume that I'm missing something simple somewhere. All clues gratefully received

Technical info:

  • Ruby 2.0.0p247
  • Rails 4.0.0
  • Windows 7 32 bit ruby
Community
  • 1
  • 1
Jane
  • 1,953
  • 1
  • 20
  • 27
  • possible duplicate of [Net::HTTP get timeout in Ruby](http://stackoverflow.com/questions/19325479/nethttp-get-timeout-in-ruby) Also for `.new`, post and get should be the same. – Ciro Santilli OurBigBook.com Oct 11 '14 at 15:52
  • @CiroSantilli that question doesn't have an accepted answer. This one does, albeit my own. – Jane Oct 13 '14 at 15:45
  • possible duplicate of [Set read\_timeout for the service call in Ruby Net::HTTP.start](http://stackoverflow.com/questions/15157553/set-read-timeout-for-the-service-call-in-ruby-nethttp-start) – Brad Werth Oct 13 '14 at 19:48

5 Answers5

43

Solved via this stackoverflow answer

I've changed my

response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}

line to be

response = Net::HTTP.start(url.host, url.port, :read_timeout => 500) {|http| http.request(request)}

and this seems to have got around this problem.

Community
  • 1
  • 1
Jane
  • 1,953
  • 1
  • 20
  • 27
35

The read_timeout is available with a plain Net::HTTP object:

url = URI.parse('http://google.com')

http = Net::HTTP.new(url.host, url.port)
http.read_timeout = 5 # seconds

http.request_post(url.path, JSON.generate(params)) do |response|
  # do something with response
  p response
end
pmrotule
  • 9,065
  • 4
  • 50
  • 58
Patrick Oscity
  • 53,604
  • 17
  • 144
  • 168
1

One thing to keep in mind is that if read_timeout is set to a small value such that a timeout does occur...Net::HTTP will "helpfully" retry the request. For a slow HTTP server, a timeout error may not be raised to the code calling Net::HTTP until 2x the read_timeout value.

This certainly was not the behavior I expected.

More info on this topic and how possible solutions differ for Ruby < 2.5 and >= 2.5 may be found here:

https://stackoverflow.com/a/59186209/5299483

Lemon Cat
  • 1,002
  • 11
  • 14
1

I catch both OpenTimeout and ReadTimeout and it's work. test in Ruby:2.6.5

def ping(host, port)
    begin
        url = URI.parse("http://#{host}:#{port}/ping")
        req = Net::HTTP::Get.new(url.to_s)

        # setting both OpenTimeout and ReadTimeout
        res = Net::HTTP.start(url.host, url.port, :open_timeout => 3, :read_timeout => 3) {|http|
          http.request(req)
        }

        if JSON.parse(res.body)["ok"]
          # return true
          STDERR.puts "#{host}:#{port} is reachable"
        else
          STDERR.puts "#{host}:#{port} is NOT reachable"
        end
    rescue Net::ReadTimeout => exception
        STDERR.puts "#{host}:#{port} is NOT reachable (ReadTimeout)"
    rescue Net::OpenTimeout => exception
        STDERR.puts "#{host}:#{port} is NOT reachable (OpenTimeout)"
    end

end

ping("#{ENV['FIRST_HOST']}", 2345)
ping("#{ENV['SECOND_HOST']}", 2345)
Webb Lu
  • 328
  • 2
  • 10
-8

If anyone is still facing timeout setting issue and Net::HTTP timeout not working as expected, then you may follow below approach as well:

begin
    Timeout::timeout(10) {
        ####
        ## YOUR REQUEST CODE WILL BE HERE
        ####
    }
rescue
    408
end
Shadman
  • 755
  • 2
  • 11
  • 19
  • 8
    You should be aware that `Timeout` uses threads and you need to be aware of [the implications of that](http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/). – Eoin Kelly Oct 13 '15 at 21:26
  • 6
    Ruby’s Timeout is a giant hammer and will only lead to a big mess. Don’t use it. http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/ – AfDev Oct 19 '16 at 12:11