class Async::HTTP::Protocol::HTTP2::Response

Typically used on the client side for writing a request and reading the incoming response.

Attributes

request[R]
stream[R]

Public Class Methods

new(stream) click to toggle source
Calls superclass method
# File lib/async/http/protocol/http2/response.rb, line 119
def initialize(stream)
        super(stream.connection.version, nil, nil)
        
        @stream = stream
        @request = nil
end

Public Instance Methods

build_request(headers) click to toggle source
# File lib/async/http/protocol/http2/response.rb, line 145
def build_request(headers)
        request = ::Protocol::HTTP::Request.new
        request.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.start_with? ':'
                        raise ::Protocol::HTTP2::HeaderError, "Invalid pseudo-header #{key}!"
                else
                        request.headers[key] = value
                end
        end
        
        @request = request
end
connection() click to toggle source
# File lib/async/http/protocol/http2/response.rb, line 129
def connection
        @stream.connection
end
head?() click to toggle source
# File lib/async/http/protocol/http2/response.rb, line 137
def head?
        @request&.head?
end
send_request(request) click to toggle source

Send a request and read it into this response.

# File lib/async/http/protocol/http2/response.rb, line 178
def send_request(request)
        @request = request
        
        # https://http2.github.io/http2-spec/#rfc.section.8.1.2.3
        # All HTTP/2 requests MUST include exactly one valid value for the :method, :scheme, and :path pseudo-header fields, unless it is a CONNECT request (Section 8.3). An HTTP request that omits mandatory pseudo-header fields is malformed (Section 8.1.2.6).
        pseudo_headers = [
                [SCHEME, request.scheme],
                [METHOD, request.method],
                [PATH, request.path],
        ]
        
        # To ensure that the HTTP/1.1 request line can be reproduced accurately, this pseudo-header field MUST be omitted when translating from an HTTP/1.1 request that has a request target in origin or asterisk form (see [RFC7230], Section 5.3). Clients that generate HTTP/2 requests directly SHOULD use the :authority pseudo-header field instead of the Host header field.
        if authority = request.authority
                pseudo_headers << [AUTHORITY, authority]
        end
        
        if protocol = request.protocol
                pseudo_headers << [PROTOCOL, protocol]
        end
        
        headers = ::Protocol::HTTP::Headers::Merged.new(
                pseudo_headers,
                request.headers
        )
        
        if request.body.nil?
                @stream.send_headers(nil, headers, ::Protocol::HTTP2::END_STREAM)
        else
                if length = request.body.length
                        # This puts it at the end of the pseudo-headers:
                        pseudo_headers << [CONTENT_LENGTH, length]
                end
                
                # This function informs the headers object that any subsequent headers are going to be trailer. Therefore, it must be called *before* sending the headers, to avoid any race conditions.
                trailer = request.headers.trailer!
                
                begin
                        @stream.send_headers(nil, headers)
                rescue
                        raise RequestFailed
                end
                
                @stream.send_body(request.body, trailer)
        end
end
valid?() click to toggle source
# File lib/async/http/protocol/http2/response.rb, line 141
def valid?
        !!@status
end
wait() click to toggle source
# File lib/async/http/protocol/http2/response.rb, line 133
def wait
        @stream.wait
end