raptor 0.22.3 → 0.23.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/Dockerfile +3 -1
- data/README.md +38 -31
- data/docs/raptor-vs-puma.md +44 -38
- data/docs/talk.md +1295 -0
- data/ext/raptor_bpf/reuseport_select.bpf.c +18 -9
- data/ext/raptor_http/extconf.rb +2 -0
- data/ext/raptor_http/raptor_http.c +91 -119
- data/ext/raptor_http2/raptor_http2.c +272 -223
- data/ext/raptor_native/raptor_native.c +38 -20
- data/lib/rackup/handler/raptor.rb +12 -11
- data/lib/raptor/binder.rb +12 -12
- data/lib/raptor/cli.rb +18 -18
- data/lib/raptor/cluster.rb +44 -44
- data/lib/raptor/control_server.rb +3 -2
- data/lib/raptor/detached_body.rb +6 -2
- data/lib/raptor/http.rb +7 -5
- data/lib/raptor/http1.rb +232 -207
- data/lib/raptor/http2.rb +312 -265
- data/lib/raptor/reactor.rb +138 -148
- data/lib/raptor/reuseport_bpf.rb +62 -38
- data/lib/raptor/server.rb +45 -34
- data/lib/raptor/stats.rb +15 -3
- data/lib/raptor/thread_locals.rb +4 -3
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/rackup/handler/raptor.rbs +2 -1
- data/sig/generated/raptor/binder.rbs +9 -9
- data/sig/generated/raptor/cli.rbs +6 -6
- data/sig/generated/raptor/cluster.rbs +9 -9
- data/sig/generated/raptor/control_server.rbs +2 -1
- data/sig/generated/raptor/detached_body.rbs +5 -1
- data/sig/generated/raptor/http.rbs +3 -3
- data/sig/generated/raptor/http1.rbs +100 -91
- data/sig/generated/raptor/http2.rbs +200 -189
- data/sig/generated/raptor/reactor.rbs +107 -118
- data/sig/generated/raptor/reuseport_bpf.rbs +54 -17
- data/sig/generated/raptor/server.rbs +26 -26
- data/sig/generated/raptor/stats.rbs +3 -2
- data/sig/generated/raptor/thread_locals.rbs +4 -3
- metadata +2 -2
- data/docs/brisrails-talk.md +0 -2398
|
@@ -3,8 +3,49 @@
|
|
|
3
3
|
module Raptor
|
|
4
4
|
# Handles HTTP/2 request processing and Rack application integration.
|
|
5
5
|
class Http2
|
|
6
|
+
EAGER_READ_BUFFER_SIZE: untyped
|
|
7
|
+
|
|
8
|
+
EAGER_MAX_ROUNDS: ::Integer
|
|
9
|
+
|
|
10
|
+
FLAG_END_STREAM: ::Integer
|
|
11
|
+
|
|
12
|
+
FLAG_ACK: ::Integer
|
|
13
|
+
|
|
14
|
+
FLAG_END_HEADERS: ::Integer
|
|
15
|
+
|
|
16
|
+
FLAG_PADDED: ::Integer
|
|
17
|
+
|
|
18
|
+
FLAG_PRIORITY: ::Integer
|
|
19
|
+
|
|
20
|
+
ERROR_NO_ERROR: ::Integer
|
|
21
|
+
|
|
22
|
+
ERROR_PROTOCOL_ERROR: ::Integer
|
|
23
|
+
|
|
24
|
+
ERROR_INTERNAL_ERROR: ::Integer
|
|
25
|
+
|
|
26
|
+
ERROR_FRAME_SIZE_ERROR: ::Integer
|
|
27
|
+
|
|
28
|
+
ERROR_REFUSED_STREAM: ::Integer
|
|
29
|
+
|
|
30
|
+
ERROR_COMPRESSION_ERROR: ::Integer
|
|
31
|
+
|
|
32
|
+
DEFAULT_WINDOW_SIZE: ::Integer
|
|
33
|
+
|
|
34
|
+
MAX_FRAME_SIZE: ::Integer
|
|
35
|
+
|
|
6
36
|
RESPONSE_TRAILERS: ::String
|
|
7
37
|
|
|
38
|
+
SERVER_PROTOCOL: ::String
|
|
39
|
+
|
|
40
|
+
REQUEST_PSEUDO_HEADERS: untyped
|
|
41
|
+
|
|
42
|
+
REQUIRED_REQUEST_PSEUDO_HEADERS: untyped
|
|
43
|
+
|
|
44
|
+
class StreamClosedError < StandardError
|
|
45
|
+
# @rbs () -> String
|
|
46
|
+
def message: () -> String
|
|
47
|
+
end
|
|
48
|
+
|
|
8
49
|
# Queues concurrent frame writes while the reactor remains the sole
|
|
9
50
|
# owner of the connection socket.
|
|
10
51
|
class Writer
|
|
@@ -34,12 +75,12 @@ module Raptor
|
|
|
34
75
|
# Queues frames for the reactor to write. Before attachment, writes
|
|
35
76
|
# directly so the writer remains usable during connection setup.
|
|
36
77
|
#
|
|
37
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
78
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
38
79
|
# @param frames [Array<String>, nil] frame bytes to write in order
|
|
39
80
|
# @return [void]
|
|
40
81
|
#
|
|
41
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Array[String]? frames) -> void
|
|
42
|
-
def write_frames: (OpenSSL::SSL::SSLSocket socket, Array[String]? frames) -> void
|
|
82
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Array[String]? frames) -> void
|
|
83
|
+
def write_frames: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Array[String]? frames) -> void
|
|
43
84
|
|
|
44
85
|
# Attaches a response body that outlives its application thread.
|
|
45
86
|
#
|
|
@@ -52,11 +93,6 @@ module Raptor
|
|
|
52
93
|
def attach_body: (Integer stream_id, DetachedBody body, ^(Symbol) -> void finished) -> bool
|
|
53
94
|
end
|
|
54
95
|
|
|
55
|
-
class StreamClosedError < StandardError
|
|
56
|
-
# @rbs () -> String
|
|
57
|
-
def message: () -> String
|
|
58
|
-
end
|
|
59
|
-
|
|
60
96
|
# Coordinates outbound flow control and stream cancellation without
|
|
61
97
|
# polling or mutexes.
|
|
62
98
|
class FlowControl
|
|
@@ -79,11 +115,12 @@ module Raptor
|
|
|
79
115
|
|
|
80
116
|
# Reserves outbound capacity on the given stream, waiting until at
|
|
81
117
|
# least one byte is available on both the connection and stream
|
|
82
|
-
# windows.
|
|
118
|
+
# windows.
|
|
83
119
|
#
|
|
84
120
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
85
121
|
# @param max_bytes [Integer] the largest size the caller would like to send
|
|
86
122
|
# @return [Integer] the number of bytes the caller may now send
|
|
123
|
+
# @raise [StreamClosedError] if the stream or connection has closed
|
|
87
124
|
#
|
|
88
125
|
# @rbs (Integer stream_id, Integer max_bytes) -> Integer
|
|
89
126
|
def acquire: (Integer stream_id, Integer max_bytes) -> Integer
|
|
@@ -93,6 +130,7 @@ module Raptor
|
|
|
93
130
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
94
131
|
# @param max_bytes [Integer] the largest size the caller would like to send
|
|
95
132
|
# @return [Integer] available bytes, or 0 when flow control is exhausted
|
|
133
|
+
# @raise [StreamClosedError] if the stream or connection has closed
|
|
96
134
|
#
|
|
97
135
|
# @rbs (Integer stream_id, Integer max_bytes) -> Integer
|
|
98
136
|
def try_acquire: (Integer stream_id, Integer max_bytes) -> Integer
|
|
@@ -115,7 +153,7 @@ module Raptor
|
|
|
115
153
|
def add_stream_window: (Integer stream_id, Integer increment) -> void
|
|
116
154
|
|
|
117
155
|
# Updates the peer's `SETTINGS_INITIAL_WINDOW_SIZE`. Shifts every
|
|
118
|
-
# existing stream window by the delta as required by RFC
|
|
156
|
+
# existing stream window by the delta as required by RFC 9113 section 6.9.2.
|
|
119
157
|
#
|
|
120
158
|
# @param new_size [Integer] the peer's new initial window size
|
|
121
159
|
# @return [void]
|
|
@@ -157,12 +195,10 @@ module Raptor
|
|
|
157
195
|
|
|
158
196
|
private
|
|
159
197
|
|
|
160
|
-
# Reserves up to `capped` bytes from the connection window
|
|
161
|
-
# returning the number of bytes granted (0 when the window is
|
|
162
|
-
# exhausted).
|
|
198
|
+
# Reserves up to `capped` bytes from the connection window.
|
|
163
199
|
#
|
|
164
200
|
# @param capped [Integer] the largest reservation the caller will accept
|
|
165
|
-
# @return [Integer]
|
|
201
|
+
# @return [Integer] bytes granted, or 0 when the window is exhausted
|
|
166
202
|
#
|
|
167
203
|
# @rbs (Integer capped) -> Integer
|
|
168
204
|
def reserve_connection: (Integer capped) -> Integer
|
|
@@ -184,7 +220,7 @@ module Raptor
|
|
|
184
220
|
|
|
185
221
|
@writer: Writer
|
|
186
222
|
|
|
187
|
-
@socket: OpenSSL::SSL::SSLSocket
|
|
223
|
+
@socket: TCPSocket | OpenSSL::SSL::SSLSocket
|
|
188
224
|
|
|
189
225
|
# Returns the number of response body bytes written to the stream.
|
|
190
226
|
#
|
|
@@ -193,19 +229,19 @@ module Raptor
|
|
|
193
229
|
|
|
194
230
|
# Creates a response stream for a Rack streaming body.
|
|
195
231
|
#
|
|
196
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
232
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
197
233
|
# @param writer [Writer] frame writer for the connection
|
|
198
|
-
# @param flow_control [FlowControl] outbound flow controller
|
|
234
|
+
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
199
235
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
200
236
|
# @param trailers [Hash] trailing response headers populated by the Rack application
|
|
201
237
|
# @return [void]
|
|
202
238
|
#
|
|
203
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] trailers) -> void
|
|
204
|
-
def initialize: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] trailers) -> void
|
|
239
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] trailers) -> void
|
|
240
|
+
def initialize: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] trailers) -> void
|
|
205
241
|
|
|
206
|
-
#
|
|
242
|
+
# Rejects reads; streaming responses are write-only.
|
|
207
243
|
#
|
|
208
|
-
# @raise [IOError]
|
|
244
|
+
# @raise [IOError] always
|
|
209
245
|
#
|
|
210
246
|
# @rbs (*untyped) -> bot
|
|
211
247
|
def read: (*untyped) -> bot
|
|
@@ -214,6 +250,9 @@ module Raptor
|
|
|
214
250
|
#
|
|
215
251
|
# @param chunk [String] response body bytes
|
|
216
252
|
# @return [Integer] number of bytes written
|
|
253
|
+
# @raise [IOError] if the stream has already closed
|
|
254
|
+
# @raise [TypeError] if the chunk is not a String
|
|
255
|
+
# @raise [StreamClosedError] if the stream or connection has closed
|
|
217
256
|
#
|
|
218
257
|
# @rbs (String chunk) -> Integer
|
|
219
258
|
def write: (String chunk) -> Integer
|
|
@@ -226,7 +265,8 @@ module Raptor
|
|
|
226
265
|
# @rbs (String chunk) -> ResponseStream
|
|
227
266
|
def <<: (String chunk) -> ResponseStream
|
|
228
267
|
|
|
229
|
-
# Flushes the stream.
|
|
268
|
+
# Flushes the stream. Frames are already handed to the writer as they
|
|
269
|
+
# are produced.
|
|
230
270
|
#
|
|
231
271
|
# @return [ResponseStream]
|
|
232
272
|
#
|
|
@@ -236,13 +276,14 @@ module Raptor
|
|
|
236
276
|
# Finishes the stream.
|
|
237
277
|
#
|
|
238
278
|
# @return [void]
|
|
279
|
+
# @raise [StreamClosedError] if the stream or connection has closed
|
|
239
280
|
#
|
|
240
281
|
# @rbs () -> void
|
|
241
282
|
def close: () -> void
|
|
242
283
|
|
|
243
284
|
# Closes the unsupported read side of the stream.
|
|
244
285
|
#
|
|
245
|
-
# @raise [IOError]
|
|
286
|
+
# @raise [IOError] always
|
|
246
287
|
#
|
|
247
288
|
# @rbs () -> bot
|
|
248
289
|
def close_read: () -> bot
|
|
@@ -262,113 +303,6 @@ module Raptor
|
|
|
262
303
|
def closed?: () -> bool
|
|
263
304
|
end
|
|
264
305
|
|
|
265
|
-
EAGER_READ_BUFFER_SIZE: untyped
|
|
266
|
-
|
|
267
|
-
EAGER_MAX_ROUNDS: ::Integer
|
|
268
|
-
|
|
269
|
-
FLAG_END_STREAM: ::Integer
|
|
270
|
-
|
|
271
|
-
FLAG_END_HEADERS: ::Integer
|
|
272
|
-
|
|
273
|
-
FLAG_ACK: ::Integer
|
|
274
|
-
|
|
275
|
-
FLAG_PRIORITY: ::Integer
|
|
276
|
-
|
|
277
|
-
ERROR_NO_ERROR: ::Integer
|
|
278
|
-
|
|
279
|
-
ERROR_PROTOCOL_ERROR: ::Integer
|
|
280
|
-
|
|
281
|
-
ERROR_INTERNAL_ERROR: ::Integer
|
|
282
|
-
|
|
283
|
-
ERROR_REFUSED_STREAM: ::Integer
|
|
284
|
-
|
|
285
|
-
DEFAULT_WINDOW_SIZE: ::Integer
|
|
286
|
-
|
|
287
|
-
MAX_FRAME_SIZE: ::Integer
|
|
288
|
-
|
|
289
|
-
SERVER_PROTOCOL: ::String
|
|
290
|
-
|
|
291
|
-
REQUEST_PSEUDO_HEADERS: untyped
|
|
292
|
-
|
|
293
|
-
REQUIRED_REQUEST_PSEUDO_HEADERS: untyped
|
|
294
|
-
|
|
295
|
-
# Returns true when a decoded header block violates the HTTP/2 pseudo-header
|
|
296
|
-
# rules from RFC 9113 section 8.3: an unknown pseudo-header, a duplicate
|
|
297
|
-
# pseudo-header, a pseudo-header appearing after any regular header, or a
|
|
298
|
-
# required pseudo-header (`:method`, `:scheme`, `:path`) missing on
|
|
299
|
-
# non-`CONNECT` requests.
|
|
300
|
-
#
|
|
301
|
-
# @param headers [Array<Array(String, String)>] decoded header pairs
|
|
302
|
-
# @return [Boolean]
|
|
303
|
-
#
|
|
304
|
-
# @rbs (Array[[String, String]] headers) -> bool
|
|
305
|
-
def self.invalid_pseudo_headers?: (Array[[ String, String ]] headers) -> bool
|
|
306
|
-
|
|
307
|
-
@running: AtomicBoolean
|
|
308
|
-
|
|
309
|
-
@initial_settings_frame: String
|
|
310
|
-
|
|
311
|
-
@on_error: ^(Hash[String, untyped]?, Exception) -> void | nil
|
|
312
|
-
|
|
313
|
-
@clean_fiber_locals: bool
|
|
314
|
-
|
|
315
|
-
@clean_thread_locals: bool
|
|
316
|
-
|
|
317
|
-
@access_log_io: IO?
|
|
318
|
-
|
|
319
|
-
@write_timeout: Integer
|
|
320
|
-
|
|
321
|
-
@server_port: Integer
|
|
322
|
-
|
|
323
|
-
@app: ^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ]
|
|
324
|
-
|
|
325
|
-
# Returns the initial server SETTINGS frame to send on every new
|
|
326
|
-
# HTTP/2 connection.
|
|
327
|
-
#
|
|
328
|
-
# @return [String]
|
|
329
|
-
attr_reader initial_settings_frame: untyped
|
|
330
|
-
|
|
331
|
-
# Creates a new Http2 handler.
|
|
332
|
-
#
|
|
333
|
-
# @param app [#call] the Rack application to dispatch requests to
|
|
334
|
-
# @param server_port [Integer] port number used to populate SERVER_PORT in the Rack env
|
|
335
|
-
# @param connection_options [Hash] per-connection settings shared across protocols
|
|
336
|
-
# @option connection_options [Integer] :write_timeout per-write socket timeout in seconds
|
|
337
|
-
# @param http2_options [Hash] HTTP/2-specific settings
|
|
338
|
-
# @option http2_options [Integer] :max_concurrent_streams maximum HTTP/2 concurrent streams per connection
|
|
339
|
-
# @param access_log_io [IO, nil] IO to write Common Log Format access entries to, or nil to disable
|
|
340
|
-
# @param clean_thread_locals [Boolean] whether to clear application thread locals after each request
|
|
341
|
-
# @param clean_fiber_locals [Boolean] whether to process each request in a fresh Fiber
|
|
342
|
-
# @param on_error [#call, nil] callback invoked with (env, exception) when the Rack app raises
|
|
343
|
-
# @return [void]
|
|
344
|
-
#
|
|
345
|
-
# @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http2_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?clean_thread_locals: bool, ?clean_fiber_locals: bool, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
346
|
-
def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http2_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?clean_thread_locals: bool, ?clean_fiber_locals: bool, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
347
|
-
|
|
348
|
-
# Creates a per-connection {Writer} configured with the handler's write timeout.
|
|
349
|
-
#
|
|
350
|
-
# @return [Writer] a new per-connection frame writer
|
|
351
|
-
#
|
|
352
|
-
# @rbs () -> Writer
|
|
353
|
-
def create_writer: () -> Writer
|
|
354
|
-
|
|
355
|
-
# Stops new stream dispatch and asks clients to finish streams already
|
|
356
|
-
# handed to the application.
|
|
357
|
-
#
|
|
358
|
-
# @param reactor [Reactor] the reactor managing HTTP/2 connections
|
|
359
|
-
# @return [void]
|
|
360
|
-
#
|
|
361
|
-
# @rbs (Reactor reactor) -> void
|
|
362
|
-
def shutdown: (Reactor reactor) -> void
|
|
363
|
-
|
|
364
|
-
# Returns a Ractor-safe proc that parses HTTP/2 frames from the
|
|
365
|
-
# state hash's buffered bytes.
|
|
366
|
-
#
|
|
367
|
-
# @return [Proc]
|
|
368
|
-
#
|
|
369
|
-
# @rbs () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
370
|
-
def parser_worker: () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
371
|
-
|
|
372
306
|
# Advances HTTP/2 frame parsing from the connection buffer, returning
|
|
373
307
|
# updated connection state along with any outgoing protocol frames and
|
|
374
308
|
# completed stream requests.
|
|
@@ -379,6 +313,23 @@ module Raptor
|
|
|
379
313
|
# @rbs (Hash[Symbol, untyped] data) -> Hash[Symbol, untyped]
|
|
380
314
|
def self.process_frames: (Hash[Symbol, untyped] data) -> Hash[Symbol, untyped]
|
|
381
315
|
|
|
316
|
+
# Returns a DATA or HEADERS payload without padding, or nil if padding
|
|
317
|
+
# is invalid.
|
|
318
|
+
#
|
|
319
|
+
# @param frame [Hash] the parsed frame
|
|
320
|
+
# @return [String, nil]
|
|
321
|
+
#
|
|
322
|
+
# @rbs (Hash[Symbol, untyped] frame) -> String?
|
|
323
|
+
def self.unpadded_payload: (Hash[Symbol, untyped] frame) -> String?
|
|
324
|
+
|
|
325
|
+
# Returns whether request pseudo-headers violate RFC 9113 section 8.3.
|
|
326
|
+
#
|
|
327
|
+
# @param headers [Array<Array(String, String)>] decoded header pairs
|
|
328
|
+
# @return [Boolean]
|
|
329
|
+
#
|
|
330
|
+
# @rbs (Array[[String, String]] headers) -> bool
|
|
331
|
+
def self.invalid_pseudo_headers?: (Array[[ String, String ]] headers) -> bool
|
|
332
|
+
|
|
382
333
|
# Applies one complete request header block to its stream, resetting
|
|
383
334
|
# malformed initial headers or trailers and completing valid trailers.
|
|
384
335
|
#
|
|
@@ -386,7 +337,7 @@ module Raptor
|
|
|
386
337
|
# @param completed_requests [Array<Hash>] accumulator of completed stream requests
|
|
387
338
|
# @param outgoing_frames [Array<String>] accumulator of protocol response frames
|
|
388
339
|
# @param parser [Http2Parser] frame parser and encoder
|
|
389
|
-
# @param stream_id [Integer] the stream identifier
|
|
340
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
390
341
|
# @param decoded_headers [Array<Array(String, String)>] decoded header pairs
|
|
391
342
|
# @param end_stream [Boolean] whether the source frame had END_STREAM set
|
|
392
343
|
# @param trailers [Boolean] whether this is a trailing header block
|
|
@@ -400,7 +351,7 @@ module Raptor
|
|
|
400
351
|
#
|
|
401
352
|
# @param streams [Hash] current open-stream map
|
|
402
353
|
# @param completed_requests [Array<Hash>] accumulator of completed stream requests
|
|
403
|
-
# @param stream_id [Integer] the stream identifier
|
|
354
|
+
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
404
355
|
# @param decoded_headers [Array<Array(String, String)>] decoded header pairs
|
|
405
356
|
# @param end_stream [Boolean] whether the source frame had END_STREAM set
|
|
406
357
|
# @return [Array(Hash, Array<Hash>)] updated streams and completed_requests
|
|
@@ -430,42 +381,101 @@ module Raptor
|
|
|
430
381
|
# @rbs (Hash[Symbol, untyped] data, String buffer, Array[untyped] hpack_table, Hash[Integer, Hash[Symbol, untyped]] streams, Array[String] outgoing_frames, Array[Hash[Symbol, untyped]] completed_requests, Array[Integer] cancelled_streams, Array[[Integer, Integer]] window_updates, Array[String] ping_acknowledgements, Integer? peer_initial_window_size, Integer connection_window, bool preface_received, Integer last_client_stream_id, Hash[Symbol, untyped]? pending_headers, bool close_connection) -> Hash[Symbol, untyped]
|
|
431
382
|
def self.build_result: (Hash[Symbol, untyped] data, String buffer, Array[untyped] hpack_table, Hash[Integer, Hash[Symbol, untyped]] streams, Array[String] outgoing_frames, Array[Hash[Symbol, untyped]] completed_requests, Array[Integer] cancelled_streams, Array[[ Integer, Integer ]] window_updates, Array[String] ping_acknowledgements, Integer? peer_initial_window_size, Integer connection_window, bool preface_received, Integer last_client_stream_id, Hash[Symbol, untyped]? pending_headers, bool close_connection) -> Hash[Symbol, untyped]
|
|
432
383
|
|
|
384
|
+
@initial_settings_frame: String
|
|
385
|
+
|
|
386
|
+
@running: AtomicBoolean
|
|
387
|
+
|
|
388
|
+
@on_error: (^(Hash[String, untyped]?, Exception) -> void)?
|
|
389
|
+
|
|
390
|
+
@clean_fiber_locals: bool
|
|
391
|
+
|
|
392
|
+
@clean_thread_locals: bool
|
|
393
|
+
|
|
394
|
+
@access_log_io: IO?
|
|
395
|
+
|
|
396
|
+
@write_timeout: Integer
|
|
397
|
+
|
|
398
|
+
@server_port_string: String
|
|
399
|
+
|
|
400
|
+
@app: ^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ]
|
|
401
|
+
|
|
402
|
+
# Creates a new Http2 handler.
|
|
403
|
+
#
|
|
404
|
+
# @param app [#call] the Rack application to dispatch requests to
|
|
405
|
+
# @param server_port [Integer] port number used to populate SERVER_PORT in the Rack env
|
|
406
|
+
# @param connection_options [Hash] per-connection settings shared across protocols
|
|
407
|
+
# @option connection_options [Integer] :write_timeout per-write socket timeout in seconds
|
|
408
|
+
# @param http2_options [Hash] HTTP/2-specific settings
|
|
409
|
+
# @option http2_options [Integer] :max_concurrent_streams maximum HTTP/2 concurrent streams per connection
|
|
410
|
+
# @param access_log_io [IO, nil] IO to write Common Log Format access entries to, or nil to disable
|
|
411
|
+
# @param clean_thread_locals [Boolean] whether to clear application thread locals after each request
|
|
412
|
+
# @param clean_fiber_locals [Boolean] whether to process each request in a fresh Fiber
|
|
413
|
+
# @param on_error [#call, nil] callback invoked with (env, exception) when the Rack app raises
|
|
414
|
+
# @return [void]
|
|
415
|
+
#
|
|
416
|
+
# @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http2_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?clean_thread_locals: bool, ?clean_fiber_locals: bool, ?on_error: (^(Hash[String, untyped]?, Exception) -> void)?) -> void
|
|
417
|
+
def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http2_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?clean_thread_locals: bool, ?clean_fiber_locals: bool, ?on_error: (^(Hash[String, untyped]?, Exception) -> void)?) -> void
|
|
418
|
+
|
|
419
|
+
# Returns a Ractor-safe proc that parses HTTP/2 frames from the
|
|
420
|
+
# state hash's buffered bytes.
|
|
421
|
+
#
|
|
422
|
+
# @return [Proc]
|
|
423
|
+
#
|
|
424
|
+
# @rbs () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
425
|
+
def parser_worker: () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
|
|
426
|
+
|
|
427
|
+
# Stops new stream dispatch and asks clients to finish streams already
|
|
428
|
+
# handed to the application.
|
|
429
|
+
#
|
|
430
|
+
# @param reactor [Reactor] the reactor managing HTTP/2 connections
|
|
431
|
+
# @return [void]
|
|
432
|
+
#
|
|
433
|
+
# @rbs (Reactor reactor) -> void
|
|
434
|
+
def shutdown: (Reactor reactor) -> void
|
|
435
|
+
|
|
433
436
|
# Sends the server SETTINGS frame on a freshly negotiated HTTP/2
|
|
434
437
|
# connection, then eagerly reads and parses the first client frame
|
|
435
438
|
# batch, dispatching completed streams directly to the thread pool.
|
|
436
439
|
# Falls back to the reactor when no initial data is ready.
|
|
437
440
|
#
|
|
438
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
439
|
-
# @param id [Integer] unique
|
|
441
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
442
|
+
# @param id [Integer] unique connection identifier
|
|
440
443
|
# @param reactor [Reactor] the reactor managing the connection
|
|
441
444
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
442
|
-
# @param remote_addr [String] client IP address
|
|
443
|
-
# @param url_scheme [String] "https"
|
|
445
|
+
# @param remote_addr [String] the client IP address
|
|
446
|
+
# @param url_scheme [String] "http" or "https"
|
|
444
447
|
# @return [void]
|
|
445
448
|
#
|
|
446
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, String remote_addr, String url_scheme) -> void
|
|
447
|
-
def eager_accept: (OpenSSL::SSL::SSLSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, String remote_addr, String url_scheme) -> void
|
|
449
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, String remote_addr, String url_scheme) -> void
|
|
450
|
+
def eager_accept: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, String remote_addr, String url_scheme) -> void
|
|
448
451
|
|
|
449
452
|
# Handles a parsed HTTP/2 result. Writes outgoing frames, dispatches
|
|
450
453
|
# completed stream requests to the thread pool, and eagerly consumes
|
|
451
454
|
# further buffered frame batches before returning control to the
|
|
452
455
|
# reactor.
|
|
453
456
|
#
|
|
454
|
-
# @param
|
|
457
|
+
# @param parsed_request [Hash] the parsed result produced by {.process_frames}
|
|
455
458
|
# @param reactor [Reactor] the reactor managing the connection
|
|
456
|
-
# @param thread_pool [AtomicThreadPool] thread pool for
|
|
459
|
+
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
457
460
|
# @return [void]
|
|
458
461
|
#
|
|
459
|
-
# @rbs (Hash[Symbol, untyped]
|
|
460
|
-
def handle_parsed_request: (Hash[Symbol, untyped]
|
|
462
|
+
# @rbs (Hash[Symbol, untyped] parsed_request, Reactor reactor, AtomicThreadPool thread_pool) -> void
|
|
463
|
+
def handle_parsed_request: (Hash[Symbol, untyped] parsed_request, Reactor reactor, AtomicThreadPool thread_pool) -> void
|
|
461
464
|
|
|
462
465
|
private
|
|
463
466
|
|
|
467
|
+
# Creates a per-connection {Writer} configured with the handler's write timeout.
|
|
468
|
+
#
|
|
469
|
+
# @return [Writer] a new per-connection frame writer
|
|
470
|
+
#
|
|
471
|
+
# @rbs () -> Writer
|
|
472
|
+
def create_writer: () -> Writer
|
|
473
|
+
|
|
464
474
|
# Applies inbound flow-control updates from a parsed result to the
|
|
465
|
-
# connection's
|
|
475
|
+
# connection's {FlowControl}.
|
|
466
476
|
#
|
|
467
|
-
# @param flow_control [FlowControl]
|
|
468
|
-
# @param result [Hash] the parsed result from
|
|
477
|
+
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
478
|
+
# @param result [Hash] the parsed result from {.process_frames}
|
|
469
479
|
# @return [void]
|
|
470
480
|
#
|
|
471
481
|
# @rbs (FlowControl flow_control, Hash[Symbol, untyped] result) -> void
|
|
@@ -474,17 +484,17 @@ module Raptor
|
|
|
474
484
|
# Reads the next frame batch from `socket` if it has already arrived,
|
|
475
485
|
# without waiting on the shared collector thread.
|
|
476
486
|
#
|
|
477
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
487
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
478
488
|
# @return [String, nil] the bytes read, or nil if nothing was available
|
|
479
489
|
#
|
|
480
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket) -> String?
|
|
481
|
-
def eager_read_next_batch: (OpenSSL::SSL::SSLSocket socket) -> String?
|
|
490
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket) -> String?
|
|
491
|
+
def eager_read_next_batch: (TCPSocket | OpenSSL::SSL::SSLSocket socket) -> String?
|
|
482
492
|
|
|
483
493
|
# Dispatches a completed stream request to the Rack app and writes
|
|
484
494
|
# the response back as HTTP/2 frames.
|
|
485
495
|
#
|
|
486
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
487
|
-
# @param writer [Writer]
|
|
496
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
497
|
+
# @param writer [Writer] frame writer for the connection
|
|
488
498
|
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
489
499
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
490
500
|
# @param headers [Array<Array(String, String)>] request headers
|
|
@@ -492,13 +502,13 @@ module Raptor
|
|
|
492
502
|
# @param remote_addr [String] the client IP address
|
|
493
503
|
# @return [void]
|
|
494
504
|
#
|
|
495
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[String, String]] headers, String body, remote_addr: String) -> void
|
|
496
|
-
def dispatch_stream_request: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[ String, String ]] headers, String body, remote_addr: String) -> void
|
|
505
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[String, String]] headers, String body, remote_addr: String) -> void
|
|
506
|
+
def dispatch_stream_request: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[ String, String ]] headers, String body, remote_addr: String) -> void
|
|
497
507
|
|
|
498
508
|
# Calls the Rack app and writes its response for one stream.
|
|
499
509
|
#
|
|
500
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
501
|
-
# @param writer [Writer]
|
|
510
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
511
|
+
# @param writer [Writer] frame writer for the connection
|
|
502
512
|
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
503
513
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
504
514
|
# @param headers [Array<Array(String, String)>] request headers
|
|
@@ -506,13 +516,13 @@ module Raptor
|
|
|
506
516
|
# @param remote_addr [String] the client IP address
|
|
507
517
|
# @return [void]
|
|
508
518
|
#
|
|
509
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[String, String]] headers, String body, remote_addr: String) -> void
|
|
510
|
-
def perform_stream_request: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[ String, String ]] headers, String body, remote_addr: String) -> void
|
|
519
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[String, String]] headers, String body, remote_addr: String) -> void
|
|
520
|
+
def perform_stream_request: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Array[[ String, String ]] headers, String body, remote_addr: String) -> void
|
|
511
521
|
|
|
512
522
|
# Starts a detached HTTP/2 response after writing its response headers.
|
|
513
523
|
#
|
|
514
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
515
|
-
# @param writer [Writer]
|
|
524
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
525
|
+
# @param writer [Writer] frame writer for the connection
|
|
516
526
|
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
517
527
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
518
528
|
# @param status [Integer] HTTP status code
|
|
@@ -522,14 +532,14 @@ module Raptor
|
|
|
522
532
|
# @yield once the response headers are queued
|
|
523
533
|
# @return [void]
|
|
524
534
|
#
|
|
525
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, DetachedBody body, ^(Symbol) -> void finished) { () -> void } -> void
|
|
526
|
-
def
|
|
535
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, DetachedBody body, ^(Symbol) -> void finished) { () -> void } -> void
|
|
536
|
+
def write_detached_response: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, DetachedBody body, ^(Symbol) -> void finished) { () -> void } -> void
|
|
527
537
|
|
|
528
538
|
# Writes a Rack response as HTTP/2 frames to the socket, partitioning
|
|
529
539
|
# DATA frames through `flow_control` to fit within the peer's windows.
|
|
530
540
|
#
|
|
531
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
532
|
-
# @param writer [Writer]
|
|
541
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
542
|
+
# @param writer [Writer] frame writer for the connection
|
|
533
543
|
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
534
544
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
535
545
|
# @param status [Integer] HTTP status code
|
|
@@ -537,68 +547,58 @@ module Raptor
|
|
|
537
547
|
# @param body [Object] response body responding to each
|
|
538
548
|
# @param trailers [Hash] trailing response headers populated by the Rack application
|
|
539
549
|
# @param request_method [String] request method used to suppress HEAD response bodies
|
|
550
|
+
# @yield once the response headers are queued
|
|
540
551
|
# @return [String] the response body size in bytes
|
|
541
552
|
#
|
|
542
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body, trailers: Hash[String, String | Array[String]], request_method: String) ?{ () -> void } -> String
|
|
543
|
-
def
|
|
553
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body, trailers: Hash[String, String | Array[String]], request_method: String) ?{ () -> void } -> String
|
|
554
|
+
def write_response: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body, trailers: Hash[String, String | Array[String]], request_method: String) ?{ () -> void } -> String
|
|
544
555
|
|
|
545
556
|
# Sends an HTTP 103 Early Hints response.
|
|
546
557
|
#
|
|
547
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
558
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
548
559
|
# @param writer [Writer] frame writer for the connection
|
|
549
560
|
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
550
561
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
551
562
|
# @param hints [Hash] response headers to send as early hints
|
|
552
563
|
# @return [void]
|
|
553
564
|
#
|
|
554
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] hints) -> void
|
|
555
|
-
def send_early_hints: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] hints) -> void
|
|
565
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] hints) -> void
|
|
566
|
+
def send_early_hints: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Hash[String, String | Array[String]] hints) -> void
|
|
556
567
|
|
|
557
568
|
# Resets one HTTP/2 stream with the given error code.
|
|
558
569
|
#
|
|
559
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
570
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
560
571
|
# @param writer [Writer] frame writer for the connection
|
|
561
572
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
562
573
|
# @param error_code [Integer] the HTTP/2 error code
|
|
563
574
|
# @return [void]
|
|
564
575
|
#
|
|
565
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id, Integer error_code) -> void
|
|
566
|
-
def
|
|
576
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id, Integer error_code) -> void
|
|
577
|
+
def write_reset_stream: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id, Integer error_code) -> void
|
|
567
578
|
|
|
568
579
|
# Writes a 500 error response as HTTP/2 frames.
|
|
569
580
|
#
|
|
570
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
571
|
-
# @param writer [Writer]
|
|
581
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
582
|
+
# @param writer [Writer] frame writer for the connection
|
|
572
583
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
573
584
|
# @return [void]
|
|
574
585
|
#
|
|
575
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id) -> void
|
|
576
|
-
def
|
|
577
|
-
|
|
578
|
-
# Instance-level wrapper around {Http.write_access_log} that routes to
|
|
579
|
-
# the configured `@access_log_io`.
|
|
580
|
-
#
|
|
581
|
-
# @param env [Hash] the Rack environment
|
|
582
|
-
# @param status [Integer] the response status code
|
|
583
|
-
# @param size [String] the response body size in bytes, or `-` if unknown
|
|
584
|
-
# @param remote_addr [String] the client IP address
|
|
585
|
-
# @return [void]
|
|
586
|
-
#
|
|
587
|
-
# @rbs (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
588
|
-
def write_access_log: (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
586
|
+
# @rbs (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id) -> void
|
|
587
|
+
def write_error_response: (TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id) -> void
|
|
589
588
|
|
|
590
589
|
# Builds a Rack environment hash from HTTP/2 headers and body.
|
|
591
590
|
#
|
|
592
591
|
# @param headers [Array<Array(String, String)>] HTTP/2 header pairs
|
|
593
592
|
# @param body [String] the request body
|
|
594
|
-
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
593
|
+
# @param socket [TCPSocket, OpenSSL::SSL::SSLSocket] the connection socket
|
|
595
594
|
# @param writer [Writer] frame writer for the connection
|
|
595
|
+
# @param flow_control [FlowControl] per-connection outbound flow controller
|
|
596
596
|
# @param stream_id [Integer] the HTTP/2 stream identifier
|
|
597
597
|
# @param remote_addr [String] the client IP address
|
|
598
598
|
# @return [Hash] fully populated Rack environment hash
|
|
599
599
|
#
|
|
600
|
-
# @rbs (Array[[String, String]] headers, String body, OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, remote_addr: String) -> Hash[String, untyped]
|
|
601
|
-
def build_rack_env: (Array[[ String, String ]] headers, String body, OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, remote_addr: String) -> Hash[String, untyped]
|
|
600
|
+
# @rbs (Array[[String, String]] headers, String body, TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, remote_addr: String) -> Hash[String, untyped]
|
|
601
|
+
def build_rack_env: (Array[[ String, String ]] headers, String body, TCPSocket | OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, remote_addr: String) -> Hash[String, untyped]
|
|
602
602
|
|
|
603
603
|
# Populates SERVER_NAME and SERVER_PORT from the HTTP_HOST header.
|
|
604
604
|
#
|
|
@@ -607,5 +607,16 @@ module Raptor
|
|
|
607
607
|
#
|
|
608
608
|
# @rbs (Hash[String, untyped] env) -> void
|
|
609
609
|
def populate_server_name_and_port: (Hash[String, untyped] env) -> void
|
|
610
|
+
|
|
611
|
+
# Writes a completed request to the access log.
|
|
612
|
+
#
|
|
613
|
+
# @param env [Hash] the Rack environment
|
|
614
|
+
# @param status [Integer] the response status code
|
|
615
|
+
# @param size [String] the response body size in bytes, or `-` if unknown
|
|
616
|
+
# @param remote_addr [String] the client IP address
|
|
617
|
+
# @return [void]
|
|
618
|
+
#
|
|
619
|
+
# @rbs (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
620
|
+
def write_access_log: (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
610
621
|
end
|
|
611
622
|
end
|