From 82b452e099b8572fab137b1e8c6c13b975353fe1 Mon Sep 17 00:00:00 2001 From: Sebastian Cohnen Date: Sun, 10 Nov 2024 15:52:10 +0100 Subject: [PATCH] handles client connection reset for keep-alive connections --- lib/webrick/httpserver.rb | 7 ++++++- test/webrick/test_httpserver.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/webrick/httpserver.rb b/lib/webrick/httpserver.rb index 0d261bf0..2017fa21 100644 --- a/lib/webrick/httpserver.rb +++ b/lib/webrick/httpserver.rb @@ -79,7 +79,12 @@ def run(sock) timeout -= 0.5 end raise HTTPStatus::EOFError if timeout <= 0 || @status != :Running - raise HTTPStatus::EOFError if sock.eof? + begin + raise HTTPStatus::EOFError if sock.eof? + rescue Errno::ECONNRESET + raise HTTPStatus::EOFError + end + req.parse(sock) res.request_method = req.request_method res.request_uri = req.request_uri diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb index 0c5a6147..c74b49f1 100644 --- a/test/webrick/test_httpserver.rb +++ b/test/webrick/test_httpserver.rb @@ -562,4 +562,35 @@ def test_accept_put_requests end end end + + def test_client_connection_reset + log_tester = lambda {|log, access_log| + assert_empty log + } + + TestWEBrick.start_httpserver({}, log_tester) do |server, addr, port, log| + server.mount_proc("/", lambda {|req, res| res.body = "hello!" }) + + http = Net::HTTP.new(addr, port) + req = Net::HTTP::Get.new("/") + req['Connection'] = 'Keep-Alive' + + # Simulate a client, which makes a request, reads the response + # and then resets the connection. + http.request(req) do |res| + res.body # read body to completion + + # Fish the socket out of the Net::HTTP object, configure it to + # linger on close, and then close it abruptly. This will reset + # the socket, discard any pending data cause a RST to be sent. + socket = http.instance_variable_get(:@socket).io + socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1,0].pack('ii')) + socket.close + end + + # delay the server shutdown so that WEBrick::HTTPServer#run begins + # a new iteration. + sleep 0.1 + end + end end