Index: lib/net/http.rb =================================================================== --- lib/net/http.rb (revision 29201) +++ lib/net/http.rb (working copy) @@ -517,6 +517,7 @@ @started = false @open_timeout = nil @read_timeout = 60 + @continue_timeout = nil @debug_output = nil @use_ssl = false @ssl_context = nil @@ -570,6 +571,16 @@ @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_timout=(sec) + @socket.continue_timeout = sec if @socket + @continue_timeout = sec + end + # returns true if the HTTP session is started. def started? @started @@ -1190,12 +1201,15 @@ def transport_request(req) begin_transport req - req.exec @socket, @curr_http_version, edit_path(req.path) - begin - res = HTTPResponse.read_new(@socket) - end while res.kind_of?(HTTPContinue) - res.reading_body(@socket, req.response_body_permitted?) { - yield res if block_given? + res = catch(:response) { + req.exec @socket, @curr_http_version, edit_path(req.path) + begin + res = HTTPResponse.read_new(@socket) + end while res.kind_of?(HTTPContinue) + res.reading_body(@socket, req.response_body_permitted?) { + yield res if block_given? + } + res } end_transport req, res res @@ -1739,6 +1753,7 @@ self.content_length = body.bytesize delete 'Transfer-Encoding' supply_default_content_type + wait_for_continue sock, ver if sock.continue_timeout write_header sock, ver, path sock.write body end @@ -1749,6 +1764,7 @@ "Content-Length not given and Transfer-Encoding is not `chunked'" end supply_default_content_type + wait_for_continue sock, ver if sock.continue_timeout write_header sock, ver, path if chunked? while s = f.read(1024) @@ -1768,6 +1784,22 @@ 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') then + if IO.select [sock.io], nil, nil, sock.continue_timeout then + 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| Index: lib/net/protocol.rb =================================================================== --- lib/net/protocol.rb (revision 29201) +++ lib/net/protocol.rb (working copy) @@ -50,12 +50,14 @@ def initialize(io) @io = io @read_timeout = 60 + @continue_timeout = 0.5 @debug_output = nil @rbuf = '' end attr_reader :io attr_accessor :read_timeout + attr_accessor :continue_timeout attr_accessor :debug_output def inspect