summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 14:13:08 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 14:13:08 +0000
commitd32a6d37fe32beffd44e95dd062513cabcc86acb (patch)
tree63277f9e1251cbcfae60e2d10350b181633e0b56 /test
parent32c00d78a6e94203507bfa57a60ab5a005af6d7b (diff)
merge revision(s) 60584,62954-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: favor .write over << method This will make the next change to use IO.copy_stream easier-to-read. When we can drop Ruby 2.4 support in a few years, this will allow us to use writev(2) with multiple arguments for headers and chunked responses. * lib/webrick/cgi.rb (write): new wrapper method lib/webrick/httpresponse.rb: (send_header): use socket.write (send_body_io): ditto (send_body_string): ditto (send_body_proc): ditto (_write_data): ditto (ChunkedWrapper#write): ditto (_send_file): ditto ------------------------------------------------------------------------ r62954 | normal | 2018-03-28 17:05:52 +0900 (水, 28 3 2018) | 14 lines 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] ------------------------------------------------------------------------ r62955 | normal | 2018-03-28 17:05:57 +0900 (水, 28 3 2018) | 10 lines 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 ------------------------------------------------------------------------ r62956 | normal | 2018-03-28 17:06:02 +0900 (水, 28 3 2018) | 7 lines 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 ------------------------------------------------------------------------ r62957 | normal | 2018-03-28 17:06:08 +0900 (水, 28 3 2018) | 8 lines 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 ------------------------------------------------------------------------ r62958 | normal | 2018-03-28 17:06:13 +0900 (水, 28 3 2018) | 7 lines 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 ------------------------------------------------------------------------ r62959 | normal | 2018-03-28 17:06:18 +0900 (水, 28 3 2018) | 9 lines 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_3@63014 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test')
-rw-r--r--test/webrick/test_filehandler.rb31
-rw-r--r--test/webrick/test_httpresponse.rb33
2 files changed, 54 insertions, 10 deletions
diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb
index 663b237a82..5b17e77fd5 100644
--- a/test/webrick/test_filehandler.rb
+++ b/test/webrick/test_filehandler.rb
@@ -15,16 +15,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)
@@ -76,6 +70,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 5c0e5d1753..6263e0a710 100644
--- a/test/webrick/test_httpresponse.rb
+++ b/test/webrick/test_httpresponse.rb
@@ -168,5 +168,38 @@ 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'
+ @res.status = status
+ error = WEBrick::HTTPStatus[status].new(message)
+ body = @res.set_error(error)
+ assert_match(/#{@res.reason_phrase}/, body)
+ assert_match(/#{message}/, body)
+ end
end
end