castrum 0.7.0 → 0.9.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.
Files changed (176) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -59
  3. package/castrum.linux-x64-gnu.node +0 -0
  4. package/dist/index.d.ts +3161 -0
  5. package/dist/index.js +7306 -0
  6. package/docs/ARCHITECTURE.md +415 -0
  7. package/docs/BENCHMARKS.md +307 -0
  8. package/docs/ENVIRONMENT.md +79 -0
  9. package/docs/GETTING_STARTED.md +209 -0
  10. package/docs/INGRESS.md +745 -0
  11. package/docs/REPO_MAP.md +259 -0
  12. package/docs/adr/0001-two-wire-formats.md +39 -0
  13. package/docs/adr/0002-zero-dom-fast-schema.md +38 -0
  14. package/docs/adr/0003-bun-builtins-delegation.md +42 -0
  15. package/docs/bun-builtins-decision-matrix.md +108 -0
  16. package/index.ts +51 -8
  17. package/package.json +73 -20
  18. package/src/data/json-rows.ts +13 -13
  19. package/src/ingress/body.ts +149 -0
  20. package/src/ingress/constants.ts +220 -48
  21. package/src/ingress/context.ts +136 -0
  22. package/src/ingress/decode/baked-result.ts +121 -0
  23. package/src/ingress/decode/fast-result.ts +160 -0
  24. package/src/ingress/decode/packed-sections.ts +56 -0
  25. package/src/ingress/decode/result-base.ts +172 -0
  26. package/src/ingress/errors.ts +72 -0
  27. package/src/ingress/fast.ts +152 -1021
  28. package/src/ingress/handlers.ts +563 -1001
  29. package/src/ingress/headers/baked-templates.ts +102 -0
  30. package/src/ingress/headers/cors.ts +44 -0
  31. package/src/ingress/headers/fast-templates.ts +238 -0
  32. package/src/ingress/headers/hsts.ts +83 -0
  33. package/src/ingress/health.ts +67 -0
  34. package/src/ingress/index.ts +130 -405
  35. package/src/ingress/metrics.ts +132 -0
  36. package/src/ingress/options.ts +197 -0
  37. package/src/ingress/packing/gather-raw-headers.ts +75 -0
  38. package/src/ingress/packing/header-packing.ts +75 -0
  39. package/src/ingress/packing/input-packer.ts +150 -0
  40. package/src/ingress/packing/scratch.ts +50 -0
  41. package/src/ingress/packing/select-headers.ts +96 -0
  42. package/src/ingress/response/error-bodies.ts +75 -0
  43. package/src/ingress/response/terminal.ts +59 -0
  44. package/src/ingress/routes/common.ts +38 -0
  45. package/src/ingress/routes/delete.ts +14 -0
  46. package/src/ingress/routes/echo.ts +107 -0
  47. package/src/ingress/routes/fallback.ts +23 -0
  48. package/src/ingress/routes/head.ts +37 -0
  49. package/src/ingress/routes/index.ts +10 -0
  50. package/src/ingress/routes/json-write.ts +153 -0
  51. package/src/ingress/routes/options.ts +36 -0
  52. package/src/ingress/routes/read.ts +45 -0
  53. package/src/ingress/server-node.ts +376 -0
  54. package/src/ingress/server.ts +443 -0
  55. package/src/ingress/shared.ts +132 -0
  56. package/src/ingress/status.ts +97 -0
  57. package/src/ingress/types.ts +157 -0
  58. package/src/integration/batch.ts +58 -0
  59. package/src/integration/index.ts +29 -0
  60. package/src/integration/pipeline.ts +217 -0
  61. package/src/integration/streaming.ts +79 -0
  62. package/src/integration/websocket.ts +92 -0
  63. package/src/loader/batch.ts +133 -0
  64. package/src/loader/cost.ts +104 -0
  65. package/src/loader/index.ts +930 -0
  66. package/src/loader/ops.ts +657 -0
  67. package/src/native/ffi.ts +1541 -0
  68. package/src/native/index.ts +8 -207
  69. package/src/native/loader.ts +194 -0
  70. package/src/native/types.ts +598 -0
  71. package/src/rust-ffi/addon.ts +10 -0
  72. package/src/rust-ffi/batch.ts +431 -0
  73. package/src/rust-ffi/client.ts +88 -0
  74. package/src/rust-ffi/context.ts +164 -0
  75. package/src/rust-ffi/index.ts +40 -541
  76. package/src/rust-ffi/options.ts +113 -0
  77. package/src/rust-ffi/packed.ts +253 -0
  78. package/src/rust-ffi/proven.ts +42 -0
  79. package/src/rust-ffi/scalar/crypto.ts +265 -0
  80. package/src/rust-ffi/scalar/factories.ts +233 -0
  81. package/src/rust-ffi/scalar/hashing.ts +72 -0
  82. package/src/rust-ffi/scalar/http.ts +206 -0
  83. package/src/rust-ffi/scalar/index.ts +31 -0
  84. package/src/rust-ffi/scalar/interface.ts +450 -0
  85. package/src/rust-ffi/scalar/json.ts +45 -0
  86. package/src/rust-ffi/scalar/payload.ts +124 -0
  87. package/src/rust-ffi/text.ts +95 -0
  88. package/src/selection.json +194 -0
  89. package/src/selection.ts +77 -0
  90. package/src/shared/adaptive.ts +68 -0
  91. package/src/shared/bench-classify.ts +209 -0
  92. package/src/shared/buffer-pool.ts +209 -0
  93. package/src/shared/bytes.ts +35 -5
  94. package/src/shared/env.ts +20 -0
  95. package/src/shared/log.ts +74 -0
  96. package/src/shared/metrics.ts +247 -0
  97. package/src/shared/packed.ts +350 -154
  98. package/src/shared/proven.ts +596 -0
  99. package/src/shared/request-id.ts +67 -0
  100. package/src/shared/response.ts +104 -0
  101. package/src/shared/runtime.ts +34 -0
  102. package/src/shared/trace.ts +81 -0
  103. package/src/shared/uuid.ts +31 -0
  104. package/Cargo.toml +0 -73
  105. package/bench.ts +0 -3
  106. package/rust/batch.rs +0 -195
  107. package/rust/cookie_parser.rs +0 -70
  108. package/rust/cors.rs +0 -263
  109. package/rust/hashing.rs +0 -164
  110. package/rust/headers.rs +0 -234
  111. package/rust/hmac_sha256.rs +0 -113
  112. package/rust/http_parser.rs +0 -132
  113. package/rust/ingress.rs +0 -616
  114. package/rust/ingress_constants.rs +0 -89
  115. package/rust/ip_trust.rs +0 -185
  116. package/rust/json_ops.rs +0 -66
  117. package/rust/json_patch_ops.rs +0 -25
  118. package/rust/json_schema.rs +0 -151
  119. package/rust/json_ser.rs +0 -429
  120. package/rust/lib.rs +0 -48
  121. package/rust/method.rs +0 -141
  122. package/rust/mime_lookup.rs +0 -76
  123. package/rust/output.rs +0 -238
  124. package/rust/proxy.rs +0 -90
  125. package/rust/query_parser.rs +0 -141
  126. package/rust/random_token.rs +0 -52
  127. package/rust/rate_limit.rs +0 -203
  128. package/rust/terminal.rs +0 -95
  129. package/rust/unit_tests.rs +0 -843
  130. package/rust/url_codec.rs +0 -133
  131. package/rust/util.rs +0 -537
  132. package/rust/validation.rs +0 -107
  133. package/rust/websocket.rs +0 -23
  134. package/src/baseline/index.ts +0 -12
  135. package/src/baseline/tasks/cookie.ts +0 -22
  136. package/src/baseline/tasks/hashing.ts +0 -18
  137. package/src/baseline/tasks/hmac.ts +0 -38
  138. package/src/baseline/tasks/http.ts +0 -62
  139. package/src/baseline/tasks/json-patch.ts +0 -12
  140. package/src/baseline/tasks/json.ts +0 -50
  141. package/src/baseline/tasks/mime.ts +0 -5
  142. package/src/baseline/tasks/query.ts +0 -14
  143. package/src/baseline/tasks/token.ts +0 -15
  144. package/src/baseline/tasks/url.ts +0 -11
  145. package/src/baseline/tasks/validation.ts +0 -19
  146. package/src/baseline/tasks/websocket.ts +0 -14
  147. package/src/bench/assert.ts +0 -70
  148. package/src/bench/checks.ts +0 -227
  149. package/src/bench/checksum.ts +0 -27
  150. package/src/bench/comparisons.ts +0 -70
  151. package/src/bench/concurrent-worker.ts +0 -135
  152. package/src/bench/fixtures.ts +0 -233
  153. package/src/bench/index.ts +0 -2
  154. package/src/bench/measure.ts +0 -177
  155. package/src/bench/now.ts +0 -3
  156. package/src/bench/report.ts +0 -79
  157. package/src/bench/run.ts +0 -57
  158. package/src/bench/tasks/complex.ts +0 -232
  159. package/src/bench/tasks/concurrent.ts +0 -213
  160. package/src/bench/tasks/cookie.ts +0 -44
  161. package/src/bench/tasks/hashing.ts +0 -33
  162. package/src/bench/tasks/hmac.ts +0 -36
  163. package/src/bench/tasks/http.ts +0 -50
  164. package/src/bench/tasks/index.ts +0 -52
  165. package/src/bench/tasks/json-patch.ts +0 -21
  166. package/src/bench/tasks/json.ts +0 -33
  167. package/src/bench/tasks/mime.ts +0 -21
  168. package/src/bench/tasks/query.ts +0 -44
  169. package/src/bench/tasks/stress.ts +0 -142
  170. package/src/bench/tasks/token.ts +0 -20
  171. package/src/bench/tasks/url.ts +0 -34
  172. package/src/bench/tasks/validation.ts +0 -57
  173. package/src/bench/tasks/websocket.ts +0 -21
  174. package/src/bench/types.ts +0 -60
  175. package/src/ingress/packed-input.ts +0 -59
  176. package/src/shared/json.ts +0 -18
