* lib/net/http.rb: Retry HTTP requests for additional network errors.

Introduce OpenTimeout subclass of Timeout::Error.  [Bug #6001]
	* test/net/http/test_http.rb:  Reduce timeout to 0.01s for faster test
	* test/net/http/test_https.rb:  ditto


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2012-02-28 04:51:37 +00:00
parent 1c85a648fe
commit 8a7da58c0f
4 changed files with 35 additions and 20 deletions

View File

@ -1,3 +1,10 @@
Tue Feb 28 13:51:12 2012 Eric Hodel <drbrain@segment7.net>
* lib/net/http.rb: Retry HTTP requests for additional network errors.
Introduce OpenTimeout subclass of Timeout::Error. [Bug #6001]
* test/net/http/test_http.rb: Reduce timeout to 0.01s for faster test
* test/net/http/test_https.rb: ditto
Tue Feb 28 11:44:49 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> Tue Feb 28 11:44:49 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* configure.in (debugflags): check if -ggdb is accepted. * configure.in (debugflags): check if -ggdb is accepted.

View File

@ -360,6 +360,9 @@ module Net #:nodoc:
# #
class HTTP < Protocol class HTTP < Protocol
class OpenTimeout < Timeout::Error
end
# :stopdoc: # :stopdoc:
Revision = %q$Revision$.split[1] Revision = %q$Revision$.split[1]
HTTPVersion = '1.1' HTTPVersion = '1.1'
@ -788,7 +791,9 @@ module Net #:nodoc:
def connect def connect
D "opening connection to #{conn_address()}..." D "opening connection to #{conn_address()}..."
s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) } s = timeout(@open_timeout, OpenTimeout) {
TCPSocket.open(conn_address(), conn_port())
}
D "opened" D "opened"
if use_ssl? if use_ssl?
ssl_parameters = Hash.new ssl_parameters = Hash.new
@ -824,7 +829,7 @@ module Net #:nodoc:
end end
# Server Name Indication (SNI) RFC 3546 # Server Name Indication (SNI) RFC 3546
s.hostname = @address if s.respond_to? :hostname= s.hostname = @address if s.respond_to? :hostname=
timeout(@open_timeout) { s.connect } timeout(@open_timeout, OpenTimeout) { s.connect }
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
s.post_connection_check(@address) s.post_connection_check(@address)
end end
@ -1355,9 +1360,11 @@ module Net #:nodoc:
} }
res res
} }
end_transport req, res rescue IOError, EOFError,
res Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE,
rescue EOFError, Errno::ECONNRESET => exception OpenSSL::SSL::SSLError, Timeout::Error => exception
raise if OpenTimeout === exception
if count == 0 && IDEMPOTENT_METHODS_.include?(req.method) if count == 0 && IDEMPOTENT_METHODS_.include?(req.method)
count += 1 count += 1
@socket.close if @socket and not @socket.closed? @socket.close if @socket and not @socket.closed?
@ -1367,12 +1374,15 @@ module Net #:nodoc:
D "Conn close because of error #{exception}" D "Conn close because of error #{exception}"
@socket.close if @socket and not @socket.closed? @socket.close if @socket and not @socket.closed?
raise raise
end
end_transport req, res
res
rescue => exception rescue => exception
D "Conn close because of error #{exception}" D "Conn close because of error #{exception}"
@socket.close if @socket and not @socket.closed? @socket.close if @socket and not @socket.closed?
raise exception raise exception
end end
end
def begin_transport(req) def begin_transport(req)
if @socket.closed? if @socket.closed?

View File

@ -195,13 +195,13 @@ module TestNetHTTP_version_1_1_methods
def test_timeout_during_HTTP_session def test_timeout_during_HTTP_session
bug4246 = "expected the HTTP session to have timed out but have not. c.f. [ruby-core:34203]" bug4246 = "expected the HTTP session to have timed out but have not. c.f. [ruby-core:34203]"
# listen for connections... but deliberately do not complete SSL handshake # listen for connections... but deliberately do not read
TCPServer.open('localhost', 0) {|server| TCPServer.open('localhost', 0) {|server|
port = server.addr[1] port = server.addr[1]
conn = Net::HTTP.new('localhost', port) conn = Net::HTTP.new('localhost', port)
conn.read_timeout = 1 conn.read_timeout = 0.01
conn.open_timeout = 1 conn.open_timeout = 0.01
th = Thread.new do th = Thread.new do
assert_raise(Timeout::Error) { assert_raise(Timeout::Error) {
@ -598,21 +598,19 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase
assert_kind_of Net::HTTPResponse, res assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body assert_kind_of String, res.body
sleep 1.5 sleep 1.5
assert_nothing_raised {
res = http.get('/') res = http.get('/')
}
assert_kind_of Net::HTTPResponse, res assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body assert_kind_of String, res.body
} }
end end
def test_keep_alive_EOF def test_keep_alive_server_close
def @server.run(sock) def @server.run(sock)
sock.close sock.close
end end
start {|http| start {|http|
assert_raises(EOFError,Errno::ECONNRESET) { assert_raises(EOFError, Errno::ECONNRESET, IOError) {
res = http.get('/') res = http.get('/')
} }
} }

View File

@ -115,11 +115,11 @@ class TestNetHTTPS < Test::Unit::TestCase
conn = Net::HTTP.new('localhost', port) conn = Net::HTTP.new('localhost', port)
conn.use_ssl = true conn.use_ssl = true
conn.read_timeout = 1 conn.read_timeout = 0.01
conn.open_timeout = 1 conn.open_timeout = 0.01
th = Thread.new do th = Thread.new do
assert_raise(Timeout::Error) { assert_raise(Net::HTTP::OpenTimeout) {
conn.get('/') conn.get('/')
} }
end end