class Stream < HTTP2::Stream
- Inherits from
HTTP2::Stream: #add_header, #receive_trailing_headers, #process_headers, #wait_for_input, #prepare_input, #update_local_window, #process_data, #finish_input, #send_body, #finish_output, #window_updated, #send_headers, #send_data
Represents the HTTP/2 stream associated with an incoming server-side request.
Definitions
def initialize(*)
Initialize the request stream.
Implementation
def initialize(*)
super
@enqueued = false
@request = Request.new(self)
end
def fail_request(status, error)
Write a failure response with the given status code and error class name.
Signature
-
parameter
statusInteger The HTTP status code to send.
-
parameter
errorException The error which caused the request to fail.
Implementation
def fail_request(status, error)
body = error.class.name
headers = [
[STATUS, status.to_s],
["content-type", "text/plain; charset=utf-8"],
]
if @request.head?
send_headers(headers, ::Protocol::HTTP2::END_STREAM)
else
send_headers(headers)
send_data(body, ::Protocol::HTTP2::END_STREAM)
end
# The peer may still be sending a request body. The response is complete, so release the stream without reporting a protocol error.
send_reset_stream(::Protocol::HTTP2::Error::NO_ERROR) unless closed?
rescue => error
Console.debug(self, "Failed to write failure response!", error)
end
def receive_initial_headers(headers, end_stream)
Process the initial headers received from the client and construct the request.
Signature
-
parameter
headersArray The list of header key-value pairs.
-
parameter
end_streamBoolean Whether the stream is complete after these headers.
Implementation
def receive_initial_headers(headers, end_stream)
@headers = ::Protocol::HTTP::Headers.new
headers.each do |key, value|
if key == SCHEME
raise ::Protocol::HTTP2::HeaderError, "Request scheme already specified!" if @request.scheme
@request.scheme = value
elsif key == AUTHORITY
raise ::Protocol::HTTP2::HeaderError, "Request authority already specified!" if @request.authority
@request.authority = value
elsif key == METHOD
raise ::Protocol::HTTP2::HeaderError, "Request method already specified!" if @request.method
@request.method = value
elsif key == PATH
raise ::Protocol::HTTP2::HeaderError, "Request path is empty!" if value.empty?
raise ::Protocol::HTTP2::HeaderError, "Request path already specified!" if @request.path
@request.path = value
elsif key == PROTOCOL
raise ::Protocol::HTTP2::HeaderError, "Request protocol already specified!" if @request.protocol
@request.protocol = value
elsif key == CONTENT_LENGTH
raise ::Protocol::HTTP2::HeaderError, "Request content length already specified!" if @length
@length = Integer(value)
elsif key == CONNECTION
raise ::Protocol::HTTP2::HeaderError, "Connection header is not allowed!"
elsif key.start_with? ":"
raise ::Protocol::HTTP2::HeaderError, "Invalid pseudo-header #{key}!"
elsif key =~ /[A-Z]/
raise ::Protocol::HTTP2::HeaderError, "Invalid characters in header #{key}!"
else
add_header(key, value)
end
end
unless @request.valid?
raise ::Protocol::HTTP2::HeaderError, "Request is missing required headers!"
else
# Validate structured headers before exposing the request to the application:
@headers.to_h
@request.headers = @headers
# We only construct the input/body if data is coming.
unless end_stream
@request.body = prepare_input(@length)
end
# We are ready for processing:
@connection.requests.enqueue(@request)
end
return headers
rescue ::Protocol::HTTP::BadRequest => error
fail_request(400, error)
end
def closed(error)
Called when the stream is closed.
Signature
-
parameter
errorException | Nil The error that caused the close, if any.
Implementation
def closed(error)
@request = nil
super
end