diff --git a/lib/protocol/http1/connection.rb b/lib/protocol/http1/connection.rb index e4f19f2..e43657e 100644 --- a/lib/protocol/http1/connection.rb +++ b/lib/protocol/http1/connection.rb @@ -176,14 +176,15 @@ def hijacked? # @return [IO] the underlying non-blocking IO. def hijack! @persistent = false - stream = @stream - @stream.flush - @stream = nil - - self.closed! - - return stream + if stream = @stream + @stream = nil + stream.flush + + self.closed! + + return stream + end end def close_read @@ -193,10 +194,15 @@ def close_read end # Close the connection and underlying stream. - def close + def close(error = nil) @persistent = false - @stream&.close - self.closed! + + if stream = @stream + @stream = nil + stream.close + end + + self.closed!(error) end def open! @@ -518,13 +524,15 @@ def write_body_and_close(body, head) self.send_end_stream! end - def idle! - @state = :idle - end - - def closed! - if @persistent - self.idle! + # Transition to the closed state. + # + # If no error occurred, and the connection is persistent, this will immediately transition to the idle state. + # + # @parameter error [Exxception] the error that caused the connection to close. + def closed!(error = nil) + if @persistent and !error + # If there was no error, and the connection is persistent, we can reuse it: + @state = :idle else @state = :closed end diff --git a/test/protocol/http1/connection.rb b/test/protocol/http1/connection.rb index a9fbfe4..cb02933 100644 --- a/test/protocol/http1/connection.rb +++ b/test/protocol/http1/connection.rb @@ -677,4 +677,21 @@ server.write_interim_response("HTTP/1.0", 100, {}) end.to raise_exception(Protocol::HTTP1::ProtocolError) end + + with "#close" do + it "enters closed state" do + server.close + expect(server).to be(:closed?) + end + + it "enters closed state when given an error" do + expect(server).to be(:persistent) + error = Protocol::HTTP1::InvalidRequest.new("Invalid request") + + expect(server).to receive(:closed!).with(error) + + server.close(error) + expect(server).to be(:closed?) + end + end end