@@ -1,113 +0,0 @@
1
- use napi::bindgen_prelude::*;
2
- use napi_derive::napi;
3
- use aws_lc_rs::hmac;
4
- use crate::util::{hex_val, trim_ascii_whitespace};
5
-
6
- const HEX_LOWER: &[u8; 16] = b"0123456789abcdef";
7
-
8
-
9
-
10
- #[napi]
11
- pub fn hmac_sha256(key: Uint8Array, data: Buffer) -> Buffer {
12
- let key = hmac::Key::new(hmac::HMAC_SHA256, key.as_ref());
13
- let tag = hmac::sign(&key, data.as_ref());
14
-
15
- let mut out = [0u8; 64];
16
- hex_encode_32(tag.as_ref(), &mut out);
17
-
18
- Buffer::from(out.to_vec())
19
- }
20
-
21
- #[napi]
22
- pub fn hmac_sha256_verify(key: Uint8Array, data: Buffer, sig: Buffer) -> bool {
23
- let sig = trim_ascii_whitespace(sig.as_ref());
24
-
25
- if sig.len() != 64 {
26
- return false;
27
- }
28
-
29
- let mut sig_bytes = [0u8; 32];
30
-
31
- let mut i = 0;
32
- while i < 32 {
33
- let hi = match hex_val(sig[2 * i]) {
34
- Some(v) => v,
35
- None => return false,
36
- };
37
-
38
- let lo = match hex_val(sig[2 * i + 1]) {
39
- Some(v) => v,
40
- None => return false,
41
- };
42
-
43
- sig_bytes[i] = (hi << 4) | lo;
44
- i += 1;
45
- }
46
-
47
- let key = hmac::Key::new(hmac::HMAC_SHA256, key.as_ref());
48
- hmac::verify(&key, data.as_ref(), &sig_bytes).is_ok()
49
- }
50
-
51
- #[napi]
52
- pub struct HmacSigner {
53
- key: hmac::Key,
54
- }
55
-
56
- #[napi]
57
- impl HmacSigner {
58
- #[napi(constructor)]
59
- pub fn new(key: Uint8Array) -> Self {
60
- Self {
61
- key: hmac::Key::new(hmac::HMAC_SHA256, key.as_ref()),
62
- }
63
- }
64
-
65
- #[napi]
66
- pub fn sign(&self, data: Buffer) -> Buffer {
67
- let tag = hmac::sign(&self.key, data.as_ref());
68
-
69
- let mut out = [0u8; 64];
70
- hex_encode_32(tag.as_ref(), &mut out);
71
-
72
- Buffer::from(out.to_vec())
73
- }
74
-
75
- #[napi]
76
- pub fn verify(&self, data: Buffer, sig: Buffer) -> bool {
77
- let sig = trim_ascii_whitespace(sig.as_ref());
78
-
79
- if sig.len() != 64 {
80
- return false;
81
- }
82
-
83
- let mut sig_bytes = [0u8; 32];
84
-
85
- let mut i = 0;
86
-
87
- while i < 32 {
88
- let hi = match hex_val(sig[2 * i]) {
89
- Some(v) => v,
90
- None => return false,
91
- };
92
-
93
- let lo = match hex_val(sig[2 * i + 1]) {
94
- Some(v) => v,
95
- None => return false,
96
- };
97
-
98
- sig_bytes[i] = (hi << 4) | lo;
99
- i += 1;
100
- }
101
-
102
- hmac::verify(&self.key, data.as_ref(), &sig_bytes).is_ok()
103
- }
104
- }
105
-
106
- fn hex_encode_32(bytes: &[u8], out: &mut [u8; 64]) {
107
- debug_assert_eq!(bytes.len(), 32);
108
-
109
- for (i, b) in bytes.iter().enumerate() {
110
- out[2 * i] = HEX_LOWER[(b >> 4) as usize];
111
- out[2 * i + 1] = HEX_LOWER[(b & 0x0f) as usize];
112
- }
113
- }
@@ -1,132 +0,0 @@
1
- // rust/http_parser.rs
2
- use crate::util::{write_bytes, write_u32_le, VecWriter};
3
- use napi::bindgen_prelude::*;
4
- use napi_derive::napi;
5
-
6
- pub fn http_parse_request_packed_into_slice(input: &[u8], out: &mut [u8]) -> Result<usize> {
7
- let mut headers = [httparse::EMPTY_HEADER; 64];
8
- let mut req = httparse::Request::new(&mut headers);
9
-
10
- match req.parse(input) {
11
- Ok(httparse::Status::Complete(_)) => {}
12
- Ok(_) => return Err(Error::new(Status::InvalidArg, "incomplete HTTP request")),
13
- Err(e) => return Err(Error::new(Status::InvalidArg, e.to_string())),
14
- }
15
-
16
- let method = req
17
- .method
18
- .ok_or_else(|| Error::new(Status::InvalidArg, "missing HTTP method"))?
19
- .as_bytes();
20
-
21
- let path = req
22
- .path
23
- .ok_or_else(|| Error::new(Status::InvalidArg, "missing HTTP path"))?
24
- .as_bytes();
25
-
26
- let version: &[u8] = match req.version {
27
- Some(0) => b"HTTP/1.0",
28
- Some(1) => b"HTTP/1.1",
29
- _ => b"HTTP/1.1",
30
- };
31
-
32
- let mut pos = 0usize;
33
-
34
- write_u32_le(out, &mut pos, method.len() as u32)?;
35
- write_bytes(out, &mut pos, method)?;
36
-
37
- write_u32_le(out, &mut pos, path.len() as u32)?;
38
- write_bytes(out, &mut pos, path)?;
39
-
40
- write_u32_le(out, &mut pos, version.len() as u32)?;
41
- write_bytes(out, &mut pos, version)?;
42
-
43
- write_u32_le(out, &mut pos, req.headers.len() as u32)?;
44
-
45
- for header in req.headers.iter() {
46
- let name = header.name.as_bytes();
47
- let value = header.value;
48
-
49
- write_u32_le(out, &mut pos, name.len() as u32)?;
50
- crate::util::write_bytes_lowercase(out, &mut pos, name)?;
51
-
52
- write_u32_le(out, &mut pos, value.len() as u32)?;
53
- crate::util::write_bytes(out, &mut pos, value)?;
54
- }
55
-
56
- Ok(pos)
57
- }
58
-
59
- /// Allocating, zero-copy-input, non-zeroing-output parser.
60
- pub fn http_parse_request_packed_vec(input: &[u8]) -> Result<Vec<u8>> {
61
- let mut headers = [httparse::EMPTY_HEADER; 64];
62
- let mut req = httparse::Request::new(&mut headers);
63
-
64
- match req.parse(input) {
65
- Ok(httparse::Status::Complete(_)) => {}
66
- Ok(_) => return Err(Error::new(Status::InvalidArg, "incomplete HTTP request")),
67
- Err(e) => return Err(Error::new(Status::InvalidArg, e.to_string())),
68
- }
69
-
70
- let method = req
71
- .method
72
- .ok_or_else(|| Error::new(Status::InvalidArg, "missing HTTP method"))?
73
- .as_bytes();
74
-
75
- let path = req
76
- .path
77
- .ok_or_else(|| Error::new(Status::InvalidArg, "missing HTTP path"))?
78
- .as_bytes();
79
-
80
- let version: &[u8] = match req.version {
81
- Some(0) => b"HTTP/1.0",
82
- Some(1) => b"HTTP/1.1",
83
- _ => b"HTTP/1.1",
84
- };
85
-
86
- // Max 64 headers.
87
- // Metadata overhead:
88
- // 4 bytes method len
89
- // 4 bytes path len
90
- // 4 bytes version len
91
- // 4 bytes header count
92
- // 8 bytes per header name/value length prefix
93
- //
94
- // 16 + 64 * 8 = 528
95
- let mut w = VecWriter::with_capacity(input.len().saturating_add(528));
96
-
97
- w.write_u32(method.len() as u32);
98
- w.write_bytes(method);
99
-
100
- w.write_u32(path.len() as u32);
101
- w.write_bytes(path);
102
-
103
- w.write_u32(version.len() as u32);
104
- w.write_bytes(version);
105
-
106
- w.write_u32(req.headers.len() as u32);
107
-
108
- for header in req.headers.iter() {
109
- let name = header.name.as_bytes();
110
- let value = header.value;
111
-
112
- w.write_u32(name.len() as u32);
113
- w.write_bytes_ascii_lowercase(name);
114
-
115
- w.write_u32(value.len() as u32);
116
- w.write_bytes(value);
117
- }
118
-
119
- Ok(w.into_bytes())
120
- }
121
-
122
- #[napi]
123
- pub fn http_parse_request_packed(input: Uint8Array) -> Result<Buffer> {
124
- Ok(Buffer::from(http_parse_request_packed_vec(
125
- input.as_ref(),
126
- )?))
127
- }
128
-
129
- #[napi]
130
- pub fn http_parse_request_packed_into(input: Uint8Array, mut output: Uint8Array) -> Result<u32> {
131
- crate::util::run_packed_into(&input, &mut output, http_parse_request_packed_into_slice)
132
- }