Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions lib/protocol/http2/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,33 @@ class Error < HTTP::Error

# The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
HTTP_1_1_REQUIRED = 0xD

MESSAGES = {
NO_ERROR => "No error.",
PROTOCOL_ERROR => "Protocol error!",
INTERNAL_ERROR => "Internal error!",
FLOW_CONTROL_ERROR => "Flow control error!",
SETTINGS_TIMEOUT => "Settings timeout!",
STREAM_CLOSED => "Stream closed!",
FRAME_SIZE_ERROR => "Frame size error!",
REFUSED_STREAM => "Stream refused.",
CANCEL => "Stream cancelled.",
COMPRESSION_ERROR => "Compression error!",
CONNECT_ERROR => "Connect error!",
ENHANCE_YOUR_CALM => "Enhance your calm!",
INADEQUATE_SECURITY => "Inadequate security!",
HTTP_1_1_REQUIRED => "HTTP/1.1 required.",
}

# Get the message for a given HTTP/2 error code.
# @parameter code [Integer] The HTTP/2 error code.
# @returns [String] The error message.
def self.message_for(code)
return MESSAGES.fetch(code) do
# Unknown error codes are allowed by the protocol, but don't have a static message.
"Unknown code: #{code}!"
end
end
end

# Raised if connection header is missing or invalid indicating that
Expand All @@ -62,6 +89,13 @@ class HandshakeError < Error
# which signals termination of the current connection. You *cannot*
# recover from this exception, or any exceptions subclassed from it.
class ProtocolError < Error
# Build a protocol error for a given HTTP/2 error code.
# @parameter code [Integer] The HTTP/2 error code.
# @returns [ProtocolError] The protocol error.
def self.for(code)
return self.new(Error.message_for(code), code)
end

# Initialize a protocol error with message and error code.
# @parameter message [String] The error message.
# @parameter code [Integer] The HTTP/2 error code.
Expand Down
2 changes: 1 addition & 1 deletion lib/protocol/http2/stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def close!(error_code = nil)
if error_code == REFUSED_STREAM
error = ::Protocol::HTTP::RefusedError.new("Stream refused.")
else
error = StreamError.new("Stream closed!", error_code)
error = StreamError.for(error_code)
end
end

Expand Down
4 changes: 4 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Releases

## Unreleased

- Improve `StreamError` messages for HTTP/2 stream reset error codes.

## v0.26.0

- On RST\_STREAM with REFUSED\_STREAM, close the stream with `Protocol::HTTP::RefusedError` instead of `StreamError`.
Expand Down
44 changes: 44 additions & 0 deletions test/protocol/http2/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,50 @@

require "protocol/http2/error"

describe Protocol::HTTP2::Error do
with ".message_for" do
it "returns a static message for a known error code" do
expect(subject.message_for(subject::CANCEL)).to be == "Stream cancelled."
end

it "returns a fallback message for an unknown error code" do
expect(subject.message_for(99)).to be == "Unknown code: 99!"
end
end
end

describe Protocol::HTTP2::ProtocolError do
with ".for" do
it "builds a protocol error for a known error code" do
error = subject.for(subject::PROTOCOL_ERROR)

expect(error).to be_a(subject)
expect(error.message).to be == "Protocol error!"
expect(error.code).to be == subject::PROTOCOL_ERROR
end
end
end

describe Protocol::HTTP2::StreamError do
with ".for" do
it "builds a stream error for a known error code" do
error = subject.for(Protocol::HTTP2::Error::CANCEL)

expect(error).to be_a(subject)
expect(error.message).to be == "Stream cancelled."
expect(error.code).to be == Protocol::HTTP2::Error::CANCEL
end

it "builds a stream error for an unknown error code" do
error = subject.for(99)

expect(error).to be_a(subject)
expect(error.message).to be == "Unknown code: 99!"
expect(error.code).to be == 99
end
end
end

describe Protocol::HTTP2::HeaderError do
let(:error) {subject.new("Invalid header key")}

Expand Down
Loading