async-http 0.94.2 → 0.94.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/async/http/body/hijack.rb +17 -0
  4. data/lib/async/http/body/pipe.rb +3 -0
  5. data/lib/async/http/body.rb +3 -0
  6. data/lib/async/http/client.rb +16 -4
  7. data/lib/async/http/endpoint.rb +33 -0
  8. data/lib/async/http/internet.rb +7 -0
  9. data/lib/async/http/middleware/location_redirector.rb +9 -0
  10. data/lib/async/http/mock/endpoint.rb +10 -0
  11. data/lib/async/http/protocol/configurable.rb +15 -0
  12. data/lib/async/http/protocol/http1/client.rb +3 -0
  13. data/lib/async/http/protocol/http1/connection.rb +13 -0
  14. data/lib/async/http/protocol/http1/finishable.rb +9 -0
  15. data/lib/async/http/protocol/http1/request.rb +22 -0
  16. data/lib/async/http/protocol/http1/response.rb +10 -0
  17. data/lib/async/http/protocol/http1/server.rb +7 -0
  18. data/lib/async/http/protocol/http1.rb +1 -0
  19. data/lib/async/http/protocol/http10.rb +1 -0
  20. data/lib/async/http/protocol/http11.rb +1 -0
  21. data/lib/async/http/protocol/http2/client.rb +10 -0
  22. data/lib/async/http/protocol/http2/connection.rb +16 -0
  23. data/lib/async/http/protocol/http2/input.rb +5 -0
  24. data/lib/async/http/protocol/http2/output.rb +13 -0
  25. data/lib/async/http/protocol/http2/request.rb +17 -0
  26. data/lib/async/http/protocol/http2/response.rb +23 -0
  27. data/lib/async/http/protocol/http2/server.rb +16 -0
  28. data/lib/async/http/protocol/http2/stream.rb +19 -0
  29. data/lib/async/http/protocol/http2.rb +1 -0
  30. data/lib/async/http/protocol/https.rb +7 -0
  31. data/lib/async/http/protocol/request.rb +9 -1
  32. data/lib/async/http/protocol/response.rb +6 -1
  33. data/lib/async/http/proxy.rb +12 -0
  34. data/lib/async/http/server.rb +14 -0
  35. data/lib/async/http/statistics.rb +19 -0
  36. data/lib/async/http/version.rb +3 -1
  37. data/lib/async/http.rb +0 -3
  38. data/readme.md +20 -4
  39. data/releases.md +4 -0
  40. data.tar.gz.sig +0 -0
  41. metadata +3 -3
  42. metadata.gz.sig +0 -0
@@ -10,7 +10,12 @@ module Async
10
10
  module HTTP
11
11
  module Protocol
12
12
  module HTTP1
13
+ # An HTTP/1 response received from a server.
13
14
  class Response < Protocol::Response
15
+ # Read the response from the connection, handling interim responses.
16
+ # @parameter connection [Connection] The HTTP/1 connection to read from.
17
+ # @parameter request [Request] The original request.
18
+ # @returns [Response | Nil] The final response.
14
19
  def self.read(connection, request)
15
20
  while parts = connection.read_response(request.method)
16
21
  response = self.new(connection, *parts)
@@ -39,6 +44,8 @@ module Async
39
44
  super(version, status, headers, body, protocol)
40
45
  end
41
46
 
47
+ # Assign the connection pool, releasing the connection if it is already idle or closed.
48
+ # @parameter pool [Async::Pool::Controller] The connection pool.
42
49
  def pool=(pool)
43
50
  if @connection.idle? or @connection.closed?
44
51
  pool.release(@connection)
@@ -47,14 +54,17 @@ module Async
47
54
  end
48
55
  end
49
56
 
57
+ # @returns [Connection] The underlying HTTP/1 connection.
50
58
  def connection
51
59
  @connection
52
60
  end
53
61
 
62
+ # @returns [Boolean] Whether connection hijacking is available (when the body is `nil`).
54
63
  def hijack?
55
64
  @body.nil?
56
65
  end
57
66
 
67
+ # Hijack the underlying connection for bidirectional communication.
58
68
  def hijack!
59
69
  @connection.hijack!
60
70
  end
@@ -16,19 +16,24 @@ module Async
16
16
  module HTTP
