raptor 0.1.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.
@@ -0,0 +1,477 @@
1
+ # Generated from lib/raptor/request.rb with RBS::Inline
2
+
3
+ module Raptor
4
+ # Handles HTTP request processing and Rack application integration.
5
+ #
6
+ # Request manages the HTTP parsing pipeline using Ractors and coordinates
7
+ # with the reactor for connection state management. It bridges between the
8
+ # low-level HTTP parsing and high-level Rack application interface, handling
9
+ # both incomplete requests (that need more data) and complete requests
10
+ # (ready for application processing).
11
+ class Request
12
+ BODY_BUFFER_THRESHOLD: untyped
13
+
14
+ FILE_CHUNK_SIZE: untyped
15
+
16
+ KEEPALIVE_BUFFER_SIZE: untyped
17
+
18
+ WRITE_TIMEOUT: ::Integer
19
+
20
+ KEEPALIVE_READ_TIMEOUT: ::Float
21
+
22
+ MAX_KEEPALIVE_REQUESTS: ::Integer
23
+
24
+ HTTP_SCHEME: ::String
25
+
26
+ HTTP_10: ::String
27
+
28
+ HTTP_11: ::String
29
+
30
+ STATUS_LINE_CACHE_10: untyped
31
+
32
+ STATUS_LINE_CACHE_11: untyped
33
+
34
+ STATUS_WITH_NO_ENTITY_BODY: untyped
35
+
36
+ ERROR_RESPONSE_500: ::String
37
+
38
+ CONNECTION_CLOSE: ::String
39
+
40
+ CONNECTION_KEEPALIVE: ::String
41
+
42
+ TRANSFER_ENCODING_CHUNKED: ::String
43
+
44
+ HTTP_CONNECTION: ::String
45
+
46
+ HTTP_TRANSFER_ENCODING: ::String
47
+
48
+ RACK_HEADER_PREFIX: ::String
49
+
50
+ RACK_HIJACKED: ::String
51
+
52
+ RACK_HIJACK_IO: ::String
53
+
54
+ ILLEGAL_HEADER_KEY_REGEX: ::Regexp
55
+
56
+ ILLEGAL_HEADER_VALUE_REGEX: ::Regexp
57
+
58
+ class Error < StandardError
59
+ end
60
+
61
+ class WriteError < Error
62
+ # @rbs () -> String
63
+ def message: () -> String
64
+ end
65
+
66
+ @server_port: Integer
67
+
68
+ @app: ^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ]
69
+
70
+ # Creates a new Request handler.
71
+ #
72
+ # @param app [#call] the Rack application to dispatch complete requests to
73
+ # @param server_port [Integer] port number used to populate SERVER_PORT in the Rack env
74
+ # @return [void]
75
+ #
76
+ # @rbs (^(Hash[String, untyped]) -> [Integer, Hash[String, String | Array[String]], untyped] app, Integer server_port) -> void
77
+ def initialize: (^(Hash[String, untyped]) -> [ Integer, Hash[String, String | Array[String]], untyped ] app, Integer server_port) -> void
78
+
79
+ # Returns a Proc for HTTP parsing work in Ractor context.
80
+ #
81
+ # The returned Proc processes raw socket data through the appropriate
82
+ # HTTP parser and returns either a complete request state (ready for
83
+ # app processing) or incomplete request state (needs more data).
84
+ #
85
+ # @return [Proc] a Ractor-safe proc that accepts a state hash and returns an updated state hash
86
+ #
87
+ # @rbs () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
88
+ def http_parser_worker: () -> ^(Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
89
+
90
+ # Handles a parsed HTTP request by either continuing parsing or dispatching to the Rack app.
91
+ #
92
+ # For incomplete requests, updates reactor state and re-registers for more I/O.
93
+ # For complete requests, removes from reactor, builds Rack env, and dispatches to thread pool.
94
+ #
95
+ # @param parsed_request [Hash] the parsed request state from the ractor pool
96
+ # @param reactor [Reactor] the reactor managing the client connection
97
+ # @param thread_pool [AtomicThreadPool] thread pool for application processing
98
+ # @return [void]
99
+ #
100
+ # @rbs (Hash[Symbol, untyped] parsed_request, Reactor reactor, AtomicThreadPool thread_pool) -> void
101
+ def handle_parsed_request: (Hash[Symbol, untyped] parsed_request, Reactor reactor, AtomicThreadPool thread_pool) -> void
102
+
103
+ private
104
+
105
+ # Processes a client connection by handling the current request and,
106
+ # if keep-alive, eagerly reading subsequent requests inline.
107
+ #
108
+ # @param socket [TCPSocket] the client socket
109
+ # @param id [Integer] unique client identifier
110
+ # @param env [Hash] partial env hash from the HTTP parser
111
+ # @param parse_data [Hash] metadata from the parsing pass
112
+ # @param body [String, nil] decoded request body
113
+ # @param reactor [Reactor] the reactor managing the client connection
114
+ # @param thread_pool [AtomicThreadPool] thread pool for application processing
115
+ # @param request_count [Integer] number of requests handled on this connection
116
+ # @param remote_addr [String] client IP address
117
+ # @param url_scheme [String] "http" or "https"
118
+ # @return [void]
119
+ #
120
+ # @rbs (TCPSocket socket, Integer id, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, Reactor reactor, AtomicThreadPool thread_pool, Integer request_count, String remote_addr, String url_scheme) -> void
121
+ def process_client: (TCPSocket socket, Integer id, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, Reactor reactor, AtomicThreadPool thread_pool, Integer request_count, String remote_addr, String url_scheme) -> void
122
+
123
+ # Builds the Rack env, calls the application, and writes the response.
124
+ # Returns true if the connection should be kept alive for further
125
+ # requests, false otherwise (including hijack and error cases).
126
+ #
127
+ # @param socket [TCPSocket] the client socket
128
+ # @param env [Hash] partial env hash from the HTTP parser
129
+ # @param parse_data [Hash] metadata from the parsing pass
130
+ # @param body [String, nil] decoded request body
131
+ # @param request_count [Integer] number of requests handled on this connection
132
+ # @param remote_addr [String] client IP address
133
+ # @param url_scheme [String] "http" or "https"
134
+ # @return [Boolean] true if the connection should be kept alive
135
+ #
136
+ # @rbs (TCPSocket socket, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, Integer request_count, String remote_addr, String url_scheme) -> bool
137
+ def process_request: (TCPSocket socket, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, Integer request_count, String remote_addr, String url_scheme) -> bool
138
+
139
+ # Attempts to read and process subsequent requests inline on a
140
+ # kept-alive connection. Blocks briefly for the next request to avoid
141
+ # a full reactor round-trip. Falls back to the reactor when no data
142
+ # arrives within the timeout, when the thread pool has queued work
143
+ # (deprioritization), or when the request is incomplete.
144
+ #
145
+ # @param socket [TCPSocket] the client socket
146
+ # @param id [Integer] unique client identifier
147
+ # @param reactor [Reactor] the reactor for fallback registration
148
+ # @param thread_pool [AtomicThreadPool] thread pool for deprioritization
149
+ # @param request_count [Integer] number of requests handled on this connection
150
+ # @param remote_addr [String] client IP address
151
+ # @param url_scheme [String] "http" or "https"
152
+ # @return [void]
153
+ #
154
+ # @rbs (TCPSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, Integer request_count, String remote_addr, String url_scheme) -> void
155
+ def eager_keepalive: (TCPSocket socket, Integer id, Reactor reactor, AtomicThreadPool thread_pool, Integer request_count, String remote_addr, String url_scheme) -> void
156
+
157
+ # Re-registers a socket with the reactor for further processing
158
+ # when an incomplete request is received during eager keep-alive.
159
+ #
160
+ # @param socket [TCPSocket] the client socket
161
+ # @param id [Integer] unique client identifier
162
+ # @param buffer [String] the partial request data already read
163
+ # @param env [Hash] partial env hash from the HTTP parser
164
+ # @param parse_data [Hash] metadata from the parsing pass
165
+ # @param reactor [Reactor] the reactor to re-register with
166
+ # @param request_count [Integer] number of requests handled on this connection
167
+ # @param remote_addr [String] client IP address
168
+ # @param url_scheme [String] "http" or "https"
169
+ # @return [void]
170
+ #
171
+ # @rbs (TCPSocket socket, Integer id, String buffer, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, Reactor reactor, Integer request_count, String remote_addr, String url_scheme) -> void
172
+ def fallback_to_reactor: (TCPSocket socket, Integer id, String buffer, Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, Reactor reactor, Integer request_count, String remote_addr, String url_scheme) -> void
173
+
174
+ # Builds a Rack environment hash from parsed HTTP request data.
175
+ #
176
+ # Populates all required Rack env keys including rack.* keys, REMOTE_ADDR,
177
+ # SERVER_NAME, SERVER_PORT, and hijack support.
178
+ #
179
+ # @param env [Hash] partial env hash from the HTTP parser
180
+ # @param parse_data [Hash] metadata from the parsing pass, including content_length
181
+ # @param body [String, nil] decoded request body, or nil if no body
182
+ # @param socket [TCPSocket] the client socket, used for hijack support
183
+ # @param remote_addr [String] client IP address
184
+ # @param url_scheme [String] "http" or "https"
185
+ # @return [Hash] fully populated Rack environment hash
186
+ #
187
+ # @rbs (Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, TCPSocket socket, ?remote_addr: String, ?url_scheme: String) -> Hash[String, untyped]
188
+ def build_rack_env: (Hash[String, untyped] env, Hash[Symbol, untyped] parse_data, String? body, TCPSocket socket, ?remote_addr: String, ?url_scheme: String) -> Hash[String, untyped]
189
+
190
+ # Determines whether the connection should be kept alive after the response.
191
+ #
192
+ # Returns false if the request limit has been reached. For HTTP/1.1, keep-alive
193
+ # is the default unless the client sent Connection: close. For HTTP/1.0,
194
+ # keep-alive must be explicitly requested.
195
+ #
196
+ # @param env [Hash] the Rack environment
197
+ # @param request_count [Integer] number of requests handled on this connection
198
+ # @return [Boolean] true if the connection should be kept alive
199
+ #
200
+ # @rbs (Hash[String, untyped] env, Integer request_count) -> bool
201
+ def keep_alive?: (Hash[String, untyped] env, Integer request_count) -> bool
202
+
203
+ # Sends an HTTP 103 Early Hints response to the client.
204
+ #
205
+ # Skips any hints with illegal header keys or values. No-ops if hints is empty.
206
+ #
207
+ # @param socket [TCPSocket] the client socket to write to
208
+ # @param hints [Hash] header name to value (or array of values) pairs
209
+ # @return [void]
210
+ #
211
+ # @rbs (TCPSocket socket, Hash[String, String | Array[String]] hints) -> void
212
+ def send_early_hints: (TCPSocket socket, Hash[String, String | Array[String]] hints) -> void
213
+
214
+ # Writes a complete HTTP response to the socket.
215
+ #
216
+ # Handles header normalization, validation, connection management, TCP corking,
217
+ # and dispatches to the appropriate body write strategy.
218
+ #
219
+ # @param socket [TCPSocket] the client socket to write to
220
+ # @param env [Hash] the Rack environment
221
+ # @param status [Integer] HTTP status code
222
+ # @param headers [Hash] response headers from the Rack application
223
+ # @param body [Object] response body (array, enumerable, file, or callable)
224
+ # @param keep_alive [Boolean] whether to send a keep-alive connection header
225
+ # @return [void]
226
+ #
227
+ # @rbs (TCPSocket socket, Hash[String, untyped] env, Integer status, Hash[String, String | Array[String]] headers, untyped body, ?keep_alive: bool) -> void
228
+ def write_response: (TCPSocket socket, Hash[String, untyped] env, Integer status, Hash[String, String | Array[String]] headers, untyped body, ?keep_alive: bool) -> void
229
+
230
+ # Validates that the status code is a valid integer.
231
+ #
232
+ # @param status [Object] the status value to validate
233
+ # @return [void]
234
+ # @raise [TypeError] if status is not an Integer
235
+ # @raise [ArgumentError] if status is less than 100
236
+ #
237
+ # @rbs (Integer status) -> void
238
+ def validate_status: (Integer status) -> void
239
+
240
+ # Normalizes response headers by downcasing keys and filtering invalid entries.
241
+ #
242
+ # Removes headers with illegal keys, rack.* prefixed headers, and "status" headers.
243
+ # Raises if headers is not a Hash or contains non-String keys.
244
+ #
245
+ # @param headers [Hash] raw headers from the Rack application
246
+ # @return [Hash] normalized headers with lowercased string keys
247
+ # @raise [TypeError] if headers is not a Hash or a key is not a String
248
+ #
249
+ # @rbs (Hash[String, String | Array[String]] headers) -> Hash[String, String | Array[String]]
250
+ def normalize_headers: (Hash[String, String | Array[String]] headers) -> Hash[String, String | Array[String]]
251
+
252
+ # Validates that headers are appropriate for the given status code.
253
+ #
254
+ # Raises if content-type or content-length are present for status codes
255
+ # that must not have an entity body (204, 304, 1xx).
256
+ #
257
+ # @param headers [Hash] normalized response headers
258
+ # @param status [Integer] HTTP status code
259
+ # @return [void]
260
+ # @raise [ArgumentError] if a forbidden header is present for the status
261
+ #
262
+ # @rbs (Hash[String, String | Array[String]] headers, Integer status) -> void
263
+ def validate_headers: (Hash[String, String | Array[String]] headers, Integer status) -> void
264
+
265
+ # Builds the HTTP status line string.
266
+ #
267
+ # @param http_version [String] "HTTP/1.1" or "HTTP/1.0"
268
+ # @param status [Integer] HTTP status code
269
+ # @return [String] the status line including trailing CRLF
270
+ #
271
+ # @rbs (String http_version, Integer status) -> String
272
+ def build_status_line: (String http_version, Integer status) -> String
273
+
274
+ # Writes response headers and delegates body writing to the hijack callback.
275
+ #
276
+ # Uncorks the socket before calling the hijack so the app has full control
277
+ # of the raw connection.
278
+ #
279
+ # @param socket [TCPSocket] the client socket
280
+ # @param response [String] the status line accumulated so far
281
+ # @param headers [Hash] normalized response headers
282
+ # @param response_hijack [Proc] callable that receives the socket and writes the body
283
+ # @return [void]
284
+ #
285
+ # @rbs (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, ^(TCPSocket) -> void response_hijack) -> void
286
+ def write_hijacked_response: (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, ^(TCPSocket) -> void response_hijack) -> void
287
+
288
+ # Writes a response with no entity body.
289
+ #
290
+ # Used for HEAD requests and status codes that must not carry a body
291
+ # (204, 304, 1xx). Adds a zero content-length for non-no-body statuses
292
+ # that did not supply one.
293
+ #
294
+ # @param socket [TCPSocket] the client socket
295
+ # @param response [String] the status line accumulated so far
296
+ # @param headers [Hash] normalized response headers
297
+ # @param status [Integer] HTTP status code
298
+ # @return [void]
299
+ #
300
+ # @rbs (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, Integer status) -> void
301
+ def write_no_body_response: (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, Integer status) -> void
302
+
303
+ # Writes a complete response with a body.
304
+ #
305
+ # Selects the appropriate write strategy based on body type: callable (streaming),
306
+ # file (zero-copy), array, or generic enumerable. Automatically determines
307
+ # content-length where possible, falling back to chunked transfer encoding
308
+ # for HTTP/1.1 when the length cannot be determined upfront.
309
+ #
310
+ # @param socket [TCPSocket] the client socket
311
+ # @param response [String] the status line accumulated so far
312
+ # @param headers [Hash] normalized response headers
313
+ # @param body [Object] the response body
314
+ # @param http_version [String] "HTTP/1.1" or "HTTP/1.0"
315
+ # @return [void]
316
+ #
317
+ # @rbs (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, untyped body, String http_version) -> void
318
+ def write_full_response: (TCPSocket socket, String response, Hash[String, String | Array[String]] headers, untyped body, String http_version) -> void
319
+
320
+ # Calculates content length from an array or file body without consuming it.
321
+ #
322
+ # Returns nil for enumerable bodies whose length cannot be determined upfront.
323
+ #
324
+ # @param body [Object] the response body
325
+ # @return [Integer, nil] the byte length, or nil if it cannot be determined
326
+ #
327
+ # @rbs (untyped body) -> Integer?
328
+ def calculate_content_length: (untyped body) -> Integer?
329
+
330
+ # Writes a file body to the socket.
331
+ #
332
+ # Uses zero-copy IO.copy_stream for large files, direct buffering for small ones,
333
+ # and chunked encoding when required.
334
+ #
335
+ # @param socket [TCPSocket] the client socket
336
+ # @param response [String] headers already serialized, to be written before the body
337
+ # @param path [String] filesystem path of the file to send
338
+ # @param content_length [Integer, nil] pre-calculated file size
339
+ # @param use_chunked [Boolean] whether to use chunked transfer encoding
340
+ # @return [void]
341
+ #
342
+ # @rbs (TCPSocket socket, String response, String path, Integer? content_length, bool use_chunked) -> void
343
+ def write_file_body: (TCPSocket socket, String response, String path, Integer? content_length, bool use_chunked) -> void
344
+
345
+ # Writes an array body to the socket.
346
+ #
347
+ # Dispatches to the single-chunk or multi-chunk path based on array length.
348
+ #
349
+ # @param socket [TCPSocket] the client socket
350
+ # @param response [String] headers already serialized, to be written before the body
351
+ # @param body_array [Array<String>] the response body chunks
352
+ # @param use_chunked [Boolean] whether to use chunked transfer encoding
353
+ # @return [void]
354
+ #
355
+ # @rbs (TCPSocket socket, String response, Array[String] body_array, bool use_chunked) -> void
356
+ def write_array_body: (TCPSocket socket, String response, Array[String] body_array, bool use_chunked) -> void
357
+
358
+ # Writes a single-element array body, optionally buffering it with the headers.
359
+ #
360
+ # Small bodies are concatenated with the headers into one write to reduce
361
+ # system call overhead.
362
+ #
363
+ # @param socket [TCPSocket] the client socket
364
+ # @param response [String] headers already serialized, to be written before the body
365
+ # @param chunk [String] the single body chunk
366
+ # @param use_chunked [Boolean] whether to use chunked transfer encoding
367
+ # @return [void]
368
+ # @raise [TypeError] if the chunk is not a String
369
+ #
370
+ # @rbs (TCPSocket socket, String response, String chunk, bool use_chunked) -> void
371
+ def write_single_chunk: (TCPSocket socket, String response, String chunk, bool use_chunked) -> void
372
+
373
+ # Writes a multi-element array body to the socket.
374
+ #
375
+ # @param socket [TCPSocket] the client socket
376
+ # @param response [String] headers already serialized, to be written before the body
377
+ # @param body_array [Array<String>] the response body chunks
378
+ # @param use_chunked [Boolean] whether to use chunked transfer encoding
379
+ # @return [void]
380
+ # @raise [TypeError] if any chunk is not a String
381
+ #
382
+ # @rbs (TCPSocket socket, String response, Array[String] body_array, bool use_chunked) -> void
383
+ def write_multiple_chunks: (TCPSocket socket, String response, Array[String] body_array, bool use_chunked) -> void
384
+
385
+ # Writes a generic enumerable body to the socket.
386
+ #
387
+ # @param socket [TCPSocket] the client socket
388
+ # @param response [String] headers already serialized, to be written before the body
389
+ # @param body [Object] any object responding to each
390
+ # @param use_chunked [Boolean] whether to use chunked transfer encoding
391
+ # @return [void]
392
+ # @raise [TypeError] if any yielded chunk is not a String
393
+ #
394
+ # @rbs (TCPSocket socket, String response, untyped body, bool use_chunked) -> void
395
+ def write_enumerable_body: (TCPSocket socket, String response, untyped body, bool use_chunked) -> void
396
+
397
+ # Returns true if the header key contains characters illegal in HTTP headers.
398
+ #
399
+ # @param key [String] the header key to check
400
+ # @return [Boolean] true if the key is illegal
401
+ #
402
+ # @rbs (String key) -> bool
403
+ def illegal_header_key?: (String key) -> bool
404
+
405
+ # Returns true if the header value contains characters illegal in HTTP headers.
406
+ #
407
+ # @param value [String] the header value to check
408
+ # @return [Boolean] true if the value is illegal
409
+ #
410
+ # @rbs (String value) -> bool
411
+ def illegal_header_value?: (String value) -> bool
412
+
413
+ # Formats a headers hash into an HTTP header string.
414
+ #
415
+ # Skips entries with illegal keys or values. Array values are written
416
+ # as separate header lines.
417
+ #
418
+ # @param headers [Hash] normalized response headers
419
+ # @return [String] formatted header lines, each ending with CRLF
420
+ #
421
+ # @rbs (Hash[String, String | Array[String]] headers) -> String
422
+ def format_headers: (Hash[String, String | Array[String]] headers) -> String
423
+
424
+ # Calls all rack.response_finished callbacks registered in the environment.
425
+ #
426
+ # Callbacks are called in reverse registration order. Individual callback
427
+ # failures are rescued so all callbacks are always attempted.
428
+ #
429
+ # @param env [Hash, nil] the Rack environment
430
+ # @param status [Integer, nil] the response status code
431
+ # @param headers [Hash, nil] the response headers
432
+ # @param error [Exception, nil] any error raised during processing, or nil on success
433
+ # @return [void]
434
+ #
435
+ # @rbs (Hash[String, untyped] env, Integer? status, Hash[String, String | Array[String]]? headers, Exception? error) -> void
436
+ def call_response_finished: (Hash[String, untyped] env, Integer? status, Hash[String, String | Array[String]]? headers, Exception? error) -> void
437
+
438
+ # Writes a string to the socket, retrying on partial writes and flow control blocks.
439
+ #
440
+ # Uses write_nonblock with a 5-second writable timeout to avoid blocking the
441
+ # thread indefinitely on slow clients.
442
+ #
443
+ # @param socket [TCPSocket] the socket to write to
444
+ # @param string [String] the data to write
445
+ # @return [void]
446
+ # @raise [WriteError] if the socket is not writable within the timeout or raises IOError
447
+ #
448
+ # @rbs (TCPSocket socket, String string) -> void
449
+ def socket_write: (TCPSocket socket, String string) -> void
450
+
451
+ # Enables TCP_CORK on the socket to batch outgoing packets into fewer segments.
452
+ #
453
+ # Only applies to TCP sockets. No-op on non-TCP sockets.
454
+ # Available on Linux only; this method is not defined on other platforms.
455
+ #
456
+ # @param socket [TCPSocket] the socket to cork
457
+ # @return [void]
458
+ #
459
+ # @rbs (TCPSocket socket) -> void
460
+ def cork_socket: (TCPSocket socket) -> void
461
+
462
+ # Disables TCP_CORK on the socket, flushing any buffered packets.
463
+ #
464
+ # Only applies to TCP sockets. No-op on non-TCP sockets.
465
+ # Available on Linux only; this method is not defined on other platforms.
466
+ #
467
+ # @param socket [TCPSocket] the socket to uncork
468
+ # @return [void]
469
+ #
470
+ # @rbs (TCPSocket socket) -> void
471
+ def uncork_socket: (TCPSocket socket) -> void
472
+
473
+ def cork_socket: (untyped socket) -> untyped
474
+
475
+ def uncork_socket: (untyped socket) -> untyped
476
+ end
477
+ end
@@ -0,0 +1,88 @@
1
+ # Generated from lib/raptor/server.rb with RBS::Inline
2
+
3
+ module Raptor
4
+ # High-performance HTTP server that accepts connections and dispatches them.
5
+ #
6
+ # Server manages the main accept loop, handling incoming client connections from
7
+ # bound sockets. It uses IO.select for efficient polling and implements automatic
8
+ # load balancing by checking reactor backlog before accepting connections,
9
+ # providing natural backpressure based on system capacity.
10
+ #
11
+ # Supports TCP, Unix domain, and SSL listeners transparently. TCP_NODELAY is
12
+ # applied only to TCP sockets, and SSL handshakes are performed synchronously
13
+ # before handing the connection to the reactor.
14
+ #
15
+ # For SSL connections, ALPN negotiation determines the protocol. HTTP/2
16
+ # connections are added to the reactor with initial SETTINGS and processed
17
+ # through the same ractor pool pipeline as HTTP/1.1 connections.
18
+ #
19
+ # @example
20
+ # binder = Binder.new(["tcp://0.0.0.0:3000"])
21
+ # reactor = Reactor.new(thread_pool, ractor_pool, client_options: {})
22
+ # server = Server.new(binder, reactor, thread_pool)
23
+ # server.run
24
+ # # ... later
25
+ # server.shutdown
26
+ class Server
27
+ HTTP_SCHEME: ::String
28
+
29
+ HTTPS_SCHEME: ::String
30
+
31
+ H2_PROTOCOL: ::String
32
+
33
+ @binder: Binder
34
+
35
+ @reactor: Reactor
36
+
37
+ @thread_pool: AtomicThreadPool
38
+
39
+ @running: AtomicBoolean
40
+
41
+ # Creates a new Server instance.
42
+ #
43
+ # @param binder [Binder] the binder managing listening sockets
44
+ # @param reactor [Reactor] the reactor for handling client connections
45
+ # @param thread_pool [AtomicThreadPool] thread pool for application processing
46
+ # @return [void]
47
+ #
48
+ # @rbs (Binder binder, Reactor reactor, AtomicThreadPool thread_pool) -> void
49
+ def initialize: (Binder binder, Reactor reactor, AtomicThreadPool thread_pool) -> void
50
+
51
+ # Starts the server's main accept loop in a new thread.
52
+ #
53
+ # The accept loop polls listening sockets for ready connections and accepts
54
+ # them when system capacity allows. It checks reactor backlog before accepting
55
+ # to prevent overload. This provides natural load balancing across multiple
56
+ # worker processes through backpressure control.
57
+ #
58
+ # @return [Thread] the thread running the accept loop
59
+ #
60
+ # @rbs () -> Thread
61
+ def run: () -> Thread
62
+
63
+ # Gracefully shuts down the server.
64
+ #
65
+ # Stops accepting new connections and closes all listening sockets.
66
+ # The server thread will exit after handling any in-flight accept operations.
67
+ #
68
+ # @return [void]
69
+ #
70
+ # @rbs () -> void
71
+ def shutdown: () -> void
72
+
73
+ private
74
+
75
+ # Accepts a connection from the given listener and dispatches it.
76
+ #
77
+ # For SSL connections with h2 negotiated via ALPN, the server sends
78
+ # initial SETTINGS and adds the connection to the reactor as an HTTP/2
79
+ # connection. All other connections follow the HTTP/1.1 path.
80
+ #
81
+ # @param listener [TCPServer, UNIXServer, Binder::SslListener] the ready listener
82
+ # @param reactor [Reactor] the reactor to dispatch connections to
83
+ # @return [void]
84
+ #
85
+ # @rbs (TCPServer | UNIXServer | Binder::SslListener listener, Reactor reactor) -> void
86
+ def accept_connection: (TCPServer | UNIXServer | Binder::SslListener listener, Reactor reactor) -> void
87
+ end
88
+ end
@@ -0,0 +1,78 @@
1
+ # Generated from lib/raptor/stats.rb with RBS::Inline
2
+
3
+ module Raptor
4
+ # Shared memory store for per-worker process statistics.
5
+ #
6
+ # Stats uses an anonymous mmap (MAP_ANON | MAP_SHARED) created before
7
+ # forking so that worker processes can write their stats and the master
8
+ # process can read them without any pipes or signals. Each worker is
9
+ # assigned a fixed-size slot in the shared region.
10
+ #
11
+ # Binary layout per slot (native byte order):
12
+ # pid uint32 4 bytes
13
+ # requests uint64 8 bytes
14
+ # backlog uint32 4 bytes
15
+ # started_at float64 8 bytes
16
+ # last_checkin float64 8 bytes
17
+ # booted uint8 1 byte
18
+ # 33 bytes total
19
+ class Stats
20
+ SLOT_FORMAT: ::String
21
+
22
+ SLOT_SIZE: untyped
23
+
24
+ @num_workers: Integer
25
+
26
+ @mmap: untyped
27
+
28
+ # Creates a new Stats instance backed by anonymous shared memory.
29
+ #
30
+ # Allocates a MAP_ANON | MAP_SHARED mmap region large enough for
31
+ # num_workers slots. Must be called before forking so that all
32
+ # worker processes share the same backing memory.
33
+ #
34
+ # @param num_workers [Integer] number of worker slots to allocate
35
+ # @return [void]
36
+ #
37
+ # @rbs (Integer num_workers) -> void
38
+ def initialize: (Integer num_workers) -> void
39
+
40
+ # Writes stats for a worker slot into shared memory.
41
+ #
42
+ # @param index [Integer] slot index to write into
43
+ # @param pid [Integer] worker process ID
44
+ # @param requests [Integer] total requests handled by this worker
45
+ # @param backlog [Integer] current queue depth
46
+ # @param started_at [Float] process start time as a Unix timestamp
47
+ # @param last_checkin [Float] time of last stats write as a Unix timestamp
48
+ # @param booted [Boolean] whether the worker has finished starting
49
+ # @return [void]
50
+ #
51
+ # @rbs (Integer index, pid: Integer, requests: Integer, backlog: Integer, started_at: Float, last_checkin: Float, booted: bool) -> void
52
+ def write: (Integer index, pid: Integer, requests: Integer, backlog: Integer, started_at: Float, last_checkin: Float, booted: bool) -> void
53
+
54
+ # Returns stats for all worker slots.
55
+ #
56
+ # @return [Array<Hash>] per-worker stat hashes with :pid, :requests, :backlog, :started_at, :last_checkin, and :booted
57
+ #
58
+ # @rbs () -> Array[Hash[Symbol, untyped]]
59
+ def all: () -> Array[Hash[Symbol, untyped]]
60
+
61
+ # Releases the shared memory mapping.
62
+ #
63
+ # @return [void]
64
+ #
65
+ # @rbs () -> void
66
+ def unmap: () -> void
67
+
68
+ private
69
+
70
+ # Reads stats for a worker slot from shared memory.
71
+ #
72
+ # @param index [Integer] slot index to read from
73
+ # @return [Hash] stat hash with :pid, :requests, :backlog, :started_at, :last_checkin, and :booted
74
+ #
75
+ # @rbs (Integer index) -> Hash[Symbol, untyped]
76
+ def read: (Integer index) -> Hash[Symbol, untyped]
77
+ end
78
+ end
@@ -0,0 +1,5 @@
1
+ # Generated from lib/raptor/version.rb with RBS::Inline
2
+
3
+ module Raptor
4
+ VERSION: ::String
5
+ end
@@ -0,0 +1,9 @@
1
+ # Generated from lib/raptor.rb with RBS::Inline
2
+
3
+ # Main module for the Raptor web server.
4
+ #
5
+ # Raptor is a high-performance, multi-threaded, multi-process Ruby web server that
6
+ # leverages Ractors for parallel HTTP/1.1 and HTTP/2 request processing, native C
7
+ # extensions for HTTP parsing and HPACK compression, and NIO for non-blocking I/O.
8
+ module Raptor
9
+ end