itsi-server 0.1.1

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,355 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "1.1.3"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "bindgen"
16
+ version = "0.69.5"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
19
+ dependencies = [
20
+ "bitflags",
21
+ "cexpr",
22
+ "clang-sys",
23
+ "itertools",
24
+ "lazy_static",
25
+ "lazycell",
26
+ "proc-macro2",
27
+ "quote",
28
+ "regex",
29
+ "rustc-hash",
30
+ "shlex",
31
+ "syn",
32
+ ]
33
+
34
+ [[package]]
35
+ name = "bitflags"
36
+ version = "2.8.0"
37
+ source = "registry+https://github.com/rust-lang/crates.io-index"
38
+ checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
39
+
40
+ [[package]]
41
+ name = "bytes"
42
+ version = "1.10.0"
43
+ source = "registry+https://github.com/rust-lang/crates.io-index"
44
+ checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
45
+
46
+ [[package]]
47
+ name = "cexpr"
48
+ version = "0.6.0"
49
+ source = "registry+https://github.com/rust-lang/crates.io-index"
50
+ checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
51
+ dependencies = [
52
+ "nom",
53
+ ]
54
+
55
+ [[package]]
56
+ name = "cfg-if"
57
+ version = "1.0.0"
58
+ source = "registry+https://github.com/rust-lang/crates.io-index"
59
+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
60
+
61
+ [[package]]
62
+ name = "clang-sys"
63
+ version = "1.8.1"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
66
+ dependencies = [
67
+ "glob",
68
+ "libc",
69
+ "libloading",
70
+ ]
71
+
72
+ [[package]]
73
+ name = "either"
74
+ version = "1.14.0"
75
+ source = "registry+https://github.com/rust-lang/crates.io-index"
76
+ checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
77
+
78
+ [[package]]
79
+ name = "glob"
80
+ version = "0.3.2"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
83
+
84
+ [[package]]
85
+ name = "itertools"
86
+ version = "0.12.1"
87
+ source = "registry+https://github.com/rust-lang/crates.io-index"
88
+ checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
89
+ dependencies = [
90
+ "either",
91
+ ]
92
+
93
+ [[package]]
94
+ name = "itsi_rb_helpers"
95
+ version = "0.1.0"
96
+ dependencies = [
97
+ "magnus",
98
+ "rb-sys",
99
+ ]
100
+
101
+ [[package]]
102
+ name = "lazy_static"
103
+ version = "1.5.0"
104
+ source = "registry+https://github.com/rust-lang/crates.io-index"
105
+ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
106
+
107
+ [[package]]
108
+ name = "lazycell"
109
+ version = "1.3.0"
110
+ source = "registry+https://github.com/rust-lang/crates.io-index"
111
+ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
112
+
113
+ [[package]]
114
+ name = "libc"
115
+ version = "0.2.170"
116
+ source = "registry+https://github.com/rust-lang/crates.io-index"
117
+ checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
118
+
119
+ [[package]]
120
+ name = "libloading"
121
+ version = "0.8.6"
122
+ source = "registry+https://github.com/rust-lang/crates.io-index"
123
+ checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
124
+ dependencies = [
125
+ "cfg-if",
126
+ "windows-targets",
127
+ ]
128
+
129
+ [[package]]
130
+ name = "magnus"
131
+ version = "0.7.1"
132
+ source = "registry+https://github.com/rust-lang/crates.io-index"
133
+ checksum = "3d87ae53030f3a22e83879e666cb94e58a7bdf31706878a0ba48752994146dab"
134
+ dependencies = [
135
+ "bytes",
136
+ "magnus-macros",
137
+ "rb-sys",
138
+ "rb-sys-env",
139
+ "seq-macro",
140
+ ]
141
+
142
+ [[package]]
143
+ name = "magnus-macros"
144
+ version = "0.6.0"
145
+ source = "registry+https://github.com/rust-lang/crates.io-index"
146
+ checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3"
147
+ dependencies = [
148
+ "proc-macro2",
149
+ "quote",
150
+ "syn",
151
+ ]
152
+
153
+ [[package]]
154
+ name = "memchr"
155
+ version = "2.7.4"
156
+ source = "registry+https://github.com/rust-lang/crates.io-index"
157
+ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
158
+
159
+ [[package]]
160
+ name = "minimal-lexical"
161
+ version = "0.2.1"
162
+ source = "registry+https://github.com/rust-lang/crates.io-index"
163
+ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
164
+
165
+ [[package]]
166
+ name = "nom"
167
+ version = "7.1.3"
168
+ source = "registry+https://github.com/rust-lang/crates.io-index"
169
+ checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
170
+ dependencies = [
171
+ "memchr",
172
+ "minimal-lexical",
173
+ ]
174
+
175
+ [[package]]
176
+ name = "proc-macro2"
177
+ version = "1.0.93"
178
+ source = "registry+https://github.com/rust-lang/crates.io-index"
179
+ checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
180
+ dependencies = [
181
+ "unicode-ident",
182
+ ]
183
+
184
+ [[package]]
185
+ name = "quote"
186
+ version = "1.0.38"
187
+ source = "registry+https://github.com/rust-lang/crates.io-index"
188
+ checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
189
+ dependencies = [
190
+ "proc-macro2",
191
+ ]
192
+
193
+ [[package]]
194
+ name = "rb-sys"
195
+ version = "0.9.110"
196
+ source = "registry+https://github.com/rust-lang/crates.io-index"
197
+ checksum = "56cf964f8e44115e50009921ea3d3791b6f74d1ae6d6ed37114fbe03a1cd7308"
198
+ dependencies = [
199
+ "rb-sys-build",
200
+ ]
201
+
202
+ [[package]]
203
+ name = "rb-sys-build"
204
+ version = "0.9.110"
205
+ source = "registry+https://github.com/rust-lang/crates.io-index"
206
+ checksum = "161480347f56473107d4135643b6b1909331eec61445e113b256708a28b691c5"
207
+ dependencies = [
208
+ "bindgen",
209
+ "lazy_static",
210
+ "proc-macro2",
211
+ "quote",
212
+ "regex",
213
+ "shell-words",
214
+ "syn",
215
+ ]
216
+
217
+ [[package]]
218
+ name = "rb-sys-env"
219
+ version = "0.1.2"
220
+ source = "registry+https://github.com/rust-lang/crates.io-index"
221
+ checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb"
222
+
223
+ [[package]]
224
+ name = "regex"
225
+ version = "1.11.1"
226
+ source = "registry+https://github.com/rust-lang/crates.io-index"
227
+ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
228
+ dependencies = [
229
+ "aho-corasick",
230
+ "memchr",
231
+ "regex-automata",
232
+ "regex-syntax",
233
+ ]
234
+
235
+ [[package]]
236
+ name = "regex-automata"
237
+ version = "0.4.9"
238
+ source = "registry+https://github.com/rust-lang/crates.io-index"
239
+ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
240
+ dependencies = [
241
+ "aho-corasick",
242
+ "memchr",
243
+ "regex-syntax",
244
+ ]
245
+
246
+ [[package]]
247
+ name = "regex-syntax"
248
+ version = "0.8.5"
249
+ source = "registry+https://github.com/rust-lang/crates.io-index"
250
+ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
251
+
252
+ [[package]]
253
+ name = "rustc-hash"
254
+ version = "1.1.0"
255
+ source = "registry+https://github.com/rust-lang/crates.io-index"
256
+ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
257
+
258
+ [[package]]
259
+ name = "seq-macro"
260
+ version = "0.3.5"
261
+ source = "registry+https://github.com/rust-lang/crates.io-index"
262
+ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
263
+
264
+ [[package]]
265
+ name = "shell-words"
266
+ version = "1.1.0"
267
+ source = "registry+https://github.com/rust-lang/crates.io-index"
268
+ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
269
+
270
+ [[package]]
271
+ name = "shlex"
272
+ version = "1.3.0"
273
+ source = "registry+https://github.com/rust-lang/crates.io-index"
274
+ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
275
+
276
+ [[package]]
277
+ name = "syn"
278
+ version = "2.0.98"
279
+ source = "registry+https://github.com/rust-lang/crates.io-index"
280
+ checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
281
+ dependencies = [
282
+ "proc-macro2",
283
+ "quote",
284
+ "unicode-ident",
285
+ ]
286
+
287
+ [[package]]
288
+ name = "unicode-ident"
289
+ version = "1.0.17"
290
+ source = "registry+https://github.com/rust-lang/crates.io-index"
291
+ checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
292
+
293
+ [[package]]
294
+ name = "windows-targets"
295
+ version = "0.52.6"
296
+ source = "registry+https://github.com/rust-lang/crates.io-index"
297
+ checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
298
+ dependencies = [
299
+ "windows_aarch64_gnullvm",
300
+ "windows_aarch64_msvc",
301
+ "windows_i686_gnu",
302
+ "windows_i686_gnullvm",
303
+ "windows_i686_msvc",
304
+ "windows_x86_64_gnu",
305
+ "windows_x86_64_gnullvm",
306
+ "windows_x86_64_msvc",
307
+ ]
308
+
309
+ [[package]]
310
+ name = "windows_aarch64_gnullvm"
311
+ version = "0.52.6"
312
+ source = "registry+https://github.com/rust-lang/crates.io-index"
313
+ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
314
+
315
+ [[package]]
316
+ name = "windows_aarch64_msvc"
317
+ version = "0.52.6"
318
+ source = "registry+https://github.com/rust-lang/crates.io-index"
319
+ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
320
+
321
+ [[package]]
322
+ name = "windows_i686_gnu"
323
+ version = "0.52.6"
324
+ source = "registry+https://github.com/rust-lang/crates.io-index"
325
+ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
326
+
327
+ [[package]]
328
+ name = "windows_i686_gnullvm"
329
+ version = "0.52.6"
330
+ source = "registry+https://github.com/rust-lang/crates.io-index"
331
+ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
332
+
333
+ [[package]]
334
+ name = "windows_i686_msvc"
335
+ version = "0.52.6"
336
+ source = "registry+https://github.com/rust-lang/crates.io-index"
337
+ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
338
+
339
+ [[package]]
340
+ name = "windows_x86_64_gnu"
341
+ version = "0.52.6"
342
+ source = "registry+https://github.com/rust-lang/crates.io-index"
343
+ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
344
+
345
+ [[package]]
346
+ name = "windows_x86_64_gnullvm"
347
+ version = "0.52.6"
348
+ source = "registry+https://github.com/rust-lang/crates.io-index"
349
+ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
350
+
351
+ [[package]]
352
+ name = "windows_x86_64_msvc"
353
+ version = "0.52.6"
354
+ source = "registry+https://github.com/rust-lang/crates.io-index"
355
+ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
@@ -0,0 +1,8 @@
1
+ [package]
2
+ name = "itsi_rb_helpers"
3
+ version = "0.1.0"
4
+ edition = "2024"
5
+
6
+ [dependencies]
7
+ magnus = { version = "0.7.1", features = ["rb-sys", "bytes"] }
8
+ rb-sys = "0.9.105"
@@ -0,0 +1,98 @@
1
+ use std::{os::raw::c_void, ptr::null_mut};
2
+
3
+ use rb_sys::{
4
+ rb_thread_call_with_gvl, rb_thread_call_without_gvl, rb_thread_create, rb_thread_wakeup,
5
+ };
6
+
7
+ pub fn create_ruby_thread<F>(f: F)
8
+ where
9
+ F: FnOnce() -> u64 + Send + 'static,
10
+ {
11
+ extern "C" fn trampoline<F>(ptr: *mut c_void) -> u64
12
+ where
13
+ F: FnOnce() -> u64,
14
+ {
15
+ // Reconstruct the boxed Option<F> that holds our closure.
16
+ let boxed_closure: Box<Option<F>> = unsafe { Box::from_raw(ptr as *mut Option<F>) };
17
+ // Extract the closure. (The Option should be Some; panic otherwise.)
18
+ let closure = (*boxed_closure).expect("Closure already taken");
19
+ // Call the closure and return its result.
20
+ closure()
21
+ }
22
+
23
+ // Box the closure (wrapped in an Option) to create a stable pointer.
24
+ let boxed_closure = Box::new(Some(f));
25
+ let ptr = Box::into_raw(boxed_closure) as *mut c_void;
26
+
27
+ // Call rb_thread_create with our trampoline and boxed closure.
28
+ unsafe {
29
+ rb_thread_wakeup(rb_thread_create(Some(trampoline::<F>), ptr));
30
+ }
31
+ }
32
+
33
+ pub fn call_without_gvl<F, R>(f: F) -> R
34
+ where
35
+ F: FnOnce() -> R,
36
+ {
37
+ // This is the function that Ruby calls “in the background” with the GVL released.
38
+ extern "C" fn trampoline<F, R>(arg: *mut c_void) -> *mut c_void
39
+ where
40
+ F: FnOnce() -> R,
41
+ {
42
+ // 1) Reconstruct the Box that holds our closure
43
+ let closure_ptr = arg as *mut Option<F>;
44
+ let closure = unsafe { (*closure_ptr).take().expect("Closure already taken") };
45
+
46
+ // 2) Call the user’s closure
47
+ let result = closure();
48
+
49
+ // 3) Box up the result so we can return a pointer to it
50
+ let boxed_result = Box::new(result);
51
+ Box::into_raw(boxed_result) as *mut c_void
52
+ }
53
+
54
+ // Box up the closure so we have a stable pointer
55
+ let mut closure_opt = Some(f);
56
+ let closure_ptr = &mut closure_opt as *mut Option<F> as *mut c_void;
57
+
58
+ // 4) Actually call `rb_thread_call_without_gvl`
59
+ let raw_result_ptr = unsafe {
60
+ rb_thread_call_without_gvl(Some(trampoline::<F, R>), closure_ptr, None, null_mut())
61
+ };
62
+
63
+ // 5) Convert the returned pointer back into R
64
+ let result_box = unsafe { Box::from_raw(raw_result_ptr as *mut R) };
65
+ *result_box
66
+ }
67
+
68
+ pub fn call_with_gvl<F, R>(f: F) -> R
69
+ where
70
+ F: FnOnce() -> R,
71
+ {
72
+ extern "C" fn trampoline<F, R>(arg: *mut c_void) -> *mut c_void
73
+ where
74
+ F: FnOnce() -> R,
75
+ {
76
+ // 1) Reconstruct the Box that holds our closure
77
+ let closure_ptr = arg as *mut Option<F>;
78
+ let closure = unsafe { (*closure_ptr).take().expect("Closure already taken") };
79
+
80
+ // 2) Call the user’s closure
81
+ let result = closure();
82
+
83
+ // 3) Box up the result so we can return a pointer to it
84
+ let boxed_result = Box::new(result);
85
+ Box::into_raw(boxed_result) as *mut c_void
86
+ }
87
+
88
+ // Box up the closure so we have a stable pointer
89
+ let mut closure_opt = Some(f);
90
+ let closure_ptr = &mut closure_opt as *mut Option<F> as *mut c_void;
91
+
92
+ // 4) Actually call `rb_thread_call_without_gvl`
93
+ let raw_result_ptr = unsafe { rb_thread_call_with_gvl(Some(trampoline::<F, R>), closure_ptr) };
94
+
95
+ // 5) Convert the returned pointer back into R
96
+ let result_box = unsafe { Box::from_raw(raw_result_ptr as *mut R) };
97
+ *result_box
98
+ }
@@ -0,0 +1,29 @@
1
+ [package]
2
+ name = "itsi-server"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
+ license = "MIT"
7
+ publish = false
8
+
9
+ [lib]
10
+ crate-type = ["cdylib"]
11
+
12
+ [dependencies]
13
+ magnus = { version = "0.7.1", features = ["bytes"] }
14
+ itsi_tracing = { path = "../itsi_tracing" }
15
+ itsi_rb_helpers = { path = "../itsi_rb_helpers" }
16
+ itsi_error = { path = "../itsi_error" }
17
+ socket2 = "0.5.8"
18
+ parking_lot = "0.12.3"
19
+ rustls-pemfile = "2.2.0"
20
+ tokio-rustls = "0.23"
21
+ bytes = "1.3"
22
+ rcgen = { version = "0.13.2", features = ["x509-parser", "pem"] }
23
+ base64 = "0.22.1"
24
+ http-body-util = "0.1.2"
25
+ hyper = { version = "1.5.0", features = ["full", "server", "http1", "http2"] }
26
+ tokio = { version = "1", features = ["full"] }
27
+ hyper-util = { version = "0.1.10", features = ["full"] }
28
+ derive_more = { version = "2.0.1", features = ["debug"] }
29
+ http = "1.2.0"
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+ require "rb_sys/mkmf"
5
+
6
+ create_rust_makefile("itsi_server/itsi_server")
@@ -0,0 +1,52 @@
1
+ use magnus::{error::Result, function, method, value::Lazy, Module, Object, RClass, RModule, Ruby};
2
+ use request::itsi_request::ItsiRequest;
3
+ use server::itsi_server::Server;
4
+ use stream_writer::StreamWriter;
5
+
6
+ pub mod request;
7
+ pub mod server;
8
+ pub mod stream_writer;
9
+
10
+ pub static ITSI_MODULE: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Itsi").unwrap());
11
+ pub static ITSI_SERVER: Lazy<RClass> = Lazy::new(|ruby| {
12
+ ruby.get_inner(&ITSI_MODULE)
13
+ .define_class("Server", ruby.class_object())
14
+ .unwrap()
15
+ });
16
+ pub static ITSI_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
17
+ ruby.get_inner(&ITSI_MODULE)
18
+ .define_class("Request", ruby.class_object())
19
+ .unwrap()
20
+ });
21
+ pub static ITSI_STREAM_WRITER: Lazy<RClass> = Lazy::new(|ruby| {
22
+ ruby.get_inner(&ITSI_MODULE)
23
+ .define_class("StreamWriter", ruby.class_object())
24
+ .unwrap()
25
+ });
26
+
27
+ #[magnus::init]
28
+ fn init(ruby: &Ruby) -> Result<()> {
29
+ itsi_tracing::init();
30
+
31
+ let server = ruby.get_inner(&ITSI_SERVER);
32
+ server.define_singleton_method("new", function!(Server::new, -1))?;
33
+ server.define_method("start", method!(Server::start, 0))?;
34
+
35
+ let request = ruby.get_inner(&ITSI_REQUEST);
36
+ request.define_method("path", method!(ItsiRequest::path, 0))?;
37
+ request.define_method("script_name", method!(ItsiRequest::script_name, 0))?;
38
+ request.define_method("query_string", method!(ItsiRequest::query_string, 0))?;
39
+ request.define_method("method", method!(ItsiRequest::method, 0))?;
40
+ request.define_method("version", method!(ItsiRequest::version, 0))?;
41
+ request.define_method("rack_protocol", method!(ItsiRequest::rack_protocol, 0))?;
42
+ request.define_method("host", method!(ItsiRequest::host, 0))?;
43
+ request.define_method("headers", method!(ItsiRequest::headers, 0))?;
44
+ request.define_method("remote_addr", method!(ItsiRequest::remote_addr, 0))?;
45
+ request.define_method("port", method!(ItsiRequest::port, 0))?;
46
+ request.define_method("body", method!(ItsiRequest::body, 0))?;
47
+
48
+ let stream_writer = ruby.get_inner(&ITSI_STREAM_WRITER);
49
+ stream_writer.define_method("write", method!(StreamWriter::write, 1))?;
50
+
51
+ Ok(())
52
+ }
@@ -0,0 +1,143 @@
1
+ use std::{collections::HashMap, sync::Arc};
2
+
3
+ use crate::server::listener::{Listener, SockAddr};
4
+ use bytes::Bytes;
5
+ use http::request::Parts;
6
+ use http_body_util::BodyExt;
7
+ use hyper::{body::Incoming, Request};
8
+ use magnus::error::Result;
9
+
10
+ #[magnus::wrap(class = "Itsi::Request", free_immediately, size)]
11
+ #[derive(Debug)]
12
+ pub struct ItsiRequest {
13
+ pub path: String,
14
+ pub script_name: String,
15
+ pub query_string: String,
16
+ pub method: String,
17
+ pub version: String,
18
+ pub rack_protocol: Vec<String>,
19
+ pub host: String,
20
+ pub scheme: String,
21
+ pub headers: HashMap<String, String>,
22
+ pub remote_addr: String,
23
+ pub port: u16,
24
+ pub body: Bytes,
25
+ pub parts: Parts,
26
+ }
27
+
28
+ impl ItsiRequest {
29
+ pub(crate) async fn build_from(
30
+ request: Request<Incoming>,
31
+ sock_addr: SockAddr,
32
+ script_name: String,
33
+ listener: Arc<Listener>,
34
+ ) -> Self {
35
+ let (parts, body) = request.into_parts();
36
+ let method = parts.method.to_string();
37
+ let port = parts.uri.port_u16().unwrap_or(listener.port());
38
+ let query_string = parts.uri.query().unwrap_or("").to_string();
39
+ let rack_protocol = parts
40
+ .headers
41
+ .get("upgrade")
42
+ .or_else(|| parts.headers.get("protocol"))
43
+ .map(|value| {
44
+ value
45
+ .to_str()
46
+ .unwrap_or("")
47
+ .split(',')
48
+ .map(|s| s.trim().to_owned())
49
+ .collect::<Vec<String>>()
50
+ })
51
+ .unwrap_or_else(|| vec!["http".to_string()]);
52
+
53
+ let host = parts
54
+ .uri
55
+ .host()
56
+ .map(ToOwned::to_owned)
57
+ .unwrap_or_else(|| listener.host());
58
+
59
+ let scheme = parts
60
+ .uri
61
+ .scheme()
62
+ .map(|s| s.to_string())
63
+ .unwrap_or_else(|| listener.scheme());
64
+
65
+ let headers = parts
66
+ .headers
67
+ .iter()
68
+ .map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
69
+ .collect();
70
+
71
+ let path = parts
72
+ .uri
73
+ .path()
74
+ .strip_prefix(&script_name)
75
+ .unwrap_or(parts.uri.path())
76
+ .to_string();
77
+
78
+ let version = format!("{:?}", parts.version);
79
+ let body = body.collect().await.unwrap().to_bytes();
80
+
81
+ Self {
82
+ remote_addr: sock_addr.to_string(),
83
+ body,
84
+ parts,
85
+ script_name,
86
+ query_string,
87
+ method,
88
+ headers,
89
+ path,
90
+ version,
91
+ rack_protocol,
92
+ host,
93
+ scheme,
94
+ port,
95
+ }
96
+ }
97
+ }
98
+
99
+ impl ItsiRequest {
100
+ pub(crate) fn path(&self) -> Result<String> {
101
+ Ok(self.path.clone())
102
+ }
103
+
104
+ pub(crate) fn script_name(&self) -> Result<String> {
105
+ Ok(self.script_name.clone())
106
+ }
107
+
108
+ pub(crate) fn query_string(&self) -> Result<String> {
109
+ Ok(self.query_string.clone())
110
+ }
111
+
112
+ pub(crate) fn method(&self) -> Result<String> {
113
+ Ok(self.method.clone())
114
+ }
115
+
116
+ pub(crate) fn version(&self) -> Result<String> {
117
+ Ok(self.version.clone())
118
+ }
119
+
120
+ pub(crate) fn rack_protocol(&self) -> Result<Vec<String>> {
121
+ Ok(self.rack_protocol.clone())
122
+ }
123
+
124
+ pub(crate) fn host(&self) -> Result<String> {
125
+ Ok(self.host.clone())
126
+ }
127
+
128
+ pub(crate) fn headers(&self) -> Result<HashMap<String, String>> {
129
+ Ok(self.headers.clone())
130
+ }
131
+
132
+ pub(crate) fn remote_addr(&self) -> Result<String> {
133
+ Ok(self.remote_addr.clone())
134
+ }
135
+
136
+ pub(crate) fn port(&self) -> Result<u16> {
137
+ Ok(self.port)
138
+ }
139
+
140
+ pub(crate) fn body(&self) -> Result<Bytes> {
141
+ Ok(self.body.clone())
142
+ }
143
+ }
@@ -0,0 +1 @@
1
+ pub mod itsi_request;