solution de Marc-André Lafortune est toujours le meilleur si vous ne pouvez pas mettre à ruby 2.x.
A partir de 2.x, une sous-classe de Timeout::Error
ressusciteront en fonction du délai d'attente a été déclenchée:
Net::OpenTimeout
Net::ReadTimeout
Cependant, le comportement est étrange read_timeout
sur 2 .x, car il semble doubler la valeur que vous définissez.
Voici un test pour les deux délais (testé sur 1.8.7, 1.9.3, 2.1.2, 2.2.4).
EDIT: Le test open_timeout fonctionne sur Mac, mais sur Linux, le client reçoit une erreur "connection refused".
require "net/http"
require "socket"
SERVER_HOST = '127.0.0.1'
SERVER_PORT = 9999
def main
puts 'with_nonlistening_server'
with_nonlistening_server do
make_request
end
puts
puts 'with_listening_server'
with_listening_server do
make_request
end
end
def with_listening_server
# This automatically starts listening
serv = TCPServer.new(SERVER_HOST, SERVER_PORT)
begin
yield
ensure
serv.close
end
end
def with_nonlistening_server
raw_serv = Socket.new Socket::AF_INET, Socket::SOCK_STREAM, 0
addr = Socket.pack_sockaddr_in SERVER_PORT, SERVER_HOST
# Bind, but don't listen
raw_serv.bind addr
begin
yield
ensure
raw_serv.close
end
end
def make_request
http = Net::HTTP.new(SERVER_HOST, SERVER_PORT)
http.open_timeout = 1
http.read_timeout = 1 # seems to be doubled on ruby 2.x
start_tm = Time.now
begin
http.start
begin
http.get('/')
rescue Timeout::Error => err
puts "Read timeout: #{err.inspect}"
end
rescue Timeout::Error => err
puts "Open timeout: #{err.inspect}"
end
end_tm = Time.now
puts "Duration (sec): #{end_tm - start_tm}"
end
if __FILE__ == $PROGRAM_NAME
main
end
Exemple de sortie sur 1.9.3:
with_nonlistening_server
Open timeout: #<Timeout::Error: execution expired>
Duration (sec): 1.002477
with_listening_server
Read timeout: #<Timeout::Error: Timeout::Error>
Duration (sec): 1.00599
Exemple de sortie sur 2.1.2:
with_nonlistening_server
Open timeout: #<Net::OpenTimeout: execution expired>
Duration (sec): 1.005923
with_listening_server
Read timeout: #<Net::ReadTimeout: Net::ReadTimeout>
Duration (sec): 2.009582
Marc, je veux vraiment que cela soit vrai, mais cela ne fonctionne pas pour moi . Je pense que c'est parce que 'http.request_get' crée et utilise une nouvelle instance de' Net :: HTTP' qui n'hérite pas des variables de délai. –
Je le reprends, il ne crée pas une nouvelle instance de 'Net: HTTP'. Cependant, il semble que le délai d'attente soit d'environ 30 secondes, peu importe ce que je définis les délais d'attente d'ouverture et de lecture. –
open_timeout fonctionne pour moi, sur ruby 1.8.7 et 1.9.2 dev. Il est plus difficile de tester read_timeout, et il se peut que ce soit par bloc de lecture, vous devriez vérifier le code. Pourtant, si vous mettez les deux à 0,1, il devrait expirer rapidement, non? En tout cas, ma réponse est toujours la façon valide de distinguer ce qui a causé le délai! –