raptor 0.6.0 → 0.8.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 +23 -0
- data/README.md +148 -23
- data/lib/rackup/handler/raptor.rb +12 -2
- data/lib/raptor/binder.rb +122 -28
- data/lib/raptor/cli.rb +82 -21
- data/lib/raptor/cluster.rb +188 -32
- data/lib/raptor/http.rb +75 -0
- data/lib/raptor/{request.rb → http1.rb} +202 -81
- data/lib/raptor/http2.rb +149 -61
- data/lib/raptor/reactor.rb +22 -15
- data/lib/raptor/server.rb +57 -37
- data/lib/raptor/stats.rb +1 -1
- data/lib/raptor/systemd.rb +69 -0
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/raptor/binder.rbs +72 -5
- data/sig/generated/raptor/cli.rbs +2 -3
- data/sig/generated/raptor/cluster.rbs +89 -13
- data/sig/generated/raptor/http.rbs +52 -0
- data/sig/generated/raptor/{request.rbs → http1.rbs} +107 -31
- data/sig/generated/raptor/http2.rbs +64 -14
- data/sig/generated/raptor/reactor.rbs +18 -11
- data/sig/generated/raptor/server.rbs +32 -18
- data/sig/generated/raptor/systemd.rbs +42 -0
- metadata +7 -3
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Generated from lib/raptor/
|
|
1
|
+
# Generated from lib/raptor/http1.rb with RBS::Inline
|
|
2
2
|
|
|
3
3
|
module Raptor
|
|
4
4
|
# Parses HTTP/1.x requests and dispatches them to the Rack
|
|
5
5
|
# application. Coordinates with the Ractor pool for parsing and
|
|
6
6
|
# with the reactor for requests that need more data before they
|
|
7
7
|
# can be handled.
|
|
8
|
-
class
|
|
8
|
+
class Http1
|
|
9
9
|
BODY_BUFFER_THRESHOLD: untyped
|
|
10
10
|
|
|
11
11
|
FILE_CHUNK_SIZE: untyped
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
MAX_CHUNK_OVERHEAD: untyped
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
READ_BUFFER_SIZE: untyped
|
|
16
16
|
|
|
17
17
|
KEEPALIVE_READ_TIMEOUT: ::Float
|
|
18
18
|
|
|
@@ -28,20 +28,26 @@ module Raptor
|
|
|
28
28
|
|
|
29
29
|
STATUS_WITH_NO_ENTITY_BODY: untyped
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
CONTINUE_RESPONSE: ::String
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
BAD_REQUEST_RESPONSE: ::String
|
|
34
34
|
|
|
35
35
|
CONTENT_TOO_LARGE_RESPONSE: ::String
|
|
36
36
|
|
|
37
|
+
INTERNAL_SERVER_ERROR_RESPONSE: ::String
|
|
38
|
+
|
|
37
39
|
CONNECTION_CLOSE: ::String
|
|
38
40
|
|
|
39
41
|
CONNECTION_KEEPALIVE: ::String
|
|
40
42
|
|
|
43
|
+
EXPECT_100_CONTINUE: ::String
|
|
44
|
+
|
|
41
45
|
TRANSFER_ENCODING_CHUNKED: ::String
|
|
42
46
|
|
|
43
47
|
HTTP_CONNECTION: ::String
|
|
44
48
|
|
|
49
|
+
HTTP_EXPECT: ::String
|
|
50
|
+
|
|
45
51
|
HTTP_TRANSFER_ENCODING: ::String
|
|
46
52
|
|
|
47
53
|
RACK_HEADER_PREFIX: ::String
|
|
@@ -54,19 +60,24 @@ module Raptor
|
|
|
54
60
|
|
|
55
61
|
ILLEGAL_HEADER_VALUE_REGEX: ::Regexp
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
# Returns true when the message framing shows a request-smuggling vector
|
|
64
|
+
# per RFC 9112 section 6.3: a `Transfer-Encoding` where `chunked` is
|
|
65
|
+
# missing, not the final encoding, or duplicated; a `Transfer-Encoding`
|
|
66
|
+
# paired with a `Content-Length`; or a `Content-Length` containing any
|
|
67
|
+
# non-digit character.
|
|
68
|
+
#
|
|
69
|
+
# @param env [Hash] the Rack environment after header parsing
|
|
70
|
+
# @return [Boolean]
|
|
71
|
+
#
|
|
72
|
+
# @rbs (Hash[String, untyped] env) -> bool
|
|
73
|
+
def self.request_smuggling?: (Hash[String, untyped] env) -> bool
|
|
64
74
|
|
|
65
75
|
# Decodes a chunked transfer-encoded body buffer.
|
|
66
76
|
#
|
|
67
77
|
# Returns the decoded bytes and a state symbol: `:complete` when the
|
|
68
78
|
# terminating zero-length chunk was found, `:too_large` when the decoded
|
|
69
|
-
# size would exceed `max_size`,
|
|
79
|
+
# size would exceed `max_size`, `:malformed` when chunk framing overhead
|
|
80
|
+
# exceeds `MAX_CHUNK_OVERHEAD`, or `:incomplete` otherwise.
|
|
70
81
|
#
|
|
71
82
|
# @param buffer [String] the raw body buffer to decode
|
|
72
83
|
# @param max_size [Integer, nil] maximum decoded body size, or nil for unlimited
|
|
@@ -75,41 +86,51 @@ module Raptor
|
|
|
75
86
|
# @rbs (String buffer, ?Integer? max_size) -> [String, Symbol]
|
|
76
87
|
def self.decode_chunked: (String buffer, ?Integer? max_size) -> [ String, Symbol ]
|
|
77
88
|
|
|
78
|
-
# Writes `string` in full, retrying on partial writes. Bounded by
|
|
79
|
-
# `WRITE_TIMEOUT` so a slow client can't pin the writing thread.
|
|
80
|
-
#
|
|
81
|
-
# @param socket [TCPSocket] the socket to write to
|
|
82
|
-
# @param string [String] the data to write
|
|
83
|
-
# @return [void]
|
|
84
|
-
# @raise [WriteError] if the socket is not writable within the timeout or raises IOError
|
|
85
|
-
#
|
|
86
|
-
# @rbs (TCPSocket socket, String string) -> void
|
|
87
|
-
def self.socket_write: (TCPSocket socket, String string) -> void
|
|
88
|
-
|
|
89
89
|
@running: AtomicBoolean
|
|
90
90
|
|
|
91
91
|
@on_error: ^(Hash[String, untyped]?, Exception) -> void | nil
|
|
92
92
|
|
|
93
|
+
@access_log_io: IO?
|
|
94
|
+
|
|
95
|
+
@max_keepalive_requests: Integer
|
|
96
|
+
|
|
93
97
|
@body_spool_threshold: Integer?
|
|
94
98
|
|
|
95
99
|
@max_body_size: Integer?
|
|
96
100
|
|
|
101
|
+
@write_timeout: Integer
|
|
102
|
+
|
|
97
103
|
@server_port: Integer
|
|
98
104
|
|
|
99
105
|
@app: ^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ]
|
|
100
106
|
|
|
101
|
-
# Creates a new
|
|
107
|
+
# Creates a new Http1 handler.
|
|
102
108
|
#
|
|
103
109
|
# @param app [#call] the Rack application to dispatch complete requests to
|
|
104
110
|
# @param server_port [Integer] port number used to populate SERVER_PORT in the Rack env
|
|
105
|
-
# @param
|
|
106
|
-
# @option
|
|
107
|
-
# @option
|
|
111
|
+
# @param connection_options [Hash] per-connection settings shared across protocols
|
|
112
|
+
# @option connection_options [Integer] :write_timeout per-write socket timeout in seconds
|
|
113
|
+
# @option connection_options [Integer, nil] :max_body_size maximum request body size in bytes
|
|
114
|
+
# @option connection_options [Integer, nil] :body_spool_threshold spool bodies larger than this to a tempfile
|
|
115
|
+
# @param http1_options [Hash] HTTP/1.1-specific settings
|
|
116
|
+
# @option http1_options [Integer] :max_keepalive_requests maximum requests per HTTP/1.1 keep-alive connection
|
|
117
|
+
# @param access_log_io [IO, nil] IO to write Common Log Format access entries to, or nil to disable
|
|
108
118
|
# @param on_error [#call, nil] callback invoked with (env, exception) when the Rack app raises
|
|
109
119
|
# @return [void]
|
|
110
120
|
#
|
|
111
|
-
# @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port, ?
|
|
112
|
-
def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port, ?
|
|
121
|
+
# @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http1_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
122
|
+
def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port, ?connection_options: Hash[Symbol, untyped], ?http1_options: Hash[Symbol, untyped], ?access_log_io: IO?, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
123
|
+
|
|
124
|
+
# Instance-level wrapper around {Http.socket_write} that applies the
|
|
125
|
+
# configured `write_timeout`.
|
|
126
|
+
#
|
|
127
|
+
# @param socket [TCPSocket] the socket to write to
|
|
128
|
+
# @param string [String] the data to write
|
|
129
|
+
# @return [void]
|
|
130
|
+
# @raise [Http::WriteError] if the socket is not writable within the timeout or raises IOError
|
|
131
|
+
#
|
|
132
|
+
# @rbs (TCPSocket socket, String string) -> void
|
|
133
|
+
def socket_write: (TCPSocket socket, String string) -> void
|
|
113
134
|
|
|
114
135
|
# Signals eager keep-alive loops to stop processing further requests on
|
|
115
136
|
# their connections. In-flight requests complete normally.
|
|
@@ -160,6 +181,28 @@ module Raptor
|
|
|
160
181
|
|
|
161
182
|
private
|
|
162
183
|
|
|
184
|
+
# Returns true if the request expects a 100 Continue response per
|
|
185
|
+
# RFC 7231 section 5.1.1.
|
|
186
|
+
#
|
|
187
|
+
# @param env [Hash] the parsed Rack environment (possibly incomplete)
|
|
188
|
+
# @return [Boolean]
|
|
189
|
+
#
|
|
190
|
+
# @rbs (Hash[String, untyped] env) -> bool
|
|
191
|
+
def expects_100_continue?: (Hash[String, untyped] env) -> bool
|
|
192
|
+
|
|
193
|
+
# Sends an HTTP 100 Continue response when an HTTP/1.1 client requested
|
|
194
|
+
# `Expect: 100-continue` and the request body has not yet been received.
|
|
195
|
+
#
|
|
196
|
+
# Returns the state hash with `:continued` set when the response has been
|
|
197
|
+
# written. A write failure is silently ignored.
|
|
198
|
+
#
|
|
199
|
+
# @param state [Hash] the partially-parsed connection state
|
|
200
|
+
# @param reactor [Reactor] the reactor holding the connection's socket
|
|
201
|
+
# @return [Hash] the state, with `:continued` set if 100 was written
|
|
202
|
+
#
|
|
203
|
+
# @rbs (Hash[Symbol, untyped] state, Reactor reactor) -> Hash[Symbol, untyped]
|
|
204
|
+
def send_continue_if_expected: (Hash[Symbol, untyped] state, Reactor reactor) -> Hash[Symbol, untyped]
|
|
205
|
+
|
|
163
206
|
# Processes a client connection by handling the current request and,
|
|
164
207
|
# if keep-alive, eagerly reading subsequent requests inline.
|
|
165
208
|
#
|
|
@@ -278,6 +321,16 @@ module Raptor
|
|
|
278
321
|
# @rbs (String? body) -> IO
|
|
279
322
|
def build_rack_input: (String? body) -> IO
|
|
280
323
|
|
|
324
|
+
# Returns true when an upstream proxy signals that it terminated TLS for
|
|
325
|
+
# this request via `X-Forwarded-Proto`, `X-Forwarded-Scheme`, or
|
|
326
|
+
# `X-Forwarded-Ssl`. Only the first comma-separated value is consulted.
|
|
327
|
+
#
|
|
328
|
+
# @param env [Hash] the Rack environment
|
|
329
|
+
# @return [Boolean]
|
|
330
|
+
#
|
|
331
|
+
# @rbs (Hash[String, untyped] env) -> bool
|
|
332
|
+
def forwarded_https?: (Hash[String, untyped] env) -> bool
|
|
333
|
+
|
|
281
334
|
# Determines whether the connection should be kept alive after the response.
|
|
282
335
|
#
|
|
283
336
|
# Returns false if the request limit has been reached. For HTTP/1.1, keep-alive
|
|
@@ -526,6 +579,29 @@ module Raptor
|
|
|
526
579
|
# @rbs (Hash[String, untyped] env, Integer? status, Hash[String, String | Array[String]]? headers, Exception? error) -> void
|
|
527
580
|
def call_response_finished: (Hash[String, untyped] env, Integer? status, Hash[String, String | Array[String]]? headers, Exception? error) -> void
|
|
528
581
|
|
|
582
|
+
# Instance-level wrapper around {Http.write_access_log} that routes to
|
|
583
|
+
# the configured `@access_log_io`.
|
|
584
|
+
#
|
|
585
|
+
# @param env [Hash] the Rack environment
|
|
586
|
+
# @param status [Integer] the response status code
|
|
587
|
+
# @param size [String] the response body size in bytes, or `-` if unknown
|
|
588
|
+
# @param remote_addr [String] the client IP address
|
|
589
|
+
# @return [void]
|
|
590
|
+
#
|
|
591
|
+
# @rbs (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
592
|
+
def write_access_log: (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
593
|
+
|
|
594
|
+
# Returns the response body size as a String for the access log, taken
|
|
595
|
+
# from the `content-length` header when set, computed from the body
|
|
596
|
+
# otherwise, or `-` when the size cannot be determined upfront.
|
|
597
|
+
#
|
|
598
|
+
# @param headers [Hash] the response headers
|
|
599
|
+
# @param body [Object] the response body
|
|
600
|
+
# @return [String]
|
|
601
|
+
#
|
|
602
|
+
# @rbs (Hash[String, String | Array[String]] headers, untyped body) -> String
|
|
603
|
+
def response_size: (Hash[String, String | Array[String]] headers, untyped body) -> String
|
|
604
|
+
|
|
529
605
|
# Enables TCP_CORK on the socket to batch outgoing packets into fewer segments.
|
|
530
606
|
#
|
|
531
607
|
# Only applies to TCP sockets. No-op on non-TCP sockets.
|
|
@@ -17,10 +17,15 @@ module Raptor
|
|
|
17
17
|
|
|
18
18
|
@state: Atom
|
|
19
19
|
|
|
20
|
+
@write_timeout: Integer
|
|
21
|
+
|
|
20
22
|
# Creates a new Writer.
|
|
21
23
|
#
|
|
22
|
-
# @
|
|
23
|
-
|
|
24
|
+
# @param write_timeout [Integer] per-write socket timeout passed through to {Http.socket_write}
|
|
25
|
+
# @return [void]
|
|
26
|
+
#
|
|
27
|
+
# @rbs (write_timeout: Integer) -> void
|
|
28
|
+
def initialize: (write_timeout: Integer) -> void
|
|
24
29
|
|
|
25
30
|
# Writes frames to the socket, coordinating with concurrent writers
|
|
26
31
|
# so that exactly one thread is actively writing at any time.
|
|
@@ -36,7 +41,7 @@ module Raptor
|
|
|
36
41
|
# Per-connection outbound flow-control accounting.
|
|
37
42
|
#
|
|
38
43
|
# Tracks the peer's connection-level and per-stream receive windows so
|
|
39
|
-
# outbound DATA frames respect RFC 7540
|
|
44
|
+
# outbound DATA frames respect RFC 7540 section 5.2. Threads dispatching stream
|
|
40
45
|
# responses call `acquire` to reserve send capacity; threads applying
|
|
41
46
|
# inbound WINDOW_UPDATE or SETTINGS frames call the mutating methods to
|
|
42
47
|
# replenish it. The connection window and per-stream windows live in
|
|
@@ -93,7 +98,7 @@ module Raptor
|
|
|
93
98
|
def add_stream_window: (Integer stream_id, Integer increment) -> void
|
|
94
99
|
|
|
95
100
|
# Updates the peer's `SETTINGS_INITIAL_WINDOW_SIZE`. Shifts every
|
|
96
|
-
# existing stream window by the delta as required by RFC 7540
|
|
101
|
+
# existing stream window by the delta as required by RFC 7540 section 6.9.2.
|
|
97
102
|
#
|
|
98
103
|
# @param new_size [Integer] the peer's new initial window size
|
|
99
104
|
# @return [void]
|
|
@@ -112,6 +117,12 @@ module Raptor
|
|
|
112
117
|
def discard_stream: (Integer stream_id) -> void
|
|
113
118
|
end
|
|
114
119
|
|
|
120
|
+
EAGER_READ_TIMEOUT: ::Float
|
|
121
|
+
|
|
122
|
+
EAGER_READ_BUFFER_SIZE: untyped
|
|
123
|
+
|
|
124
|
+
EAGER_MAX_ROUNDS: ::Integer
|
|
125
|
+
|
|
115
126
|
FLAG_END_STREAM: ::Integer
|
|
116
127
|
|
|
117
128
|
FLAG_END_HEADERS: ::Integer
|
|
@@ -134,28 +145,44 @@ module Raptor
|
|
|
134
145
|
|
|
135
146
|
HOP_BY_HOP_HEADERS: untyped
|
|
136
147
|
|
|
148
|
+
@initial_settings_frame: String
|
|
149
|
+
|
|
137
150
|
@on_error: ^(Hash[String, untyped]?, Exception) -> void | nil
|
|
138
151
|
|
|
152
|
+
@access_log_io: IO?
|
|
153
|
+
|
|
154
|
+
@write_timeout: Integer
|
|
155
|
+
|
|
139
156
|
@server_port: Integer
|
|
140
157
|
|
|
141
158
|
@app: ^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ]
|
|
142
159
|
|
|
160
|
+
# The initial server SETTINGS frame sent on every new HTTP/2 connection.
|
|
161
|
+
#
|
|
162
|
+
# @return [String] the encoded SETTINGS frame
|
|
163
|
+
attr_reader initial_settings_frame: untyped
|
|
164
|
+
|
|
143
165
|
# Creates a new Http2 handler.
|
|
144
166
|
#
|
|
145
167
|
# @param app [#call] the Rack application to dispatch requests to
|
|
146
168
|
# @param server_port [Integer] port number used to populate SERVER_PORT in the Rack env
|
|
169
|
+
# @param connection_options [Hash] per-connection settings shared across protocols
|
|
170
|
+
# @option connection_options [Integer] :write_timeout per-write socket timeout in seconds
|
|
171
|
+
# @param http2_options [Hash] HTTP/2-specific settings
|
|
172
|
+
# @option http2_options [Integer] :max_concurrent_streams maximum HTTP/2 concurrent streams per connection
|
|
173
|
+
# @param access_log_io [IO, nil] IO to write Common Log Format access entries to, or nil to disable
|
|
147
174
|
# @param on_error [#call, nil] callback invoked with (env, exception) when the Rack app raises
|
|
148
175
|
# @return [void]
|
|
149
176
|
#
|
|
150
|
-
# @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
151
|
-
def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
177
|
+
# @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?, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
178
|
+
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?, ?on_error: ^(Hash[String, untyped]?, Exception) -> void | nil) -> void
|
|
152
179
|
|
|
153
|
-
#
|
|
180
|
+
# Creates a per-connection {Writer} configured with the handler's write timeout.
|
|
154
181
|
#
|
|
155
|
-
# @return [
|
|
182
|
+
# @return [Writer] a new per-connection frame writer
|
|
156
183
|
#
|
|
157
|
-
# @rbs () ->
|
|
158
|
-
def
|
|
184
|
+
# @rbs () -> Writer
|
|
185
|
+
def create_writer: () -> Writer
|
|
159
186
|
|
|
160
187
|
# Processes HTTP/2 frames from the connection buffer.
|
|
161
188
|
#
|
|
@@ -205,7 +232,9 @@ module Raptor
|
|
|
205
232
|
# Handles a parsed HTTP/2 request from the ractor pool.
|
|
206
233
|
#
|
|
207
234
|
# Writes outgoing protocol frames to the socket, updates reactor state,
|
|
208
|
-
# and dispatches completed stream requests to the thread pool.
|
|
235
|
+
# and dispatches completed stream requests to the thread pool. Eagerly
|
|
236
|
+
# consumes subsequent frame batches that are already buffered, skipping
|
|
237
|
+
# the reactor and ractor pool hops while the connection is hot.
|
|
209
238
|
#
|
|
210
239
|
# @param result [Hash] the parsed result from the ractor pool
|
|
211
240
|
# @param reactor [Reactor] the reactor managing the connection
|
|
@@ -227,6 +256,15 @@ module Raptor
|
|
|
227
256
|
# @rbs (FlowControl flow_control, Hash[Symbol, untyped] result) -> void
|
|
228
257
|
def apply_flow_control_updates: (FlowControl flow_control, Hash[Symbol, untyped] result) -> void
|
|
229
258
|
|
|
259
|
+
# Reads the next frame batch from `socket` within a short window, or
|
|
260
|
+
# returns nil if nothing arrives in time.
|
|
261
|
+
#
|
|
262
|
+
# @param socket [OpenSSL::SSL::SSLSocket] the connection socket
|
|
263
|
+
# @return [String, nil] the bytes read, or nil if nothing was available
|
|
264
|
+
#
|
|
265
|
+
# @rbs (OpenSSL::SSL::SSLSocket socket) -> String?
|
|
266
|
+
def eager_read_next_batch: (OpenSSL::SSL::SSLSocket socket) -> String?
|
|
267
|
+
|
|
230
268
|
# Dispatches a completed stream request to the Rack app and writes
|
|
231
269
|
# the response back as HTTP/2 frames.
|
|
232
270
|
#
|
|
@@ -254,10 +292,10 @@ module Raptor
|
|
|
254
292
|
# @param status [Integer] HTTP status code
|
|
255
293
|
# @param headers [Hash] response headers from the Rack application
|
|
256
294
|
# @param body [Object] response body responding to each
|
|
257
|
-
# @return [
|
|
295
|
+
# @return [String] the response body size in bytes
|
|
258
296
|
#
|
|
259
|
-
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body) ->
|
|
260
|
-
def write_http2_response: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body) ->
|
|
297
|
+
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body) -> String
|
|
298
|
+
def write_http2_response: (OpenSSL::SSL::SSLSocket socket, Writer writer, FlowControl flow_control, Integer stream_id, Integer status, Hash[String, String | Array[String]] headers, untyped body) -> String
|
|
261
299
|
|
|
262
300
|
# Writes a 500 error response as HTTP/2 frames.
|
|
263
301
|
#
|
|
@@ -269,6 +307,18 @@ module Raptor
|
|
|
269
307
|
# @rbs (OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id) -> void
|
|
270
308
|
def write_http2_error_response: (OpenSSL::SSL::SSLSocket socket, Writer writer, Integer stream_id) -> void
|
|
271
309
|
|
|
310
|
+
# Instance-level wrapper around {Http.write_access_log} that routes to
|
|
311
|
+
# the configured `@access_log_io`.
|
|
312
|
+
#
|
|
313
|
+
# @param env [Hash] the Rack environment
|
|
314
|
+
# @param status [Integer] the response status code
|
|
315
|
+
# @param size [String] the response body size in bytes, or `-` if unknown
|
|
316
|
+
# @param remote_addr [String] the client IP address
|
|
317
|
+
# @return [void]
|
|
318
|
+
#
|
|
319
|
+
# @rbs (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
320
|
+
def write_access_log: (Hash[String, untyped] env, Integer status, String size, String remote_addr) -> void
|
|
321
|
+
|
|
272
322
|
# Builds a Rack environment hash from HTTP/2 headers and body.
|
|
273
323
|
#
|
|
274
324
|
# Translates HTTP/2 pseudo-headers into Rack-compatible environment keys
|
|
@@ -10,10 +10,12 @@ module Raptor
|
|
|
10
10
|
# the server uses for backpressure control to prevent overload.
|
|
11
11
|
#
|
|
12
12
|
# @example
|
|
13
|
-
# reactor = Reactor.new(
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
13
|
+
# reactor = Reactor.new(
|
|
14
|
+
# ractor_pool,
|
|
15
|
+
# thread_pool,
|
|
16
|
+
# connection_options: { first_data_timeout: 30, chunk_data_timeout: 10 },
|
|
17
|
+
# http1_options: { persistent_data_timeout: 65 }
|
|
18
|
+
# )
|
|
17
19
|
# reactor.run
|
|
18
20
|
# reactor.add(id: client.object_id, socket: client)
|
|
19
21
|
# # ... later
|
|
@@ -71,7 +73,11 @@ module Raptor
|
|
|
71
73
|
|
|
72
74
|
@selector: NIO::Selector
|
|
73
75
|
|
|
74
|
-
@
|
|
76
|
+
@persistent_data_timeout: Integer
|
|
77
|
+
|
|
78
|
+
@chunk_data_timeout: Integer
|
|
79
|
+
|
|
80
|
+
@first_data_timeout: Integer
|
|
75
81
|
|
|
76
82
|
@ractor_pool: untyped
|
|
77
83
|
|
|
@@ -81,14 +87,15 @@ module Raptor
|
|
|
81
87
|
#
|
|
82
88
|
# @param ractor_pool [RactorPool] ractor pool for HTTP parsing
|
|
83
89
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
84
|
-
# @param
|
|
85
|
-
# @option
|
|
86
|
-
# @option
|
|
87
|
-
# @
|
|
90
|
+
# @param connection_options [Hash] per-connection timeout configuration
|
|
91
|
+
# @option connection_options [Integer] :first_data_timeout timeout for initial data
|
|
92
|
+
# @option connection_options [Integer] :chunk_data_timeout timeout for subsequent chunks
|
|
93
|
+
# @param http1_options [Hash] HTTP/1.1-specific configuration
|
|
94
|
+
# @option http1_options [Integer] :persistent_data_timeout timeout for keep-alive idle connections
|
|
88
95
|
# @return [void]
|
|
89
96
|
#
|
|
90
|
-
# @rbs (untyped ractor_pool, untyped thread_pool,
|
|
91
|
-
def initialize: (untyped ractor_pool, untyped thread_pool,
|
|
97
|
+
# @rbs (untyped ractor_pool, untyped thread_pool, connection_options: Hash[Symbol, untyped], http1_options: Hash[Symbol, untyped]) -> void
|
|
98
|
+
def initialize: (untyped ractor_pool, untyped thread_pool, connection_options: Hash[Symbol, untyped], http1_options: Hash[Symbol, untyped]) -> void
|
|
92
99
|
|
|
93
100
|
# Starts the reactor's main event loop in a new thread.
|
|
94
101
|
#
|
|
@@ -14,9 +14,10 @@ module Raptor
|
|
|
14
14
|
#
|
|
15
15
|
# @example
|
|
16
16
|
# binder = Binder.new(["tcp://0.0.0.0:3000"])
|
|
17
|
-
# reactor = Reactor.new(ractor_pool, thread_pool,
|
|
18
|
-
#
|
|
19
|
-
#
|
|
17
|
+
# reactor = Reactor.new(ractor_pool, thread_pool, connection_options: {}, http1_options: {})
|
|
18
|
+
# http1 = Http1.new(app, 3000)
|
|
19
|
+
# http2 = Http2.new(app, 3000)
|
|
20
|
+
# server = Server.new(binder, reactor, thread_pool, http1, http2, connection_options: { first_data_timeout: 30 })
|
|
20
21
|
# server.run
|
|
21
22
|
# # ... later
|
|
22
23
|
# server.shutdown
|
|
@@ -35,9 +36,13 @@ module Raptor
|
|
|
35
36
|
|
|
36
37
|
@running: AtomicBoolean
|
|
37
38
|
|
|
38
|
-
@
|
|
39
|
+
@drain_accept_queue: bool
|
|
39
40
|
|
|
40
|
-
@
|
|
41
|
+
@first_data_timeout: Integer
|
|
42
|
+
|
|
43
|
+
@http2: Http2
|
|
44
|
+
|
|
45
|
+
@http1: Http1
|
|
41
46
|
|
|
42
47
|
@thread_pool: AtomicThreadPool
|
|
43
48
|
|
|
@@ -50,12 +55,14 @@ module Raptor
|
|
|
50
55
|
# @param binder [Binder] the binder managing listening sockets
|
|
51
56
|
# @param reactor [Reactor] the reactor for handling client connections
|
|
52
57
|
# @param thread_pool [AtomicThreadPool] thread pool for application processing
|
|
53
|
-
# @param
|
|
54
|
-
# @param
|
|
58
|
+
# @param http1 [Http1] the HTTP/1.1 handler
|
|
59
|
+
# @param http2 [Http2] the HTTP/2 handler (provides the initial SETTINGS frame)
|
|
60
|
+
# @param connection_options [Hash] per-connection timeout configuration, used to bound TLS handshakes
|
|
61
|
+
# @param drain_accept_queue [Boolean] whether to drain the kernel accept queue on shutdown
|
|
55
62
|
# @return [void]
|
|
56
63
|
#
|
|
57
|
-
# @rbs (Binder binder, Reactor reactor, AtomicThreadPool thread_pool,
|
|
58
|
-
def initialize: (Binder binder, Reactor reactor, AtomicThreadPool thread_pool,
|
|
64
|
+
# @rbs (Binder binder, Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], ?drain_accept_queue: bool) -> void
|
|
65
|
+
def initialize: (Binder binder, Reactor reactor, AtomicThreadPool thread_pool, Http1 http1, Http2 http2, connection_options: Hash[Symbol, untyped], ?drain_accept_queue: bool) -> void
|
|
59
66
|
|
|
60
67
|
# Starts the server's main accept loop in a new thread.
|
|
61
68
|
#
|
|
@@ -71,8 +78,9 @@ module Raptor
|
|
|
71
78
|
|
|
72
79
|
# Gracefully shuts down the server.
|
|
73
80
|
#
|
|
74
|
-
# Stops accepting new connections and closes all listening sockets.
|
|
75
|
-
#
|
|
81
|
+
# Stops accepting new connections and closes all listening sockets. When
|
|
82
|
+
# `drain_accept_queue` is enabled, dispatches every connection already in
|
|
83
|
+
# the kernel accept queue before closing the listeners.
|
|
76
84
|
#
|
|
77
85
|
# @return [void]
|
|
78
86
|
#
|
|
@@ -81,6 +89,14 @@ module Raptor
|
|
|
81
89
|
|
|
82
90
|
private
|
|
83
91
|
|
|
92
|
+
# Dispatches every connection already in the kernel accept queue for each
|
|
93
|
+
# listener until all are drained.
|
|
94
|
+
#
|
|
95
|
+
# @return [void]
|
|
96
|
+
#
|
|
97
|
+
# @rbs () -> void
|
|
98
|
+
def drain_accept_queue: () -> void
|
|
99
|
+
|
|
84
100
|
# Accepts a connection from the given listener and dispatches it.
|
|
85
101
|
#
|
|
86
102
|
# For SSL listeners the TLS handshake is offloaded to the thread pool so
|
|
@@ -90,11 +106,10 @@ module Raptor
|
|
|
90
106
|
# follow the HTTP/1.1 path.
|
|
91
107
|
#
|
|
92
108
|
# @param listener [TCPServer, UNIXServer, Binder::SslListener] the ready listener
|
|
93
|
-
# @
|
|
94
|
-
# @return [void]
|
|
109
|
+
# @return [Boolean] true if a connection was accepted, false if the listener had nothing to dispatch
|
|
95
110
|
#
|
|
96
|
-
# @rbs (TCPServer | UNIXServer | Binder::SslListener listener
|
|
97
|
-
def accept_connection: (TCPServer | UNIXServer | Binder::SslListener listener
|
|
111
|
+
# @rbs (TCPServer | UNIXServer | Binder::SslListener listener) -> bool
|
|
112
|
+
def accept_connection: (TCPServer | UNIXServer | Binder::SslListener listener) -> bool
|
|
98
113
|
|
|
99
114
|
# Performs the TLS handshake for an accepted SSL connection and dispatches
|
|
100
115
|
# it through the HTTP/2 or HTTP/1.1 path. The handshake is bounded by
|
|
@@ -103,11 +118,10 @@ module Raptor
|
|
|
103
118
|
# @param listener [Binder::SslListener] the SSL listener that accepted the connection
|
|
104
119
|
# @param tcp_client [TCPSocket] the accepted TCP socket
|
|
105
120
|
# @param remote_addr [String] the client's IP address
|
|
106
|
-
# @param reactor [Reactor] the reactor to dispatch the connection to
|
|
107
121
|
# @return [void]
|
|
108
122
|
#
|
|
109
|
-
# @rbs (Binder::SslListener listener, TCPSocket tcp_client, String remote_addr
|
|
110
|
-
def dispatch_ssl_connection: (Binder::SslListener listener, TCPSocket tcp_client, String remote_addr
|
|
123
|
+
# @rbs (Binder::SslListener listener, TCPSocket tcp_client, String remote_addr) -> void
|
|
124
|
+
def dispatch_ssl_connection: (Binder::SslListener listener, TCPSocket tcp_client, String remote_addr) -> void
|
|
111
125
|
|
|
112
126
|
# Drives a non-blocking SSL handshake to completion, bounded by the
|
|
113
127
|
# configured first-data timeout. Returns true on success, false on
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Generated from lib/raptor/systemd.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Raptor
|
|
4
|
+
# Integration with systemd's service notification protocol and
|
|
5
|
+
# socket-activation file descriptors.
|
|
6
|
+
module Systemd
|
|
7
|
+
LISTEN_FDS_START: ::Integer
|
|
8
|
+
|
|
9
|
+
LISTEN_FDNAMES_ENV: ::String
|
|
10
|
+
|
|
11
|
+
LISTEN_FDS_ENV: ::String
|
|
12
|
+
|
|
13
|
+
LISTEN_PID_ENV: ::String
|
|
14
|
+
|
|
15
|
+
NOTIFY_SOCKET_ENV: ::String
|
|
16
|
+
|
|
17
|
+
# Sends `message` to the systemd notification socket, returning true on
|
|
18
|
+
# success and false when the socket is unset or the send fails.
|
|
19
|
+
#
|
|
20
|
+
# @param message [String] notify protocol payload, e.g. "READY=1"
|
|
21
|
+
# @return [Boolean]
|
|
22
|
+
#
|
|
23
|
+
# @rbs (String message) -> bool
|
|
24
|
+
def self.notify: (String message) -> bool
|
|
25
|
+
|
|
26
|
+
# Returns the file descriptors passed in via socket activation, or an
|
|
27
|
+
# empty array when systemd has not exported any.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array<Integer>]
|
|
30
|
+
#
|
|
31
|
+
# @rbs () -> Array[Integer]
|
|
32
|
+
def self.listen_fds: () -> Array[Integer]
|
|
33
|
+
|
|
34
|
+
# Clears the socket-activation environment variables so children don't
|
|
35
|
+
# act on stale values.
|
|
36
|
+
#
|
|
37
|
+
# @return [void]
|
|
38
|
+
#
|
|
39
|
+
# @rbs () -> void
|
|
40
|
+
def self.clear_listen_env: () -> void
|
|
41
|
+
end
|
|
42
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: raptor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Young
|
|
@@ -121,24 +121,28 @@ files:
|
|
|
121
121
|
- lib/raptor/binder.rb
|
|
122
122
|
- lib/raptor/cli.rb
|
|
123
123
|
- lib/raptor/cluster.rb
|
|
124
|
+
- lib/raptor/http.rb
|
|
125
|
+
- lib/raptor/http1.rb
|
|
124
126
|
- lib/raptor/http2.rb
|
|
125
127
|
- lib/raptor/log.rb
|
|
126
128
|
- lib/raptor/reactor.rb
|
|
127
|
-
- lib/raptor/request.rb
|
|
128
129
|
- lib/raptor/server.rb
|
|
129
130
|
- lib/raptor/stats.rb
|
|
131
|
+
- lib/raptor/systemd.rb
|
|
130
132
|
- lib/raptor/version.rb
|
|
131
133
|
- sig/generated/rackup/handler/raptor.rbs
|
|
132
134
|
- sig/generated/raptor.rbs
|
|
133
135
|
- sig/generated/raptor/binder.rbs
|
|
134
136
|
- sig/generated/raptor/cli.rbs
|
|
135
137
|
- sig/generated/raptor/cluster.rbs
|
|
138
|
+
- sig/generated/raptor/http.rbs
|
|
139
|
+
- sig/generated/raptor/http1.rbs
|
|
136
140
|
- sig/generated/raptor/http2.rbs
|
|
137
141
|
- sig/generated/raptor/log.rbs
|
|
138
142
|
- sig/generated/raptor/reactor.rbs
|
|
139
|
-
- sig/generated/raptor/request.rbs
|
|
140
143
|
- sig/generated/raptor/server.rbs
|
|
141
144
|
- sig/generated/raptor/stats.rbs
|
|
145
|
+
- sig/generated/raptor/systemd.rbs
|
|
142
146
|
- sig/generated/raptor/version.rbs
|
|
143
147
|
homepage: https://github.com/joshuay03/raptor
|
|
144
148
|
licenses:
|