From 2a5edbc1d50d40c68d842847b0a8160874d8b7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Sun, 30 Dec 2018 13:30:48 +0100 Subject: [PATCH] Close connection if the request has not been consumed entirely, don't skip any bytes --- spec/std/http/server/server_spec.cr | 42 ++-------------------------- src/http/server/request_processor.cr | 28 ++++--------------- 2 files changed, 8 insertions(+), 62 deletions(-) diff --git a/spec/std/http/server/server_spec.cr b/spec/std/http/server/server_spec.cr index 5b953e4294a6..91ed646cecdb 100644 --- a/spec/std/http/server/server_spec.cr +++ b/spec/std/http/server/server_spec.cr @@ -715,44 +715,6 @@ module HTTP )) end - it "skips body with known length" do - processor = HTTP::Server::RequestProcessor.new do |context| - context.response.content_type = "text/plain" - context.response.puts "Hello world\r" - end - - input = IO::Memory.new(requestize(<<-REQUEST - POST / HTTP/1.1 - Content-Length: 7 - - hello - POST / HTTP/1.1 - Content-Length: 7 - - hello - REQUEST - )) - output = IO::Memory.new - processor.process(input, output) - output.rewind - output.gets_to_end.should eq(requestize(<<-RESPONSE - HTTP/1.1 200 OK - Connection: keep-alive - Content-Type: text/plain - Content-Length: 13 - - Hello world - HTTP/1.1 200 OK - Connection: keep-alive - Content-Type: text/plain - Content-Length: 13 - - Hello world - - RESPONSE - )) - end - it "fail if body is not consumed" do processor = HTTP::Server::RequestProcessor.new do |context| context.response.content_type = "text/plain" @@ -827,9 +789,9 @@ module HTTP input = IO::Memory.new(requestize(<<-REQUEST POST / HTTP/1.1 - Content-Length: 16387 + Content-Length: 4 - #{"0" * 16_384}1 + 1 POST / HTTP/1.1 Content-Length: 7 diff --git a/src/http/server/request_processor.cr b/src/http/server/request_processor.cr index 5e9668dc2d0d..eee8b366f0ee 100644 --- a/src/http/server/request_processor.cr +++ b/src/http/server/request_processor.cr @@ -59,21 +59,17 @@ class HTTP::Server::RequestProcessor break unless HTTP.keep_alive?(response) # The request body is either FixedLengthContent or ChunkedContent. - # In case it has not entirely been consumed by the handler, try to - # skip to the end. If the request is larger than maxmum skippable size, - # we close the connection even if keep alive was requested. + # In case it has not entirely been consumed by the handler, the connection is + # closed the connection even if keep alive was requested. case body = request.body when FixedLengthContent - if body.read_remaining > 16_384 - # Close the connection if remaining length exceeds the maximum skipable size. + if body.read_remaining > 0 + # Close the connection if there are bytes remaining break - else - body.skip_to_end end when ChunkedContent - # Try to read maximum skipable number of bytes. - # Close the connection if the IO has still more to read. - break unless skip_to_end(body) + # Close the connection if the IO has still bytes to read. + break unless body.read_byte.nil? end end rescue ex : Errno @@ -86,16 +82,4 @@ class HTTP::Server::RequestProcessor end end end - - # Reads and discards bytes from `io` until there are no more bytes. - # If there are more than 16_384 bytes to be read from the IO, it returns `false`. - private def skip_to_end(io : IO) : Bool - buffer = uninitialized UInt8[4096] - - 4.times do - return true if io.read(buffer.to_slice) < 4096 - end - - false - end end