From 56206ab8cd0e822e861ae963fc02e2343652d8e2 Mon Sep 17 00:00:00 2001 From: naruse Date: Sat, 7 Apr 2012 21:50:34 +0000 Subject: [PATCH] * lib/webrick/httpresponse.rb (WEBrick::HTTPResponse#send_body_io): use readpartial to get data even if the response is streaming data and each data is smaller than @buffer_size. patched by yu nobuoka. [ruby-dev:45471] [Bug #6230] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35253 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++++ lib/webrick/httpresponse.rb | 19 ++++++---- test/webrick/test_httpserver.rb | 64 +++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index a746048bd6..e7b0fdf8ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sun Apr 8 06:46:48 2012 NARUSE, Yui + + * lib/webrick/httpresponse.rb (WEBrick::HTTPResponse#send_body_io): + use readpartial to get data even if the response is streaming data and + each data is smaller than @buffer_size. + patched by yu nobuoka. [ruby-dev:45471] [Bug #6230] + Sat Apr 7 22:35:36 2012 Hiroshi Shirosaki * include/ruby/win32.h (rb_w32_aspawn_flags): add the declaration of diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb index baa49dea92..5adbc82173 100644 --- a/lib/webrick/httpresponse.rb +++ b/lib/webrick/httpresponse.rb @@ -330,13 +330,18 @@ module WEBrick if @request_method == "HEAD" # do nothing elsif chunked? - while buf = @body.read(@buffer_size) - next if buf.empty? - data = "" - data << format("%x", buf.bytesize) << CRLF - data << buf << CRLF - _write_data(socket, data) - @sent_size += buf.bytesize + begin + buf = '' + data = '' + while true + @body.readpartial( @buffer_size, buf ) # there is no need to clear buf? + data << format("%x", buf.bytesize) << CRLF + data << buf << CRLF + _write_data(socket, data) + data.clear + @sent_size += buf.bytesize + end + rescue EOFError # do nothing end _write_data(socket, "0#{CRLF}#{CRLF}") else diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb index 526d72c381..bbfef53611 100644 --- a/test/webrick/test_httpserver.rb +++ b/test/webrick/test_httpserver.rb @@ -258,6 +258,70 @@ class TestWEBrickHTTPServer < Test::Unit::TestCase assert_equal(stopped, 1) end + # This class is needed by test_response_io_with_chunked_set method + class EventManagerForChunkedResponseTest + def initialize + @listeners = [] + end + def add_listener( &block ) + @listeners << block + end + def raise_str_event( str ) + @listeners.each{ |e| e.call( :str, str ) } + end + def raise_close_event() + @listeners.each{ |e| e.call( :cls ) } + end + end + def test_response_io_with_chunked_set + evt_man = EventManagerForChunkedResponseTest.new + t = Thread.new do + begin + config = { + :ServerName => "localhost" + } + TestWEBrick.start_httpserver(config) do |server, addr, port, log| + body_strs = [ 'aaaaaa', 'bb', 'cccc' ] + server.mount_proc( "/", ->( req, res ){ + # Test for setting chunked... + res.chunked = true + r,w = IO.pipe + evt_man.add_listener do |type,str| + type == :cls ? ( w.close ) : ( w << str ) + end + res.body = r + } ) + Thread.pass while server.status != :Running + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/") + http.request(req) do |res| + i = 0 + evt_man.raise_str_event( body_strs[i] ) + res.read_body do |s| + assert_equal( body_strs[i], s ) + i += 1 + if i < body_strs.length + evt_man.raise_str_event( body_strs[i] ) + else + evt_man.raise_close_event() + end + end + assert_equal( body_strs.length, i ) + end + end + rescue => err + flunk( 'exception raised in thread: ' + err.to_s ) + end + end + if t.join( 3 ).nil? + evt_man.raise_close_event() + flunk( 'timeout' ) + if t.join( 1 ).nil? + Thread.kill t + end + end + end + def test_response_io_without_chunked_set config = { :ServerName => "localhost"