diff options
author | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-28 13:54:58 +0000 |
---|---|---|
committer | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-28 13:54:58 +0000 |
commit | c461bdc3c5243d4b0ea1f47b78fa67eac0d355db (patch) | |
tree | ce725a85295b57b9728c70cb1348da1edb386e45 /test/webrick | |
parent | 16b426e96611d1ccc9acc9a9f9a2ea1f6c5cc4ec (diff) |
merge revision(s) 60584,62954,62955,62956,62957,62958,62959,63008:
webrick: support Proc objects as body responses
* lib/webrick/httpresponse.rb (send_body): call send_body_proc
(send_body_proc): new method
(class ChunkedWrapper): new class
* test/webrick/test_httpresponse.rb (test_send_body_proc): new test
(test_send_body_proc_chunked): ditto
[Feature #855]
webrick/httpresponse: IO.copy_stream for regular files
Remove the redundant _send_file method since its functionality
is unnecessary with IO.copy_stream. IO.copy_stream also allows
the use of sendfile under some OSes to speed up copies to
non-TLS sockets.
Testing with "curl >/dev/null" and "ruby -run -e httpd" to
read a 1G file over Linux loopback reveals a reduction from
around ~0.770 to ~0.490 seconds on the client side.
* lib/webrick/httpresponse.rb (send_body_io): use IO.copy_stream
(_send_file): remove
[Feature #14237]
webrick: use IO.copy_stream for single range response
This is also compatible with range responses generated
by Rack::File (tested with rack 2.0.3).
* lib/webrick/httpresponse.rb (send_body_io): use Content-Range
* lib/webrick/httpservlet/filehandler.rb (make_partial_content):
use File object for the single range case
* test/webrick/test_filehandler.rb (get_res_body): use send_body
to test result
test/webrick/test_filehandler.rb: stricter multipart range test
We need to ensure we generate compatibile output in
the face of future changes
* test/webrick/test_filehandler.rb (test_make_partial_content):
check response body
webrick: quiet warning for multi-part ranges
Content-Length is ignored by WEBrick::HTTPResponse even if we
calculate it, so instead we chunk responses to HTTP/1.1 clients
and terminate HTTP/1.0 connections.
* lib/webrick/httpservlet/filehandler.rb (make_partial_content):
quiet warning
webrick/httpresponse: make ChunkedWrapper copy_stream-compatible
The .write method needs to return the number of bytes written
to avoid confusing IO.copy_stream.
* lib/webrick/httpresponse.rb (ChunkedWrapper#write): return bytes written
(ChunkedWrapper#<<): return self
webrick: use IO.copy_stream for multipart response
Use the new Proc response body feature to generate a multipart
range response dynamically. We use a flat array to minimize
object overhead as much as possible; as many ranges may fit
into an HTTP request header.
* lib/webrick/httpservlet/filehandler.rb (multipart_body): new method
(make_partial_content): use multipart_body
get rid of test error/failure on Windows introduced at r62955
* lib/webrick/httpresponse.rb (send_body_io): use seek if NotImplementedError
is raised in IO.copy_stream with offset.
* lib/webrick/httpservlet/filehandler.rb (multipart_body): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@63012 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/webrick')
-rw-r--r-- | test/webrick/test_filehandler.rb | 31 | ||||
-rw-r--r-- | test/webrick/test_httpresponse.rb | 23 |
2 files changed, 44 insertions, 10 deletions
diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb index 0e05c6824c..b0fc07b56e 100644 --- a/test/webrick/test_filehandler.rb +++ b/test/webrick/test_filehandler.rb @@ -20,16 +20,10 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase end def get_res_body(res) - body = res.body - if defined? body.read - begin - body.read - ensure - body.close - end - else - body - end + sio = StringIO.new + sio.binmode + res.send_body(sio) + sio.string end def make_range_request(range_spec) @@ -81,6 +75,23 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase res = make_range_response(filename, "bytes=0-0, -2") assert_match(%r{^multipart/byteranges}, res["content-type"]) + body = get_res_body(res) + boundary = /; boundary=(.+)/.match(res['content-type'])[1] + off = filesize - 2 + last = filesize - 1 + + exp = "--#{boundary}\r\n" \ + "Content-Type: text/plain\r\n" \ + "Content-Range: bytes 0-0/#{filesize}\r\n" \ + "\r\n" \ + "#{IO.read(__FILE__, 1)}\r\n" \ + "--#{boundary}\r\n" \ + "Content-Type: text/plain\r\n" \ + "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \ + "\r\n" \ + "#{IO.read(__FILE__, 2, off)}\r\n" \ + "--#{boundary}--\r\n" + assert_equal exp, body end def test_filehandler diff --git a/test/webrick/test_httpresponse.rb b/test/webrick/test_httpresponse.rb index 3a98a53b71..6263e0a710 100644 --- a/test/webrick/test_httpresponse.rb +++ b/test/webrick/test_httpresponse.rb @@ -169,6 +169,29 @@ module WEBrick assert_equal 0, logger.messages.length end + def test_send_body_proc + @res.body = Proc.new { |out| out.write('hello') } + IO.pipe do |r, w| + @res.send_body(w) + w.close + r.binmode + assert_equal 'hello', r.read + end + assert_equal 0, logger.messages.length + end + + def test_send_body_proc_chunked + @res.body = Proc.new { |out| out.write('hello') } + @res.chunked = true + IO.pipe do |r, w| + @res.send_body(w) + w.close + r.binmode + assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read + end + assert_equal 0, logger.messages.length + end + def test_set_error status = 400 message = 'missing attribute' |