diff --git a/lib/protocol/http1/connection.rb b/lib/protocol/http1/connection.rb index 596a39d..ad463eb 100644 --- a/lib/protocol/http1/connection.rb +++ b/lib/protocol/http1/connection.rb @@ -349,7 +349,7 @@ def read(length) # Read a line from the connection. # - # @returns [String | Nil] the line read, or nil if the connection is gracefully closed. + # @returns [String | Nil] the line read, or nil if the connection is closed. # @raises [LineLengthError] if the line is too long. # @raises [ProtocolError] if the line is not terminated properly. def read_line? @@ -366,8 +366,9 @@ def read_line? end return line - - # I considered rescuing Errno::ECONNRESET here, but it seems like that would be ignoring a potentially serious error. + # If a connection is shut down abruptly, we treat it as EOF, but only specifically in `read_line?`. + rescue Errno::ECONNRESET + return nil end # Read a line from the connection. diff --git a/releases.md b/releases.md index ac83d5a..13ad2ac 100644 --- a/releases.md +++ b/releases.md @@ -3,6 +3,7 @@ ## Unreleased - Tidy up implementation of `read_line?` to handle line length errors and protocol violations more clearly. + - Improve error handling for unexpected connection closures (`Errno::ECONNRESET`) in `read_line?`. ## v0.35.0 diff --git a/test/protocol/http1/connection.rb b/test/protocol/http1/connection.rb index f6fa283..185f465 100644 --- a/test/protocol/http1/connection.rb +++ b/test/protocol/http1/connection.rb @@ -48,6 +48,12 @@ server.read_line? end.to raise_exception(Protocol::HTTP1::ProtocolError) end + + it "returns nil on Errno::ECONNRESET" do + expect(server.stream).to receive(:gets).and_raise(Errno::ECONNRESET) + + expect(server.read_line?).to be_nil + end end with "#read_request" do