17
17
  module Protocol
18
18
  module HTTP1
19
+ # An HTTP/1 server connection that receives requests and sends responses.
19
20
  class Server < Connection
21
+ # Initialize the HTTP/1 server connection.
20
22
  def initialize(...)
21
23
  super
22
24
 
23
25
  @ready = Async::Notification.new
24
26
  end
25
27
 
28
+ # Called when the connection is closed, signalling any waiting tasks.
26
29
  def closed(error = nil)
27
30
  super
28
31
 
29
32
  @ready.signal
30
33
  end
31
34
 
35
+ # Write a failure response with the given status code.
36
+ # @parameter status [Integer] The HTTP status code to send.
32
37
  def fail_request(status)
33
38
  @persistent = false
34
39
  write_response(@version, status, {})
@@ -38,6 +43,8 @@ module Async
38
43
  Console.debug(self, "Failed to write failure response!", error)
39
44
  end
40
45
 
46
+ # Read the next incoming request from the connection.
47
+ # @returns [Request | Nil] The next request, or `nil` if the connection is closed.
41
48
  def next_request
42
49
  if closed?
43
50
  return nil
@@ -14,6 +14,7 @@ require "io/stream"
14
14
  module Async
15
15
  module HTTP
16
16
  module Protocol
17
+ # Provides HTTP/1.0 and HTTP/1.1 client and server implementations.
17
18
  module HTTP1
18
19
  extend Configurable
19
20
 
@@ -9,6 +9,7 @@ require_relative "http1"
9
9
  module Async
10
10
  module HTTP
11
11
  module Protocol
12
+ # Provides an HTTP/1.0 client and server protocol implementation.
12
13
  module HTTP10
13
14
  extend Configurable
14
15
 
@@ -10,6 +10,7 @@ require_relative "http1"
10
10
  module Async
11
11
  module HTTP
12
12
  module Protocol
13
+ # Provides an HTTP/1.1 client and server protocol implementation.
13
14
  module HTTP11
14
15
  extend Configurable
15
16
 
@@ -12,9 +12,12 @@ module Async
12
12
  module HTTP
13
13
  module Protocol
14
14
  module HTTP2
15
+ # An HTTP/2 client connection that sends requests and reads responses.
15
16
  class Client < ::Protocol::HTTP2::Client
16
17
  include Connection
17
18
 
19
+ # Initialize the HTTP/2 client with an IO stream.
20
+ # @parameter stream [IO::Stream] The underlying stream.
18
21
  def initialize(stream)
19
22
  @stream = stream
20
23
 
@@ -23,6 +26,8 @@ module Async
23
26
  super(framer)
24
27
  end
25
28
 
29
+ # Create a new response stream for the next request.
30
+ # @returns [Response] The response object to be populated.
26
31
  def create_response
27
32
  Response::Stream.create(self, self.next_stream_id).response
28
33
  end
@@ -38,10 +43,15 @@ module Async
38
43
  return response
39
44
  end
40
45
 
46
+ # Write a request to the remote server via the given response stream.
47
+ # @parameter response [Response] The response stream to write through.
48
+ # @parameter request [Protocol::HTTP::Request] The request to send.
41
49
  def write_request(response, request)
42
50
  response.send_request(request)
43
51
  end
44
52
 
53
+ # Wait for the response headers to arrive.
54
+ # @parameter response [Response] The response to wait on.
45
55
  def read_response(response)
46
56
  response.wait
47
57
  end
@@ -26,7 +26,9 @@ module Async
26
26
  CONNECTION = "connection".freeze
27
27
  TRAILER = "trailer".freeze
28
28
 
29
+ # Provides shared connection behaviour for HTTP/2 client and server connections.
29
30
  module Connection
31
+ # Initialize the connection state.
30
32
  def initialize(...)
31
33
  super
32
34
 
@@ -36,36 +38,45 @@ module Async
36
38
  @write_frame_guard = Async::Semaphore.new(1)
37
39
  end
38
40
 
41
+ # Synchronize write access to the connection.
42
+ # @yields {|...| ...} The block to execute while holding the write lock.
39
43
  def synchronize(&block)
40
44
  @write_frame_guard.acquire(&block)
41
45
  end
42
46
 
