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:
parent
87daaf61b9
commit
bee7ccddd2
4 changed files with 90 additions and 2 deletions
14
ChangeLog
14
ChangeLog
|
@ -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>
|
Thu Jan 19 07:53:09 2012 Tadayoshi Funaba <tadf@dotrb.org>
|
||||||
|
|
||||||
* ext/date/date_strptime.c: moved detector of leftover.
|
* ext/date/date_strptime.c: moved detector of leftover.
|
||||||
|
|
|
@ -578,7 +578,8 @@ module Net #:nodoc:
|
||||||
@address = address
|
@address = address
|
||||||
@port = (port || HTTP.default_port)
|
@port = (port || HTTP.default_port)
|
||||||
@curr_http_version = HTTPVersion
|
@curr_http_version = HTTPVersion
|
||||||
@no_keepalive_server = false
|
@keep_alive_timeout = 2
|
||||||
|
@last_communicated = nil
|
||||||
@close_on_empty_response = false
|
@close_on_empty_response = false
|
||||||
@socket = nil
|
@socket = nil
|
||||||
@started = false
|
@started = false
|
||||||
|
@ -648,6 +649,12 @@ module Net #:nodoc:
|
||||||
@continue_timeout = sec
|
@continue_timeout = sec
|
||||||
end
|
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.
|
# Returns true if the HTTP session has been started.
|
||||||
def started?
|
def started?
|
||||||
@started
|
@started
|
||||||
|
@ -1332,7 +1339,10 @@ module Net #:nodoc:
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
|
||||||
|
|
||||||
def transport_request(req)
|
def transport_request(req)
|
||||||
|
count = 0
|
||||||
begin_transport req
|
begin_transport req
|
||||||
res = catch(:response) {
|
res = catch(:response) {
|
||||||
req.exec @socket, @curr_http_version, edit_path(req.path)
|
req.exec @socket, @curr_http_version, edit_path(req.path)
|
||||||
|
@ -1346,6 +1356,16 @@ module Net #:nodoc:
|
||||||
}
|
}
|
||||||
end_transport req, res
|
end_transport req, res
|
||||||
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
|
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?
|
||||||
|
@ -1353,7 +1373,14 @@ module Net #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def begin_transport(req)
|
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
|
if not req.response_body_permitted? and @close_on_empty_response
|
||||||
req['connection'] ||= 'close'
|
req['connection'] ||= 'close'
|
||||||
end
|
end
|
||||||
|
@ -1362,6 +1389,7 @@ module Net #:nodoc:
|
||||||
|
|
||||||
def end_transport(req, res)
|
def end_transport(req, res)
|
||||||
@curr_http_version = res.http_version
|
@curr_http_version = res.http_version
|
||||||
|
@last_communicated = nil
|
||||||
if @socket.closed?
|
if @socket.closed?
|
||||||
D 'Conn socket closed'
|
D 'Conn socket closed'
|
||||||
elsif not res.body and @close_on_empty_response
|
elsif not res.body and @close_on_empty_response
|
||||||
|
@ -1369,6 +1397,7 @@ module Net #:nodoc:
|
||||||
@socket.close
|
@socket.close
|
||||||
elsif keep_alive?(req, res)
|
elsif keep_alive?(req, res)
|
||||||
D 'Conn keep-alive'
|
D 'Conn keep-alive'
|
||||||
|
@last_communicated = Time.now
|
||||||
else
|
else
|
||||||
D 'Conn close'
|
D 'Conn close'
|
||||||
@socket.close
|
@socket.close
|
||||||
|
|
|
@ -564,3 +564,47 @@ class TestNetHTTPContinue < Test::Unit::TestCase
|
||||||
assert_not_match(/HTTP\/1.1 100 continue/, @debug.string)
|
assert_not_match(/HTTP\/1.1 100 continue/, @debug.string)
|
||||||
end
|
end
|
||||||
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
|
||||||
|
|
|
@ -51,6 +51,7 @@ module TestNetHTTPUtils
|
||||||
:ServerType => Thread,
|
:ServerType => Thread,
|
||||||
}
|
}
|
||||||
server_config[:OutputBufferSize] = 4 if config('chunked')
|
server_config[:OutputBufferSize] = 4 if config('chunked')
|
||||||
|
server_config[:RequestTimeout] = config('RequestTimeout') if config('RequestTimeout')
|
||||||
if defined?(OpenSSL) and config('ssl_enable')
|
if defined?(OpenSSL) and config('ssl_enable')
|
||||||
server_config.update({
|
server_config.update({
|
||||||
:SSLEnable => true,
|
:SSLEnable => true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue