Class: Async::HTTP::Protocol::HTTP2::Response
- Inherits:
-
Response
- Object
- Protocol::HTTP::Response
- Response
- Async::HTTP::Protocol::HTTP2::Response
- Defined in:
- lib/async/http/protocol/http2/response.rb
Instance Attribute Summary collapse
-
#stream ⇒ Object
readonly
Returns the value of attribute stream.
Attributes inherited from Response
Instance Method Summary collapse
- #accept_push_promise_stream(promised_stream_id, headers) ⇒ Object
-
#close! ⇒ Object
Stream state transition into ‘:closed`.
-
#initialize(connection, stream_id) ⇒ Response
constructor
A new instance of Response.
- #promises ⇒ Object
- #receive_data(stream, data, end_stream) ⇒ Object
-
#receive_headers(stream, headers, end_stream) ⇒ Object
This should be invoked from the background reader, and notifies the task waiting for the headers that we are done.
- #receive_reset_stream(stream, error_code) ⇒ Object
-
#send_request(request) ⇒ Object
Send a request and read it into this response.
- #stop_connection(error) ⇒ Object
-
#wait ⇒ Object
Wait for the headers to be received or for stream reset.
Methods inherited from Response
#hijack?, #peer, #remote_address, #remote_address=
Constructor Details
#initialize(connection, stream_id) ⇒ Response
Returns a new instance of Response.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/async/http/protocol/http2/response.rb', line 28 def initialize(connection, stream_id) @input = nil @length = nil super(connection.version, nil, ::Protocol::HTTP::Headers.new) @connection = connection @stream = Stream.new(self, connection, stream_id) @notification = Async::Notification.new @exception = nil @promises = nil end |
Instance Attribute Details
#stream ⇒ Object (readonly)
Returns the value of attribute stream.
43 44 45 |
# File 'lib/async/http/protocol/http2/response.rb', line 43 def stream @stream end |
Instance Method Details
#accept_push_promise_stream(promised_stream_id, headers) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/async/http/protocol/http2/response.rb', line 49 def accept_push_promise_stream(promised_stream_id, headers) @connection.accept_push_promise_stream(promised_stream_id) do promise = Promise.new(@connection, headers, promised_stream_id) self.promises.enqueue(promise) end end |
#close! ⇒ Object
Stream state transition into ‘:closed`.
58 59 60 |
# File 'lib/async/http/protocol/http2/response.rb', line 58 def close! self.promises.enqueue(nil) end |
#promises ⇒ Object
45 46 47 |
# File 'lib/async/http/protocol/http2/response.rb', line 45 def promises @promises ||= Async::Queue.new end |
#receive_data(stream, data, end_stream) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/async/http/protocol/http2/response.rb', line 107 def receive_data(stream, data, end_stream) unless data.empty? @input.write(data) end if end_stream @input.close end rescue @stream.send_reset_stream(0) end |
#receive_headers(stream, headers, end_stream) ⇒ Object
This should be invoked from the background reader, and notifies the task waiting for the headers that we are done.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/async/http/protocol/http2/response.rb', line 87 def receive_headers(stream, headers, end_stream) headers.each do |key, value| if key == STATUS @status = Integer(value) elsif key == CONTENT_LENGTH @length = Integer(value) elsif key == PROTOCOL @protocol = value else @headers[key] = value end end unless end_stream @body = @input = Body::Writable.new(@length) end notify! end |
#receive_reset_stream(stream, error_code) ⇒ Object
119 120 121 122 123 124 125 |
# File 'lib/async/http/protocol/http2/response.rb', line 119 def receive_reset_stream(stream, error_code) if error_code > 0 @exception = EOFError.new("Stream reset: error_code=#{error_code}") end notify! end |
#send_request(request) ⇒ Object
Send a request and read it into this response.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/async/http/protocol/http2/response.rb', line 134 def send_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 = request. pseudo_headers << [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 begin @stream.send_headers(nil, headers) rescue raise RequestFailed end @stream.send_body(request.body) end end |
#stop_connection(error) ⇒ Object
127 128 129 130 131 |
# File 'lib/async/http/protocol/http2/response.rb', line 127 def stop_connection(error) @exception = error notify! end |
#wait ⇒ Object
Wait for the headers to be received or for stream reset.
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/async/http/protocol/http2/response.rb', line 75 def wait # If you call wait after the headers were already received, it should return immediately. if @notification @notification.wait end if @exception raise @exception end end |