47
+ # @returns [String] A string representation of this connection.
43
48
  def to_s
44
49
  "\#<#{self.class} #{@streams.count} active streams>"
45
50
  end
46
51
 
52
+ # @returns [String] A JSON-compatible representation.
47
53
  def as_json(...)
48
54
  to_s
49
55
  end
50
56
 
57
+ # @returns [String] A JSON string representation.
51
58
  def to_json(...)
52
59
  as_json.to_json(...)
53
60
  end
54
61
 
55
62
  attr :stream
56
63
 
64
+ # @returns [Boolean] Whether this is an HTTP/1 connection.
57
65
  def http1?
58
66
  false
59
67
  end
60
68
 
69
+ # @returns [Boolean] Whether this is an HTTP/2 connection.
61
70
  def http2?
62
71
  true
63
72
  end
64
73
 
74
+ # Start the background reader task if it is not already running.
65
75
  def start_connection
66
76
  @reader || read_in_background
67
77
  end
68
78
 
79
+ # Close the connection and stop the background reader.
69
80
  def close(error = nil)
70
81
  # Ensure the reader task is stopped.
71
82
  if @reader
@@ -77,6 +88,7 @@ module Async
77
88
  super
78
89
  end
79
90
 
91
+ # Start a transient background task that reads frames from the connection.
80
92
  def read_in_background(parent: Task.current)
81
93
  raise RuntimeError, "Connection is closed!" if closed?
82
94
 
@@ -106,12 +118,14 @@ module Async
106
118
 
107
119
  attr :promises
108
120
 
121
+ # @returns [Protocol::HTTP::Peer] The peer information for this connection.
109
122
  def peer
110
123
  @peer ||= ::Protocol::HTTP::Peer.for(@stream.io)
111
124
  end
112
125
 
113
126
  attr :count
114
127
 
128
+ # @returns [Integer] The maximum number of concurrent streams allowed.
115
129
  def concurrency
116
130
  self.maximum_concurrent_streams
117
131
  end
@@ -121,10 +135,12 @@ module Async
121
135
  @stream&.readable?
122
136
  end
123
137
 
138
+ # @returns [Boolean] Whether the connection can be reused.
124
139
  def reusable?
125
140
  !self.closed?
126
141
  end
127
142
 
143
+ # @returns [String] The HTTP version string.
128
144
  def version
129
145
  VERSION
130
146
  end
@@ -11,6 +11,9 @@ module Async
11
11
  module HTTP2
12
12
  # A writable body which requests window updates when data is read from it.
13
13
  class Input < ::Protocol::HTTP::Body::Writable
14
+ # Initialize the input body.
15
+ # @parameter stream [Stream] The HTTP/2 stream to read from.
16
+ # @parameter length [Integer | Nil] The expected content length.
14
17
  def initialize(stream, length)
15
18
  super(length)
16
19
 
@@ -18,6 +21,8 @@ module Async
18
21
  @remaining = length
19
22
  end
20
23
 
24
+ # Read the next chunk of data, requesting window updates as needed.
25
+ # @returns [String | Nil] The next chunk, or `nil` if the body is complete.
21
26
  def read
22
27
  if chunk = super
23
28
  # If we read a chunk fron the stream, we want to extend the window if required so more data will be provided.
@@ -9,7 +9,12 @@ module Async
9
9
  module HTTP
10
10
  module Protocol
11
11
  module HTTP2
12
+ # Writes body data to an HTTP/2 stream, respecting flow control windows.
12
13
  class Output
14
+ # Initialize the output handler.
15
+ # @parameter stream [Stream] The HTTP/2 stream to write to.
16
+ # @parameter body [Protocol::HTTP::Body::Readable] The body to read from.
17
+ # @parameter trailer [Protocol::HTTP::Headers | Nil] Optional trailing headers.
13
18
  def initialize(stream, body, trailer = nil)
14
19
  @stream = stream
15
20
  @body = body
@@ -23,6 +28,7 @@ module Async
23
28
 
24
29
  attr :trailer
25
30
 
31
+ # Start an asynchronous task to write the body to the stream.
26
32
  def start(parent: Task.current)
27
33
  raise "Task already started!" if @task
28
34
 
@@ -33,6 +39,9 @@ module Async
33
39
  end
34
40
  end
