class Async::HTTP::Protocol::HTTP2::Response::Stream
Represents the HTTP/2 stream associated with an outgoing client-side response.
def accept_push_promise_stream(promised_stream_id, headers)
@parameter promised_stream_id [Integer] The stream ID for the promised resource.
Handle a push promise stream from the server.
def accept_push_promise_stream(promised_stream_id, headers) raise ProtocolError, "Cannot accept push promise stream!" end
def closed(error)
Called when the stream is closed.
def closed(error) super if @response @response = nil end unless @ready.resolved? error ||= EOFError.new("Stream closed before response headers were received!") @ready.reject(error) end end
def initialize(*)
def initialize(*) super @response = Response.new(self) @ready = Async::Promise.new end
def receive_initial_headers(headers, end_stream)
def receive_initial_headers(headers, end_stream) # While in theory, the response pseudo-headers may be extended in the future, currently they only response pseudo-header is :status, so we can assume it is always the first header. status_header = headers.shift if status_header.first != ":status" raise ProtocolError, "Invalid response headers: #{headers.inspect}" end status = Integer(status_header.last) if status >= 100 && status < 200 return receive_interim_headers(status, headers) end @response.status = status @headers = ::Protocol::HTTP::Headers.new # If the protocol request was successful, ensure the response protocol matches: if status == 200 and protocol = @response.request.protocol @response.protocol = Array(protocol).first end headers.each do |key, value| # It's guaranteed that this should be the first header: if key == CONTENT_LENGTH @length = Integer(value) else add_header(key, value) end end @response.headers = @headers if @response.valid? if !end_stream # We only construct the input/body if data is coming. @response.body = prepare_input(@length) elsif @response.head? @response.body = ::Protocol::HTTP::Body::Head.new(@length) end else send_reset_stream(::Protocol::HTTP2::Error::PROTOCOL_ERROR) end @ready.resolve(nil) return headers end
def receive_interim_headers(status, headers)
@parameter status [Integer] The interim status code.
Process interim (1xx) response headers.
def receive_interim_headers(status, headers) if headers.any? headers = ::Protocol::HTTP::Headers[headers] else headers = nil end @response.request.send_interim_response(status, headers) end
def wait
def wait @ready.wait rescue ::Protocol::HTTP2::StreamError => error if error.code == ::Protocol::HTTP2::Error::INTERNAL_ERROR raise ::Protocol::HTTP::RemoteError, error.message end raise end
def wait_for_input
Wait for the response headers and return the response body.
def wait_for_input response = @response # The input isn't ready until the response headers have been received: response.wait # There is a possible race condition if you try to access @input - it might already be closed and nil. return response.body end