webrick/httprequest: use InputBufferSize for chunked requests
While WEBrick::HTTPRequest#body provides a Proc interface for streaming large request bodies, clients must not force the server to use an excessively large chunk size. * lib/webrick/httprequest.rb (read_chunk_size): limit each read and block.call to :InputBufferSize in config. * test/webrick/test_httpserver.rb (test_big_chunks): new test git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62963 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6db6eb572b
commit
2d41d88c4d
@ -509,12 +509,16 @@ module WEBrick
|
||||
def read_chunked(socket, block)
|
||||
chunk_size, = read_chunk_size(socket)
|
||||
while chunk_size > 0
|
||||
data = read_data(socket, chunk_size) # read chunk-data
|
||||
if data.nil? || data.bytesize != chunk_size
|
||||
raise HTTPStatus::BadRequest, "bad chunk data size."
|
||||
end
|
||||
begin
|
||||
sz = [ chunk_size, @buffer_size ].min
|
||||
data = read_data(socket, sz) # read chunk-data
|
||||
if data.nil? || data.bytesize != sz
|
||||
raise HTTPStatus::BadRequest, "bad chunk data size."
|
||||
end
|
||||
block.call(data)
|
||||
end while (chunk_size -= sz) > 0
|
||||
|
||||
read_line(socket) # skip CRLF
|
||||
block.call(data)
|
||||
chunk_size, = read_chunk_size(socket)
|
||||
end
|
||||
read_header(socket) # trailer + CRLF
|
||||
|
@ -475,4 +475,37 @@ class TestWEBrickHTTPServer < Test::Unit::TestCase
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_big_chunks
|
||||
nr_out = 3
|
||||
buf = 'big' # 3 bytes is bigger than 2!
|
||||
config = { :InputBufferSize => 2 }.freeze
|
||||
total = 0
|
||||
all = ''
|
||||
TestWEBrick.start_httpserver(config){|server, addr, port, log|
|
||||
server.mount_proc('/', ->(req, res) {
|
||||
err = []
|
||||
ret = req.body do |chunk|
|
||||
n = chunk.bytesize
|
||||
n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
|
||||
total += n
|
||||
all << chunk
|
||||
end
|
||||
ret.nil? or err << 'req.body should return nil'
|
||||
(buf * nr_out) == all or err << 'input body does not match expected'
|
||||
res.header['connection'] = 'close'
|
||||
res.body = err.join("\n")
|
||||
})
|
||||
TCPSocket.open(addr, port) do |c|
|
||||
c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
|
||||
"Transfer-Encoding: chunked\r\n\r\n")
|
||||
chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
|
||||
nr_out.times { c.write(chunk) }
|
||||
c.write("0\r\n\r\n")
|
||||
head, body = c.read.split("\r\n\r\n")
|
||||
assert_match %r{\AHTTP/1\.1 200 OK}, head
|
||||
assert_nil body
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user