35
41
 
42
+ # Signal that the flow control window has been updated.
43
+ # @parameter size [Integer] The new window size.
44
+ # @returns [Boolean] Always returns `true`.
36
45
  def window_updated(size)
37
46
  @guard.synchronize do
38
47
  @window_updated.signal
@@ -41,6 +50,8 @@ module Async
41
50
  return true
42
51
  end
43
52
 
53
+ # Write a chunk of data to the HTTP/2 stream, respecting flow control.
54
+ # @parameter chunk [String] The data to write.
44
55
  def write(chunk)
45
56
  until chunk.empty?
46
57
  maximum_size = @stream.available_frame_size
@@ -62,6 +73,8 @@ module Async
62
73
  end
63
74
  end
64
75
 
76
+ # Finish writing to the stream.
77
+ # @parameter error [Exception | Nil] An optional error that caused the close.
65
78
  def close_write(error = nil)
66
79
  if stream = @stream
67
80
  @stream = nil
@@ -12,7 +12,9 @@ module Async
12
12
  module HTTP2
13
13
  # Typically used on the server side to represent an incoming request, and write the response.
14
14
  class Request < Protocol::Request
15
+ # Represents the HTTP/2 stream associated with an incoming server-side request.
15
16
  class Stream < HTTP2::Stream
17
+ # Initialize the request stream.
16
18
  def initialize(*)
17
19
  super
18
20
 
@@ -22,6 +24,9 @@ module Async
22
24
 
23
25
  attr :request
24
26
 
27
+ # Process the initial headers received from the client and construct the request.
28
+ # @parameter headers [Array] The list of header key-value pairs.
29
+ # @parameter end_stream [Boolean] Whether the stream is complete after these headers.
25
30
  def receive_initial_headers(headers, end_stream)
26
31
  @headers = ::Protocol::HTTP::Headers.new
27
32
 
@@ -79,6 +84,8 @@ module Async
79
84
  return headers
80
85
  end
81
86
 
87
+ # Called when the stream is closed.
88
+ # @parameter error [Exception | Nil] The error that caused the close, if any.
82
89
  def closed(error)
83
90
  @request = nil
84
91
 
@@ -86,6 +93,8 @@ module Async
86
93
  end
87
94
  end
88
95
 
96
+ # Initialize the request from an HTTP/2 stream.
97
+ # @parameter stream [Stream] The HTTP/2 stream for this request.
89
98
  def initialize(stream)
90
99
  super(nil, nil, nil, nil, VERSION, nil, nil, nil, self.public_method(:write_interim_response))
91
100
 
@@ -94,14 +103,17 @@ module Async
94
103
 
95
104
  attr :stream
96
105
 
106
+ # @returns [Connection] The underlying HTTP/2 connection.
97
107
  def connection
98
108
  @stream.connection
99
109
  end
100
110
 
111
+ # @returns [Boolean] Whether the request has the required pseudo-headers.
101
112
  def valid?
102
113
  @scheme and @method and (@path or @method == ::Protocol::HTTP::Methods::CONNECT)
103
114
  end
104
115
 
116
+ # @returns [Boolean] Whether connection hijacking is supported (not available for HTTP/2).
105
117
  def hijack?
106
118
  false
107
119
  end
@@ -110,6 +122,8 @@ module Async
110
122
  [STATUS, "500"],
111
123
  ]
112
124
 
125
+ # Send a response back to the client via the HTTP/2 stream.
126
+ # @parameter response [Protocol::HTTP::Response | Nil] The response to send.
113
127
  def send_response(response)
114
128
  if response.nil?
115
129
  return @stream.send_headers(NO_RESPONSE, ::Protocol::HTTP2::END_STREAM)
@@ -143,6 +157,9 @@ module Async
143
157
  end
144
158
  end
145
159
 
160
+ # Write an interim (1xx) response to the client.
161
+ # @parameter status [Integer] The interim HTTP status code.
162
+ # @parameter headers [Hash | Nil] Optional interim response headers.
146
163
  def write_interim_response(status, headers = nil)
