mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/net/http.rb, lib/net/protocol.rb: Allow to configure to wait
server returning '100 continue' response befor sending HTTP request body. See NEWS for more detail. See #3622. Original patch is made by Eric Hodel <drbrain@segment7.net>. * test/net/http/test_http.rb: test it. * NEWS: Add new feature. On my env (Ubuntu 11.04 64bit), 9510 tests, 2203824 assertions, 0 failures, 0 errors, 29 skips -> 9514 tests, 2203836 assertions, 0 failures, 0 errors, 29 skips git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31860 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
da1db8b454
commit
b219a56c07
5 changed files with 144 additions and 6 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Tue May 31 17:03:24 2011 Hiroshi Nakamura <nahi@ruby-lang.org>
|
||||
|
||||
* lib/net/http.rb, lib/net/protocol.rb: Allow to configure to wait
|
||||
server returning '100 continue' response befor sending HTTP request
|
||||
body. See NEWS for more detail. See #3622.
|
||||
Original patch is made by Eric Hodel <drbrain@segment7.net>.
|
||||
|
||||
* test/net/http/test_http.rb: test it.
|
||||
|
||||
* NEWS: Add new feature.
|
||||
|
||||
Tue May 31 14:17:49 2011 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* io.c (rb_io_s_pipe): potential bug. the mode of read IO is set as
|
||||
|
|
11
NEWS
11
NEWS
|
@ -98,6 +98,17 @@ with all sufficient information, see the ChangeLog file.
|
|||
* net/http
|
||||
* SNI (Server Name Indication) supported for HTTPS.
|
||||
|
||||
* Allow to configure to wait server returning '100 continue' response
|
||||
before sending HTTP request body. Set Net::HTTP#continue_timeout AND pass
|
||||
'expect' => '100-continue' to a extra HTTP header.
|
||||
|
||||
For example, the following code sends HTTP header and waits for getting
|
||||
'100 continue' response before sending HTTP request body. When 0.5 [sec]
|
||||
timeout occurs or the server send '100 continue', the client sends HTTP
|
||||
request body.
|
||||
http.continue_timeout = 0.5
|
||||
http.request_post('/continue', 'body=BODY', 'expect' => '100-continue')
|
||||
|
||||
* openssl
|
||||
* PKey::RSA and PKey::DSA now use the generic X.509 encoding scheme
|
||||
(e.g. used in a X.509 certificate's Subject Public Key Info) when
|
||||
|
|
|
@ -581,6 +581,7 @@ module Net #:nodoc:
|
|||
@started = false
|
||||
@open_timeout = nil
|
||||
@read_timeout = 60
|
||||
@continue_timeout = nil
|
||||
@debug_output = nil
|
||||
@use_ssl = false
|
||||
@ssl_context = nil
|
||||
|
@ -634,6 +635,16 @@ module Net #:nodoc:
|
|||
@read_timeout = sec
|
||||
end
|
||||
|
||||
# Seconds to wait for 100 Continue response. If the HTTP object does not
|
||||
# receive a response in this many seconds it sends the request body.
|
||||
attr_reader :continue_timeout
|
||||
|
||||
# Setter for the continue_timeout attribute.
|
||||
def continue_timeout=(sec)
|
||||
@socket.continue_timeout = sec if @socket
|
||||
@continue_timeout = sec
|
||||
end
|
||||
|
||||
# Returns true if the HTTP session has been started.
|
||||
def started?
|
||||
@started
|
||||
|
@ -764,6 +775,7 @@ module Net #:nodoc:
|
|||
end
|
||||
@socket = BufferedIO.new(s)
|
||||
@socket.read_timeout = @read_timeout
|
||||
@socket.continue_timeout = @continue_timeout
|
||||
@socket.debug_output = @debug_output
|
||||
if use_ssl?
|
||||
begin
|
||||
|
@ -1298,6 +1310,7 @@ module Net #:nodoc:
|
|||
|
||||
def transport_request(req)
|
||||
begin_transport req
|
||||
res = catch(:response) {
|
||||
req.exec @socket, @curr_http_version, edit_path(req.path)
|
||||
begin
|
||||
res = HTTPResponse.read_new(@socket)
|
||||
|
@ -1305,6 +1318,8 @@ module Net #:nodoc:
|
|||
res.reading_body(@socket, req.response_body_permitted?) {
|
||||
yield res if block_given?
|
||||
}
|
||||
res
|
||||
}
|
||||
end_transport req, res
|
||||
res
|
||||
rescue => exception
|
||||
|
@ -1915,6 +1930,7 @@ module Net #:nodoc:
|
|||
delete 'Transfer-Encoding'
|
||||
supply_default_content_type
|
||||
write_header sock, ver, path
|
||||
wait_for_continue sock, ver if sock.continue_timeout
|
||||
sock.write body
|
||||
end
|
||||
|
||||
|
@ -1925,6 +1941,7 @@ module Net #:nodoc:
|
|||
end
|
||||
supply_default_content_type
|
||||
write_header sock, ver, path
|
||||
wait_for_continue sock, ver if sock.continue_timeout
|
||||
if chunked?
|
||||
while s = f.read(1024)
|
||||
sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
|
||||
|
@ -2030,6 +2047,22 @@ module Net #:nodoc:
|
|||
set_content_type 'application/x-www-form-urlencoded'
|
||||
end
|
||||
|
||||
##
|
||||
# Waits up to the continue timeout for a response from the server provided
|
||||
# we're speaking HTTP 1.1 and are expecting a 100-continue response.
|
||||
|
||||
def wait_for_continue(sock, ver)
|
||||
if ver >= '1.1' and @header['expect'] and
|
||||
@header['expect'].include?('100-continue')
|
||||
if IO.select([sock.io], nil, nil, sock.continue_timeout)
|
||||
res = HTTPResponse.read_new(sock)
|
||||
unless res.kind_of?(Net::HTTPContinue)
|
||||
throw :response, res
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def write_header(sock, ver, path)
|
||||
buf = "#{@method} #{path} HTTP/#{ver}\r\n"
|
||||
each_capitalized do |k,v|
|
||||
|
|
|
@ -50,12 +50,14 @@ module Net # :nodoc:
|
|||
def initialize(io)
|
||||
@io = io
|
||||
@read_timeout = 60
|
||||
@continue_timeout = nil
|
||||
@debug_output = nil
|
||||
@rbuf = ''
|
||||
end
|
||||
|
||||
attr_reader :io
|
||||
attr_accessor :read_timeout
|
||||
attr_accessor :continue_timeout
|
||||
attr_accessor :debug_output
|
||||
|
||||
def inspect
|
||||
|
|
|
@ -464,3 +464,84 @@ class TestNetHTTP_v1_2_chunked < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
class TestNetHTTPContinue < Test::Unit::TestCase
|
||||
CONFIG = {
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 10081,
|
||||
'proxy_host' => nil,
|
||||
'proxy_port' => nil,
|
||||
'chunked' => true,
|
||||
}
|
||||
|
||||
include TestNetHTTPUtils
|
||||
|
||||
def logfile
|
||||
@debug = StringIO.new('')
|
||||
end
|
||||
|
||||
def mount_proc(&block)
|
||||
@server.mount('/continue', WEBrick::HTTPServlet::ProcHandler.new(block.to_proc))
|
||||
end
|
||||
|
||||
def test_expect_continue
|
||||
mount_proc {|req, res|
|
||||
req.continue
|
||||
res.body = req.query['body']
|
||||
}
|
||||
start {|http|
|
||||
http.continue_timeout = 0.2
|
||||
http.request_post('/continue', 'body=BODY', 'expect' => '100-continue') {|res|
|
||||
assert_equal('BODY', res.read_body)
|
||||
}
|
||||
}
|
||||
assert_match(/Expect: 100-continue/, @debug.string)
|
||||
assert_match(/HTTP\/1.1 100 continue/, @debug.string)
|
||||
end
|
||||
|
||||
def test_expect_continue_timeout
|
||||
mount_proc {|req, res|
|
||||
sleep 0.2
|
||||
req.continue # just ignored because it's '100'
|
||||
res.body = req.query['body']
|
||||
}
|
||||
start {|http|
|
||||
http.continue_timeout = 0
|
||||
http.request_post('/continue', 'body=BODY', 'expect' => '100-continue') {|res|
|
||||
assert_equal('BODY', res.read_body)
|
||||
}
|
||||
}
|
||||
assert_match(/Expect: 100-continue/, @debug.string)
|
||||
assert_match(/HTTP\/1.1 100 continue/, @debug.string)
|
||||
end
|
||||
|
||||
def test_expect_continue_error
|
||||
mount_proc {|req, res|
|
||||
res.status = 501
|
||||
res.body = req.query['body']
|
||||
}
|
||||
start {|http|
|
||||
http.continue_timeout = 0
|
||||
http.request_post('/continue', 'body=ERROR', 'expect' => '100-continue') {|res|
|
||||
assert_equal('ERROR', res.read_body)
|
||||
}
|
||||
}
|
||||
assert_match(/Expect: 100-continue/, @debug.string)
|
||||
assert_not_match(/HTTP\/1.1 100 continue/, @debug.string)
|
||||
end
|
||||
|
||||
def test_expect_continue_error_while_waiting
|
||||
mount_proc {|req, res|
|
||||
res.status = 501
|
||||
res.body = req.query['body']
|
||||
}
|
||||
start {|http|
|
||||
http.continue_timeout = 0.5
|
||||
http.request_post('/continue', 'body=ERROR', 'expect' => '100-continue') {|res|
|
||||
assert_equal('ERROR', res.read_body)
|
||||
}
|
||||
}
|
||||
assert_match(/Expect: 100-continue/, @debug.string)
|
||||
assert_not_match(/HTTP\/1.1 100 continue/, @debug.string)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue