1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/net/http.rb (Net::HTTP#transport_request): retry a idempotent

request automatically. [ruby-dev:45030] [Bug #5790]
  [ruby-core:41821] [Bug #5813]

* lib/net/http.rb (Net::HTTP#keep_alive_timeout=): added to specify
  the second to reconnect the TCP connection on Keep-Alive.
  The default value is 2 second because current servers uses 2 sec.
  http://ftp-admin.blogspot.com/2009/09/keepalivetimeout2.html

* lib/net/http.rb (Net::HTTP#begin_transport): reconnect TCP
  connection on keep-alive timeout.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34341 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2012-01-20 05:56:35 +00:00
parent 87daaf61b9
commit bee7ccddd2
4 changed files with 90 additions and 2 deletions

View file

@ -1,3 +1,17 @@
Fri Jan 20 14:31:43 2012 NARUSE, Yui <naruse@ruby-lang.org>
* lib/net/http.rb (Net::HTTP#transport_request): retry a idempotent
request automatically. [ruby-dev:45030] [Bug #5790]
[ruby-core:41821] [Bug #5813]
* lib/net/http.rb (Net::HTTP#keep_alive_timeout=): added to specify
the second to reconnect the TCP connection on Keep-Alive.
The default value is 2 second because current servers uses 2 sec.
http://ftp-admin.blogspot.com/2009/09/keepalivetimeout2.html
* lib/net/http.rb (Net::HTTP#begin_transport): reconnect TCP
connection on keep-alive timeout.
Thu Jan 19 07:53:09 2012 Tadayoshi Funaba <tadf@dotrb.org>
* ext/date/date_strptime.c: moved detector of leftover.

View file

@ -578,7 +578,8 @@ module Net #:nodoc:
@address = address
@port = (port || HTTP.default_port)
@curr_http_version = HTTPVersion
@no_keepalive_server = false
@keep_alive_timeout = 2
@last_communicated = nil
@close_on_empty_response = false
@socket = nil
@started = false
@ -648,6 +649,12 @@ module Net #:nodoc:
@continue_timeout = sec
end
# Seconds to reuse the connection of the previous request.
# If the idle time is less than this Keep-Alive Timeout,
# Net::HTTP reuses the TCP/IP socket used by the previous communication.
# The default value is 2 seconds.
attr_accessor :keep_alive_timeout
# Returns true if the HTTP session has been started.
def started?
@started
@ -1332,7 +1339,10 @@ module Net #:nodoc:
res
end
IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
def transport_request(req)
count = 0
begin_transport req
res = catch(:response) {
req.exec @socket, @curr_http_version, edit_path(req.path)
@ -1346,6 +1356,16 @@ module Net #:nodoc:
}
end_transport req, res
res
rescue EOFError, Errno::ECONNRESET => exception
if count == 0 && IDEMPOTENT_METHODS_.include?(req.method)
count += 1
@socket.close if @socket and not @socket.closed?
D "Conn close because of error #{exception}, and retry"
retry
end
D "Conn close because of error #{exception}"
@socket.close if @socket and not @socket.closed?
raise
rescue => exception
D "Conn close because of error #{exception}"
@socket.close if @socket and not @socket.closed?
@ -1353,7 +1373,14 @@ module Net #:nodoc:
end
def begin_transport(req)
connect if @socket.closed?
if @socket.closed?
connect
elsif @last_communicated && @last_communicated + @keep_alive_timeout < Time.now
D 'Conn close because of keep_alive_timeout'
@socket.close
connect
end
if not req.response_body_permitted? and @close_on_empty_response
req['connection'] ||= 'close'
end
@ -1362,6 +1389,7 @@ module Net #:nodoc:
def end_transport(req, res)
@curr_http_version = res.http_version
@last_communicated = nil
if @socket.closed?
D 'Conn socket closed'
elsif not res.body and @close_on_empty_response
@ -1369,6 +1397,7 @@ module Net #:nodoc:
@socket.close
elsif keep_alive?(req, res)
D 'Conn keep-alive'
@last_communicated = Time.now
else
D 'Conn close'
@socket.close

View file

@ -564,3 +564,47 @@ class TestNetHTTPContinue < Test::Unit::TestCase
assert_not_match(/HTTP\/1.1 100 continue/, @debug.string)
end
end
class TestNetHTTPKeepAlive < Test::Unit::TestCase
CONFIG = {
'host' => '127.0.0.1',
'port' => 10081,
'proxy_host' => nil,
'proxy_port' => nil,
'RequestTimeout' => 1,
}
include TestNetHTTPUtils
def test_keep_alive_get_auto_reconnect
start {|http|
http.set_debug_output($stderr)
res = http.get('/')
http.keep_alive_timeout = 1
assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body
sleep 1.5
assert_nothing_raised {
res = http.get('/')
}
assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body
}
end
def test_keep_alive_get_auto_retry
start {|http|
http.set_debug_output($stderr)
res = http.get('/')
http.keep_alive_timeout = 5
assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body
sleep 1.5
assert_nothing_raised {
res = http.get('/')
}
assert_kind_of Net::HTTPResponse, res
assert_kind_of String, res.body
}
end
end

View file

@ -51,6 +51,7 @@ module TestNetHTTPUtils
:ServerType => Thread,
}
server_config[:OutputBufferSize] = 4 if config('chunked')
server_config[:RequestTimeout] = config('RequestTimeout') if config('RequestTimeout')
if defined?(OpenSSL) and config('ssl_enable')
server_config.update({
:SSLEnable => true,