147
164
  interim_response_headers = [
148
165
  [STATUS, status]
@@ -12,7 +12,9 @@ module Async
12
12
  module HTTP2
13
13
  # Typically used on the client side for writing a request and reading the incoming response.
14
14
  class Response < Protocol::Response
15
+ # Represents the HTTP/2 stream associated with an outgoing client-side response.
15
16
  class Stream < HTTP2::Stream
17
+ # Initialize the response stream.
16
18
  def initialize(*)
17
19
  super
18
20
 
@@ -24,6 +26,8 @@ module Async
24
26
 
25
27
  attr :response
26
28
 
29
+ # Wait for the response headers and return the response body.
30
+ # @returns [Protocol::HTTP::Body::Readable | Nil] The response body.
27
31
  def wait_for_input
28
32
  # The input isn't ready until the response headers have been received:
29
33
  @response.wait
@@ -32,6 +36,9 @@ module Async
32
36
  return @response.body
33
37
  end
34
38
 
39
+ # Handle a push promise stream from the server.
40
+ # @parameter promised_stream_id [Integer] The stream ID for the promised resource.
41
+ # @parameter headers [Array] The promise headers.
35
42
  def accept_push_promise_stream(promised_stream_id, headers)
36
43
  raise ProtocolError, "Cannot accept push promise stream!"
37
44
  end
@@ -86,6 +93,9 @@ module Async
86
93
  return headers
87
94
  end
88
95
 
96
+ # Process interim (1xx) response headers.
97
+ # @parameter status [Integer] The interim status code.
98
+ # @parameter headers [Array] The interim response headers.
89
99
  def receive_interim_headers(status, headers)
90
100
  if headers.any?
91
101
  headers = ::Protocol::HTTP::Headers[headers]
@@ -114,6 +124,8 @@ module Async
114
124
  end
115
125
  end
116
126
 
127
+ # Called when the stream is closed.
128
+ # @parameter error [Exception | Nil] The error that caused the close, if any.
117
129
  def closed(error)
118
130
  super
119
131
 
@@ -127,6 +139,8 @@ module Async
127
139
  end
128
140
  end
129
141
 
142
+ # Initialize the response from an HTTP/2 stream.
143
+ # @parameter stream [Stream] The HTTP/2 stream for this response.
130
144
  def initialize(stream)
131
145
  super(stream.connection.version, nil, nil)
132
146
 
@@ -137,6 +151,8 @@ module Async
137
151
  attr :stream
138
152
  attr :request
139
153
 
154
+ # Assign the connection pool, releasing the connection when the stream is closed.
155
+ # @parameter pool [Async::Pool::Controller] The connection pool.
140
156
  def pool=(pool)
141
157
  # If we are already closed, the stream can be released now:
142
158
  if @stream.closed?
@@ -147,22 +163,29 @@ module Async
147
163
  end
148
164
  end
149
165
 
166
+ # @returns [Connection] The underlying HTTP/2 connection.
150
167
  def connection
151
168
  @stream.connection
152
169
  end
153
170
 
171
+ # Wait for the response headers to be received.
154
172
  def wait
155
173
  @stream.wait
156
174
  end
157
175
 
176
+ # @returns [Boolean] Whether the original request was a HEAD request.
158
177
  def head?
159
178
  @request&.head?
160
179
  end
161
180
 
181
+ # @returns [Boolean] Whether the response has a valid status.
162
182
  def valid?
163
183
  !!@status
164
184
  end
165
185
 
186
+ # Build a request object from push promise headers.
187
+ # @parameter headers [Array] The push promise pseudo-headers and headers.
188
+ # @returns [Protocol::HTTP::Request] The constructed request.
166
189
  def build_request(headers)
167
190
  request = ::Protocol::HTTP::Request.new
168
191
  request.headers = ::Protocol::HTTP::Headers.new
@@ -12,9 +12,12 @@ module Async
12
12
  module HTTP
13
13
  module Protocol
14
14
  module HTTP2
15
+ # An HTTP/2 server connection that receives requests and sends responses.
15
16
  class Server < ::Protocol::HTTP2::Server
16
17
  include Connection
17
18
 
19
+ # Initialize the HTTP/2 server with an IO stream.
20
+ # @parameter stream [IO::Stream] The underlying stream.
18
21
  def initialize(stream)
19
22
  # Used by some generic methods in Connetion:
20
23
  @stream = stream
@@ -28,12 +31,15 @@ module Async
28
31
 
29
32
  attr :requests
30
33
 
34
+ # Accept a new stream from a client.
35
+ # @parameter stream_id [Integer] The stream ID assigned by the client.
31
36
  def accept_stream(stream_id)
32
37
  super do
33
38
  Request::Stream.create(self, stream_id)
34
39
  end
35
40
  end
36
41
 
42
+ # Close the server connection and stop accepting requests.
37
43
  def close(error = nil)
38
44
  if @requests
39
45
  # Stop the request loop:
@@ -44,6 +50,9 @@ module Async
44
50
  super
45
51
  end
46
52
 
53
+ # Enumerate incoming requests, yielding each one for processing.
54
+ # @yields {|request| ...} Each incoming request.
55
+ # @parameter request [Request] The incoming HTTP/2 request.
47
56
  def each(task: Task.current)
48
57
  task.annotate("Reading #{version} requests for #{self.class}.")
49
58
 
@@ -51,6 +60,8 @@ module Async
51
60
  @requests&.async do |task, request|
52
61
  task.annotate("Incoming request: #{request.method} #{request.path.inspect}.")
53
62
 
63
+ response = nil
64
+
54
65
  task.defer_stop do
55
66
  response = yield(request)
56
67
  rescue
@@ -60,6 +71,11 @@ module Async
60
71
  raise
61
72
  else
62
73
  request.send_response(response)
74
+ # If send response is successful, we clear it so that we don't close it below.
75
+ response = nil
76
+ ensure
77
+ # If some failure occurs and we didn't send the response correctly, ensure that it's closed:
78
+ response&.close
63
79
  end
64
80
  end
65
81
 
@@ -14,7 +14,9 @@ module Async
14
14
  module HTTP
15
15
  module Protocol
16
16
  module HTTP2
17
+ # An HTTP/2 stream that manages headers, input data, and output data for a single request/response exchange.
17
18
  class Stream < ::Protocol::HTTP2::Stream
19
+ # Initialize the stream state.
18
20
  def initialize(*)
19
21
  super
20
22
 
@@ -36,6 +38,9 @@ module Async
36
38
 
37
39
  attr :input
38
40
 
41
+ # Add a header to the stream, validating against HTTP/2 constraints.
42
+ # @parameter key [String] The header name.
43
+ # @parameter value [String] The header value.
39
44
  def add_header(key, value, trailer: false)
40
45
  if key == CONNECTION
41
46
  raise ::Protocol::HTTP2::HeaderError, "Connection header is not allowed!"
@@ -48,12 +53,17 @@ module Async
48
53
  end
49
54
  end
50
55
 
56
+ # Process trailing headers received after the body.
57
+ # @parameter headers [Array] The trailing header key-value pairs.
58
+ # @parameter end_stream [Boolean] Whether the stream ends after these headers.
51
59
  def receive_trailing_headers(headers, end_stream)
52
60
  headers.each do |key, value|
53
61
  add_header(key, value, trailer: true)
54
62
  end
55
63
  end
56
64
 
65
+ # Process an incoming HEADERS frame, dispatching to initial or trailing header handling.
66
+ # @parameter frame [Protocol::HTTP2::HeadersFrame] The headers frame to process.
57
67
  def process_headers(frame)
58
68
  if @headers and frame.end_stream?
59
69
  self.receive_trailing_headers(super, frame.end_stream?)
@@ -74,6 +84,7 @@ module Async
74
84
  send_reset_stream(error.code)
75
85
  end
76
86
 
87
+ # @returns [Input | Nil] The input body for this stream, if available.
77
88
  def wait_for_input
78
89
  return @input
79
90
  end
@@ -88,6 +99,8 @@ module Async
88
99
  end
89
100
  end
90
101
 
102
+ # Update the local flow control window after receiving data.
103
+ # @parameter frame [Protocol::HTTP2::DataFrame] The received data frame.
91
104
  def update_local_window(frame)
92
105
  consume_local_window(frame)
93
106
 
@@ -95,6 +108,9 @@ module Async
95
108
  # request_window_update
96
109
  end
97
110
 
111
+ # Process an incoming DATA frame and write it to the input body.
112
+ # @parameter frame [Protocol::HTTP2::DataFrame] The data frame to process.
113
+ # @returns [String] The unpacked data.
98
114
  def process_data(frame)
99
115
  data = frame.unpack
100
116
 
@@ -142,6 +158,9 @@ module Async
142
158
  end
143
159
  end
144
160
 
161
+ # Called when the flow control window is updated.
162
+ # @parameter size [Integer] The new window size.
163
+ # @returns [Boolean] Always returns `true`.
145
164
  def window_updated(size)
146
165
  super
147
166
 
@@ -14,6 +14,7 @@ require "io/stream"
14
14
  module Async
15
15
  module HTTP
16
16
  module Protocol
17
+ # Provides an HTTP/2 client and server protocol implementation.
17
18
  module HTTP2
18
19
  extend Configurable
19
20
 
@@ -23,11 +23,18 @@ module Async
23
23
  nil => HTTP11,
24
24
  }
25
25
 
26
+ # Initialize the HTTPS protocol negotiator.
27
+ # @parameter handlers [Hash] A mapping of ALPN protocol names to protocol classes.
28
+ # @parameter options [Hash] Per-protocol options keyed by protocol class.
26
29
  def initialize(handlers = HANDLERS, **options)
27
30
  @handlers = handlers
28
31
  @options = options
29
32
  end
30
33
 
34
+ # Register a protocol handler for a given ALPN protocol name.
35
+ # @parameter name [String] The ALPN protocol name.
36
+ # @parameter protocol [Class] The protocol class to handle connections.
37
+ # @parameter options [Hash] Options to pass when creating client or server instances.
31
38
  def add(name, protocol, **options)
32
39
  @handlers[name] = protocol
33
40
  @options[protocol] = options
@@ -15,27 +15,35 @@ module Async
15
15
  class RequestFailed < StandardError
16
16
  end
17
17
 
18
- # This is generated by server protocols.
18
+ # An incoming HTTP request generated by server protocol implementations.
19
19
  class Request < ::Protocol::HTTP::Request
20
+ # @returns [Connection | Nil] The underlying protocol connection.
20
21
  def connection
21
22
  nil
22
23
  end
23
24
 
25
+ # @returns [Boolean] Whether this request supports connection hijacking.
24
26
  def hijack?
25
27
  false
26
28
  end
27
29
 
30
+ # Write an interim (1xx) response back to the client.
31
+ # @parameter status [Integer] The interim HTTP status code.
32
+ # @parameter headers [Hash | Nil] Optional headers to include.
28
33
  def write_interim_response(status, headers = nil)
29
34
  end
30
35
 
36
+ # @returns [Protocol::HTTP::Peer | Nil] The peer associated with this connection.
31
37
  def peer
32
38
  self.connection&.peer
33
39
  end
34
40
 
41
+ # @returns [Addrinfo | Nil] The remote address of the peer.
35
42
  def remote_address
36
43
  self.peer&.address
37
44
  end
38
45
 
46
+ # @returns [String] A string representation of the request.
39
47
  def inspect
40
48
  "#<#{self.class}:0x#{self.object_id.to_s(16)} method=#{method} path=#{path} version=#{version}>"
41
49
  end
@@ -10,24 +10,29 @@ require_relative "../body/writable"
10
10
  module Async
11
11
  module HTTP
12
12
  module Protocol
13
- # This is generated by client protocols.
13
+ # An HTTP response received from a server via client protocol implementations.
14
14
  class Response < ::Protocol::HTTP::Response
15
+ # @returns [Connection | Nil] The underlying protocol connection.
15
16
  def connection
16
17
  nil
17
18
  end
18
19
 
20
+ # @returns [Boolean] Whether this response supports connection hijacking.
19
21
  def hijack?
20
22
  false
21
23
  end
22
24
 
25
+ # @returns [Protocol::HTTP::Peer | Nil] The peer associated with this connection.
23
26
  def peer
24
27
  self.connection&.peer
25
28
  end
26
29
 
30
+ # @returns [Addrinfo | Nil] The remote address of the peer.
27
31
  def remote_address
28
32
  self.peer&.remote_address
29
33
  end
30
34
 
35
+ # @returns [String] A string representation of the response.
31
36
  def inspect
32
37
  "#<#{self.class}:0x#{self.object_id.to_s(16)} status=#{status}>"
33
38
  end