spikard 0.10.2 → 0.11.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/README.md +4 -2
- data/ext/spikard_rb/Cargo.lock +253 -66
- data/ext/spikard_rb/Cargo.toml +1 -1
- data/ext/spikard_rb/extconf.rb +2 -4
- data/lib/spikard/version.rb +1 -1
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +3 -3
- data/vendor/crates/spikard-core/Cargo.toml +14 -5
- data/vendor/crates/spikard-http/Cargo.toml +4 -4
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +1 -1
- data/vendor/crates/spikard-http/src/server/grpc_routing.rs +227 -0
- data/vendor/crates/spikard-http/src/server/mod.rs +9 -8
- data/vendor/crates/spikard-http/src/testing.rs +40 -0
- data/vendor/crates/spikard-rb/Cargo.toml +2 -2
- data/vendor/crates/spikard-rb-macros/Cargo.toml +1 -1
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ddca560615174394e71fc0066ee7749daa3fcc5e91c8387c3abcc6e8685c7f82
|
|
4
|
+
data.tar.gz: 273523e0e3aa0068e95b660744bf4278cfc6b157d61a9d935ac6953da7431fb9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b6005c4cc1e6f32e2e5b5157874b76b0d797931a792c12bf07324f04a83ba17210fd56ff8a495534056a7ac85bd07bcbc6af487c071c41ff0f6aa76dbfe6e67
|
|
7
|
+
data.tar.gz: 342a8ed2c1d180180701aedb5cc01467eadb3da8317310678b4b9857a002ba09231b5b1c5d6a85fc0f07c1e432a6cb45a97a92fe30c583a5abe406b625494dd2
|
data/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/@spikard/node)
|
|
7
7
|
[](https://rubygems.org/gems/spikard)
|
|
8
8
|
[](https://packagist.org/packages/spikard/spikard)
|
|
9
|
+
[](https://hex.pm/packages/spikard)
|
|
9
10
|
[](../../LICENSE)
|
|
10
11
|
|
|
11
12
|
Ruby bindings for Spikard: a Rust-centric web framework with type-safe code generation from OpenAPI, GraphQL, AsyncAPI, and OpenRPC specifications. Leverage Sinatra-style routing with zero-copy FFI performance.
|
|
@@ -246,7 +247,7 @@ Spikard is **1.4x faster** than Roda with significantly lower tail latency.
|
|
|
246
247
|
## Learn More
|
|
247
248
|
|
|
248
249
|
**Examples & Code Generation:**
|
|
249
|
-
- [Runnable Examples](../../examples/) - Ruby, Python, TypeScript, PHP, and
|
|
250
|
+
- [Runnable Examples](../../examples/) - Ruby, Python, TypeScript, PHP, Elixir, and Rust
|
|
250
251
|
- [Code Generation Guide](../../examples/README.md) - Generate from OpenAPI, GraphQL, AsyncAPI, OpenRPC
|
|
251
252
|
|
|
252
253
|
**Documentation:**
|
|
@@ -256,8 +257,9 @@ Spikard is **1.4x faster** than Roda with significantly lower tail latency.
|
|
|
256
257
|
|
|
257
258
|
**Other Languages:**
|
|
258
259
|
- [Python (PyPI)](https://pypi.org/project/spikard/)
|
|
259
|
-
- [TypeScript (npm)](https://www.npmjs.com/package/
|
|
260
|
+
- [TypeScript (npm)](https://www.npmjs.com/package/@spikard/node)
|
|
260
261
|
- [PHP (Packagist)](https://packagist.org/packages/spikard/spikard)
|
|
262
|
+
- [Elixir (Hex.pm)](https://hex.pm/packages/spikard)
|
|
261
263
|
- [Rust (Crates.io)](https://crates.io/crates/spikard)
|
|
262
264
|
|
|
263
265
|
## License
|
data/ext/spikard_rb/Cargo.lock
CHANGED
|
@@ -63,9 +63,9 @@ dependencies = [
|
|
|
63
63
|
|
|
64
64
|
[[package]]
|
|
65
65
|
name = "anyhow"
|
|
66
|
-
version = "1.0.
|
|
66
|
+
version = "1.0.101"
|
|
67
67
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
-
checksum = "
|
|
68
|
+
checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea"
|
|
69
69
|
|
|
70
70
|
[[package]]
|
|
71
71
|
name = "arbitrary"
|
|
@@ -78,9 +78,9 @@ dependencies = [
|
|
|
78
78
|
|
|
79
79
|
[[package]]
|
|
80
80
|
name = "async-compression"
|
|
81
|
-
version = "0.4.
|
|
81
|
+
version = "0.4.39"
|
|
82
82
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
83
|
-
checksum = "
|
|
83
|
+
checksum = "68650b7df54f0293fd061972a0fb05aaf4fc0879d3b3d21a638a182c5c543b9f"
|
|
84
84
|
dependencies = [
|
|
85
85
|
"compression-codecs",
|
|
86
86
|
"compression-core",
|
|
@@ -277,9 +277,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
|
|
277
277
|
|
|
278
278
|
[[package]]
|
|
279
279
|
name = "bitflags"
|
|
280
|
-
version = "2.
|
|
280
|
+
version = "2.11.0"
|
|
281
281
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
282
|
-
checksum = "
|
|
282
|
+
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
|
283
283
|
|
|
284
284
|
[[package]]
|
|
285
285
|
name = "block-buffer"
|
|
@@ -331,9 +331,9 @@ checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
|
|
|
331
331
|
|
|
332
332
|
[[package]]
|
|
333
333
|
name = "bytes"
|
|
334
|
-
version = "1.11.
|
|
334
|
+
version = "1.11.1"
|
|
335
335
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
336
|
-
checksum = "
|
|
336
|
+
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
|
337
337
|
|
|
338
338
|
[[package]]
|
|
339
339
|
name = "bytesize"
|
|
@@ -343,9 +343,9 @@ checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3"
|
|
|
343
343
|
|
|
344
344
|
[[package]]
|
|
345
345
|
name = "cc"
|
|
346
|
-
version = "1.2.
|
|
346
|
+
version = "1.2.56"
|
|
347
347
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
348
|
-
checksum = "
|
|
348
|
+
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
|
349
349
|
dependencies = [
|
|
350
350
|
"find-msvc-tools",
|
|
351
351
|
"shlex",
|
|
@@ -536,9 +536,9 @@ dependencies = [
|
|
|
536
536
|
|
|
537
537
|
[[package]]
|
|
538
538
|
name = "deranged"
|
|
539
|
-
version = "0.5.
|
|
539
|
+
version = "0.5.6"
|
|
540
540
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
541
|
-
checksum = "
|
|
541
|
+
checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4"
|
|
542
542
|
dependencies = [
|
|
543
543
|
"powerfmt",
|
|
544
544
|
]
|
|
@@ -792,6 +792,12 @@ version = "1.0.7"
|
|
|
792
792
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
793
793
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
794
794
|
|
|
795
|
+
[[package]]
|
|
796
|
+
name = "foldhash"
|
|
797
|
+
version = "0.1.5"
|
|
798
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
799
|
+
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|
800
|
+
|
|
795
801
|
[[package]]
|
|
796
802
|
name = "foldhash"
|
|
797
803
|
version = "0.2.0"
|
|
@@ -958,6 +964,19 @@ dependencies = [
|
|
|
958
964
|
"wasm-bindgen",
|
|
959
965
|
]
|
|
960
966
|
|
|
967
|
+
[[package]]
|
|
968
|
+
name = "getrandom"
|
|
969
|
+
version = "0.4.1"
|
|
970
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
971
|
+
checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
|
|
972
|
+
dependencies = [
|
|
973
|
+
"cfg-if",
|
|
974
|
+
"libc",
|
|
975
|
+
"r-efi",
|
|
976
|
+
"wasip2",
|
|
977
|
+
"wasip3",
|
|
978
|
+
]
|
|
979
|
+
|
|
961
980
|
[[package]]
|
|
962
981
|
name = "glob"
|
|
963
982
|
version = "0.3.3"
|
|
@@ -1033,6 +1052,15 @@ version = "0.14.5"
|
|
|
1033
1052
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1034
1053
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
1035
1054
|
|
|
1055
|
+
[[package]]
|
|
1056
|
+
name = "hashbrown"
|
|
1057
|
+
version = "0.15.5"
|
|
1058
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1059
|
+
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|
1060
|
+
dependencies = [
|
|
1061
|
+
"foldhash 0.1.5",
|
|
1062
|
+
]
|
|
1063
|
+
|
|
1036
1064
|
[[package]]
|
|
1037
1065
|
name = "hashbrown"
|
|
1038
1066
|
version = "0.16.1"
|
|
@@ -1041,9 +1069,15 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
|
|
1041
1069
|
dependencies = [
|
|
1042
1070
|
"allocator-api2",
|
|
1043
1071
|
"equivalent",
|
|
1044
|
-
"foldhash",
|
|
1072
|
+
"foldhash 0.2.0",
|
|
1045
1073
|
]
|
|
1046
1074
|
|
|
1075
|
+
[[package]]
|
|
1076
|
+
name = "heck"
|
|
1077
|
+
version = "0.5.0"
|
|
1078
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1079
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
1080
|
+
|
|
1047
1081
|
[[package]]
|
|
1048
1082
|
name = "hkdf"
|
|
1049
1083
|
version = "0.12.4"
|
|
@@ -1151,13 +1185,12 @@ dependencies = [
|
|
|
1151
1185
|
|
|
1152
1186
|
[[package]]
|
|
1153
1187
|
name = "hyper-util"
|
|
1154
|
-
version = "0.1.
|
|
1188
|
+
version = "0.1.20"
|
|
1155
1189
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1156
|
-
checksum = "
|
|
1190
|
+
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
|
|
1157
1191
|
dependencies = [
|
|
1158
1192
|
"bytes",
|
|
1159
1193
|
"futures-channel",
|
|
1160
|
-
"futures-core",
|
|
1161
1194
|
"futures-util",
|
|
1162
1195
|
"http",
|
|
1163
1196
|
"http-body",
|
|
@@ -1275,6 +1308,12 @@ dependencies = [
|
|
|
1275
1308
|
"zerovec",
|
|
1276
1309
|
]
|
|
1277
1310
|
|
|
1311
|
+
[[package]]
|
|
1312
|
+
name = "id-arena"
|
|
1313
|
+
version = "2.3.0"
|
|
1314
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1315
|
+
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|
1316
|
+
|
|
1278
1317
|
[[package]]
|
|
1279
1318
|
name = "idna"
|
|
1280
1319
|
version = "1.1.0"
|
|
@@ -1343,9 +1382,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
|
|
1343
1382
|
|
|
1344
1383
|
[[package]]
|
|
1345
1384
|
name = "jiff"
|
|
1346
|
-
version = "0.2.
|
|
1385
|
+
version = "0.2.20"
|
|
1347
1386
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1348
|
-
checksum = "
|
|
1387
|
+
checksum = "c867c356cc096b33f4981825ab281ecba3db0acefe60329f044c1789d94c6543"
|
|
1349
1388
|
dependencies = [
|
|
1350
1389
|
"jiff-static",
|
|
1351
1390
|
"jiff-tzdb-platform",
|
|
@@ -1358,9 +1397,9 @@ dependencies = [
|
|
|
1358
1397
|
|
|
1359
1398
|
[[package]]
|
|
1360
1399
|
name = "jiff-static"
|
|
1361
|
-
version = "0.2.
|
|
1400
|
+
version = "0.2.20"
|
|
1362
1401
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1363
|
-
checksum = "
|
|
1402
|
+
checksum = "f7946b4325269738f270bb55b3c19ab5c5040525f83fd625259422a9d25d9be5"
|
|
1364
1403
|
dependencies = [
|
|
1365
1404
|
"proc-macro2",
|
|
1366
1405
|
"quote",
|
|
@@ -1394,9 +1433,9 @@ dependencies = [
|
|
|
1394
1433
|
|
|
1395
1434
|
[[package]]
|
|
1396
1435
|
name = "jsonschema"
|
|
1397
|
-
version = "0.
|
|
1436
|
+
version = "0.41.0"
|
|
1398
1437
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1399
|
-
checksum = "
|
|
1438
|
+
checksum = "9320368abda84a3aad44953d61e70515681fe43ae94529dff5567e0215b88438"
|
|
1400
1439
|
dependencies = [
|
|
1401
1440
|
"ahash",
|
|
1402
1441
|
"bytecount",
|
|
@@ -1457,11 +1496,17 @@ version = "1.3.0"
|
|
|
1457
1496
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1458
1497
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
1459
1498
|
|
|
1499
|
+
[[package]]
|
|
1500
|
+
name = "leb128fmt"
|
|
1501
|
+
version = "0.1.0"
|
|
1502
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1503
|
+
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
1504
|
+
|
|
1460
1505
|
[[package]]
|
|
1461
1506
|
name = "libc"
|
|
1462
|
-
version = "0.2.
|
|
1507
|
+
version = "0.2.182"
|
|
1463
1508
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1464
|
-
checksum = "
|
|
1509
|
+
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
|
1465
1510
|
|
|
1466
1511
|
[[package]]
|
|
1467
1512
|
name = "libloading"
|
|
@@ -1558,9 +1603,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
|
|
1558
1603
|
|
|
1559
1604
|
[[package]]
|
|
1560
1605
|
name = "memchr"
|
|
1561
|
-
version = "2.
|
|
1606
|
+
version = "2.8.0"
|
|
1562
1607
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1563
|
-
checksum = "
|
|
1608
|
+
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
1564
1609
|
|
|
1565
1610
|
[[package]]
|
|
1566
1611
|
name = "mime"
|
|
@@ -1947,6 +1992,16 @@ dependencies = [
|
|
|
1947
1992
|
"yansi",
|
|
1948
1993
|
]
|
|
1949
1994
|
|
|
1995
|
+
[[package]]
|
|
1996
|
+
name = "prettyplease"
|
|
1997
|
+
version = "0.2.37"
|
|
1998
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1999
|
+
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
|
2000
|
+
dependencies = [
|
|
2001
|
+
"proc-macro2",
|
|
2002
|
+
"syn",
|
|
2003
|
+
]
|
|
2004
|
+
|
|
1950
2005
|
[[package]]
|
|
1951
2006
|
name = "primeorder"
|
|
1952
2007
|
version = "0.13.6"
|
|
@@ -2156,9 +2211,9 @@ dependencies = [
|
|
|
2156
2211
|
|
|
2157
2212
|
[[package]]
|
|
2158
2213
|
name = "referencing"
|
|
2159
|
-
version = "0.
|
|
2214
|
+
version = "0.41.0"
|
|
2160
2215
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2161
|
-
checksum = "
|
|
2216
|
+
checksum = "d5773259506800a8c6ef38df3674b061c62c5941162507891ff8b580e93d954e"
|
|
2162
2217
|
dependencies = [
|
|
2163
2218
|
"ahash",
|
|
2164
2219
|
"fluent-uri",
|
|
@@ -2171,9 +2226,9 @@ dependencies = [
|
|
|
2171
2226
|
|
|
2172
2227
|
[[package]]
|
|
2173
2228
|
name = "regex"
|
|
2174
|
-
version = "1.12.
|
|
2229
|
+
version = "1.12.3"
|
|
2175
2230
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2176
|
-
checksum = "
|
|
2231
|
+
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
|
2177
2232
|
dependencies = [
|
|
2178
2233
|
"aho-corasick",
|
|
2179
2234
|
"memchr",
|
|
@@ -2183,9 +2238,9 @@ dependencies = [
|
|
|
2183
2238
|
|
|
2184
2239
|
[[package]]
|
|
2185
2240
|
name = "regex-automata"
|
|
2186
|
-
version = "0.4.
|
|
2241
|
+
version = "0.4.14"
|
|
2187
2242
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2188
|
-
checksum = "
|
|
2243
|
+
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
|
2189
2244
|
dependencies = [
|
|
2190
2245
|
"aho-corasick",
|
|
2191
2246
|
"memchr",
|
|
@@ -2194,9 +2249,9 @@ dependencies = [
|
|
|
2194
2249
|
|
|
2195
2250
|
[[package]]
|
|
2196
2251
|
name = "regex-syntax"
|
|
2197
|
-
version = "0.8.
|
|
2252
|
+
version = "0.8.9"
|
|
2198
2253
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2199
|
-
checksum = "
|
|
2254
|
+
checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
|
|
2200
2255
|
|
|
2201
2256
|
[[package]]
|
|
2202
2257
|
name = "reserve-port"
|
|
@@ -2315,9 +2370,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
|
2315
2370
|
|
|
2316
2371
|
[[package]]
|
|
2317
2372
|
name = "ryu"
|
|
2318
|
-
version = "1.0.
|
|
2373
|
+
version = "1.0.23"
|
|
2319
2374
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2320
|
-
checksum = "
|
|
2375
|
+
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
|
2321
2376
|
|
|
2322
2377
|
[[package]]
|
|
2323
2378
|
name = "same-file"
|
|
@@ -2416,13 +2471,14 @@ dependencies = [
|
|
|
2416
2471
|
|
|
2417
2472
|
[[package]]
|
|
2418
2473
|
name = "serde_qs"
|
|
2419
|
-
version = "0.
|
|
2474
|
+
version = "1.0.0"
|
|
2420
2475
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2421
|
-
checksum = "
|
|
2476
|
+
checksum = "ac22439301a0b6f45a037681518e3169e8db1db76080e2e9600a08d1027df037"
|
|
2422
2477
|
dependencies = [
|
|
2478
|
+
"itoa",
|
|
2423
2479
|
"percent-encoding",
|
|
2480
|
+
"ryu",
|
|
2424
2481
|
"serde",
|
|
2425
|
-
"thiserror 2.0.18",
|
|
2426
2482
|
]
|
|
2427
2483
|
|
|
2428
2484
|
[[package]]
|
|
@@ -2528,9 +2584,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
|
|
2528
2584
|
|
|
2529
2585
|
[[package]]
|
|
2530
2586
|
name = "simple_asn1"
|
|
2531
|
-
version = "0.6.
|
|
2587
|
+
version = "0.6.4"
|
|
2532
2588
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2533
|
-
checksum = "
|
|
2589
|
+
checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d"
|
|
2534
2590
|
dependencies = [
|
|
2535
2591
|
"num-bigint",
|
|
2536
2592
|
"num-traits",
|
|
@@ -2562,7 +2618,7 @@ dependencies = [
|
|
|
2562
2618
|
|
|
2563
2619
|
[[package]]
|
|
2564
2620
|
name = "spikard-bindings-shared"
|
|
2565
|
-
version = "0.10.
|
|
2621
|
+
version = "0.10.2"
|
|
2566
2622
|
dependencies = [
|
|
2567
2623
|
"axum",
|
|
2568
2624
|
"bytes",
|
|
@@ -2581,7 +2637,7 @@ dependencies = [
|
|
|
2581
2637
|
|
|
2582
2638
|
[[package]]
|
|
2583
2639
|
name = "spikard-core"
|
|
2584
|
-
version = "0.10.
|
|
2640
|
+
version = "0.10.2"
|
|
2585
2641
|
dependencies = [
|
|
2586
2642
|
"anyhow",
|
|
2587
2643
|
"base64",
|
|
@@ -2605,7 +2661,7 @@ dependencies = [
|
|
|
2605
2661
|
|
|
2606
2662
|
[[package]]
|
|
2607
2663
|
name = "spikard-http"
|
|
2608
|
-
version = "0.10.
|
|
2664
|
+
version = "0.10.2"
|
|
2609
2665
|
dependencies = [
|
|
2610
2666
|
"ahash",
|
|
2611
2667
|
"anyhow",
|
|
@@ -2654,7 +2710,7 @@ dependencies = [
|
|
|
2654
2710
|
|
|
2655
2711
|
[[package]]
|
|
2656
2712
|
name = "spikard-rb"
|
|
2657
|
-
version = "0.10.
|
|
2713
|
+
version = "0.10.2"
|
|
2658
2714
|
dependencies = [
|
|
2659
2715
|
"async-stream",
|
|
2660
2716
|
"axum",
|
|
@@ -2686,7 +2742,7 @@ dependencies = [
|
|
|
2686
2742
|
|
|
2687
2743
|
[[package]]
|
|
2688
2744
|
name = "spikard-rb-ext"
|
|
2689
|
-
version = "0.10.
|
|
2745
|
+
version = "0.10.2"
|
|
2690
2746
|
dependencies = [
|
|
2691
2747
|
"magnus",
|
|
2692
2748
|
"spikard-rb",
|
|
@@ -2694,7 +2750,7 @@ dependencies = [
|
|
|
2694
2750
|
|
|
2695
2751
|
[[package]]
|
|
2696
2752
|
name = "spikard-rb-macros"
|
|
2697
|
-
version = "0.10.
|
|
2753
|
+
version = "0.10.2"
|
|
2698
2754
|
dependencies = [
|
|
2699
2755
|
"proc-macro2",
|
|
2700
2756
|
"quote",
|
|
@@ -2740,9 +2796,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
|
2740
2796
|
|
|
2741
2797
|
[[package]]
|
|
2742
2798
|
name = "syn"
|
|
2743
|
-
version = "2.0.
|
|
2799
|
+
version = "2.0.115"
|
|
2744
2800
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2745
|
-
checksum = "
|
|
2801
|
+
checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12"
|
|
2746
2802
|
dependencies = [
|
|
2747
2803
|
"proc-macro2",
|
|
2748
2804
|
"quote",
|
|
@@ -2817,9 +2873,9 @@ dependencies = [
|
|
|
2817
2873
|
|
|
2818
2874
|
[[package]]
|
|
2819
2875
|
name = "time"
|
|
2820
|
-
version = "0.3.
|
|
2876
|
+
version = "0.3.47"
|
|
2821
2877
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2822
|
-
checksum = "
|
|
2878
|
+
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
|
|
2823
2879
|
dependencies = [
|
|
2824
2880
|
"deranged",
|
|
2825
2881
|
"itoa",
|
|
@@ -2838,9 +2894,9 @@ checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
|
|
2838
2894
|
|
|
2839
2895
|
[[package]]
|
|
2840
2896
|
name = "time-macros"
|
|
2841
|
-
version = "0.2.
|
|
2897
|
+
version = "0.2.27"
|
|
2842
2898
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2843
|
-
checksum = "
|
|
2899
|
+
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
|
|
2844
2900
|
dependencies = [
|
|
2845
2901
|
"num-conv",
|
|
2846
2902
|
"time-core",
|
|
@@ -2922,9 +2978,9 @@ dependencies = [
|
|
|
2922
2978
|
|
|
2923
2979
|
[[package]]
|
|
2924
2980
|
name = "tonic"
|
|
2925
|
-
version = "0.14.
|
|
2981
|
+
version = "0.14.4"
|
|
2926
2982
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2927
|
-
checksum = "
|
|
2983
|
+
checksum = "7f32a6f80051a4111560201420c7885d0082ba9efe2ab61875c587bb6b18b9a0"
|
|
2928
2984
|
dependencies = [
|
|
2929
2985
|
"async-trait",
|
|
2930
2986
|
"axum",
|
|
@@ -3161,9 +3217,15 @@ checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f"
|
|
|
3161
3217
|
|
|
3162
3218
|
[[package]]
|
|
3163
3219
|
name = "unicode-ident"
|
|
3164
|
-
version = "1.0.
|
|
3220
|
+
version = "1.0.23"
|
|
3221
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3222
|
+
checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e"
|
|
3223
|
+
|
|
3224
|
+
[[package]]
|
|
3225
|
+
name = "unicode-xid"
|
|
3226
|
+
version = "0.2.6"
|
|
3165
3227
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3166
|
-
checksum = "
|
|
3228
|
+
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
3167
3229
|
|
|
3168
3230
|
[[package]]
|
|
3169
3231
|
name = "url"
|
|
@@ -3259,11 +3321,11 @@ checksum = "e2eebbbfe4093922c2b6734d7c679ebfebd704a0d7e56dfcb0d05818ce28977d"
|
|
|
3259
3321
|
|
|
3260
3322
|
[[package]]
|
|
3261
3323
|
name = "uuid"
|
|
3262
|
-
version = "1.
|
|
3324
|
+
version = "1.21.0"
|
|
3263
3325
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3264
|
-
checksum = "
|
|
3326
|
+
checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb"
|
|
3265
3327
|
dependencies = [
|
|
3266
|
-
"getrandom 0.
|
|
3328
|
+
"getrandom 0.4.1",
|
|
3267
3329
|
"js-sys",
|
|
3268
3330
|
"serde_core",
|
|
3269
3331
|
"wasm-bindgen",
|
|
@@ -3343,6 +3405,15 @@ dependencies = [
|
|
|
3343
3405
|
"wit-bindgen",
|
|
3344
3406
|
]
|
|
3345
3407
|
|
|
3408
|
+
[[package]]
|
|
3409
|
+
name = "wasip3"
|
|
3410
|
+
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
3411
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3412
|
+
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
|
3413
|
+
dependencies = [
|
|
3414
|
+
"wit-bindgen",
|
|
3415
|
+
]
|
|
3416
|
+
|
|
3346
3417
|
[[package]]
|
|
3347
3418
|
name = "wasm-bindgen"
|
|
3348
3419
|
version = "0.2.108"
|
|
@@ -3388,6 +3459,40 @@ dependencies = [
|
|
|
3388
3459
|
"unicode-ident",
|
|
3389
3460
|
]
|
|
3390
3461
|
|
|
3462
|
+
[[package]]
|
|
3463
|
+
name = "wasm-encoder"
|
|
3464
|
+
version = "0.244.0"
|
|
3465
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3466
|
+
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
|
3467
|
+
dependencies = [
|
|
3468
|
+
"leb128fmt",
|
|
3469
|
+
"wasmparser",
|
|
3470
|
+
]
|
|
3471
|
+
|
|
3472
|
+
[[package]]
|
|
3473
|
+
name = "wasm-metadata"
|
|
3474
|
+
version = "0.244.0"
|
|
3475
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3476
|
+
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
|
3477
|
+
dependencies = [
|
|
3478
|
+
"anyhow",
|
|
3479
|
+
"indexmap",
|
|
3480
|
+
"wasm-encoder",
|
|
3481
|
+
"wasmparser",
|
|
3482
|
+
]
|
|
3483
|
+
|
|
3484
|
+
[[package]]
|
|
3485
|
+
name = "wasmparser"
|
|
3486
|
+
version = "0.244.0"
|
|
3487
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3488
|
+
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|
3489
|
+
dependencies = [
|
|
3490
|
+
"bitflags",
|
|
3491
|
+
"hashbrown 0.15.5",
|
|
3492
|
+
"indexmap",
|
|
3493
|
+
"semver",
|
|
3494
|
+
]
|
|
3495
|
+
|
|
3391
3496
|
[[package]]
|
|
3392
3497
|
name = "web-sys"
|
|
3393
3498
|
version = "0.3.85"
|
|
@@ -3586,6 +3691,88 @@ name = "wit-bindgen"
|
|
|
3586
3691
|
version = "0.51.0"
|
|
3587
3692
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3588
3693
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
3694
|
+
dependencies = [
|
|
3695
|
+
"wit-bindgen-rust-macro",
|
|
3696
|
+
]
|
|
3697
|
+
|
|
3698
|
+
[[package]]
|
|
3699
|
+
name = "wit-bindgen-core"
|
|
3700
|
+
version = "0.51.0"
|
|
3701
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3702
|
+
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
|
3703
|
+
dependencies = [
|
|
3704
|
+
"anyhow",
|
|
3705
|
+
"heck",
|
|
3706
|
+
"wit-parser",
|
|
3707
|
+
]
|
|
3708
|
+
|
|
3709
|
+
[[package]]
|
|
3710
|
+
name = "wit-bindgen-rust"
|
|
3711
|
+
version = "0.51.0"
|
|
3712
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3713
|
+
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|
3714
|
+
dependencies = [
|
|
3715
|
+
"anyhow",
|
|
3716
|
+
"heck",
|
|
3717
|
+
"indexmap",
|
|
3718
|
+
"prettyplease",
|
|
3719
|
+
"syn",
|
|
3720
|
+
"wasm-metadata",
|
|
3721
|
+
"wit-bindgen-core",
|
|
3722
|
+
"wit-component",
|
|
3723
|
+
]
|
|
3724
|
+
|
|
3725
|
+
[[package]]
|
|
3726
|
+
name = "wit-bindgen-rust-macro"
|
|
3727
|
+
version = "0.51.0"
|
|
3728
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3729
|
+
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
|
3730
|
+
dependencies = [
|
|
3731
|
+
"anyhow",
|
|
3732
|
+
"prettyplease",
|
|
3733
|
+
"proc-macro2",
|
|
3734
|
+
"quote",
|
|
3735
|
+
"syn",
|
|
3736
|
+
"wit-bindgen-core",
|
|
3737
|
+
"wit-bindgen-rust",
|
|
3738
|
+
]
|
|
3739
|
+
|
|
3740
|
+
[[package]]
|
|
3741
|
+
name = "wit-component"
|
|
3742
|
+
version = "0.244.0"
|
|
3743
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3744
|
+
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|
3745
|
+
dependencies = [
|
|
3746
|
+
"anyhow",
|
|
3747
|
+
"bitflags",
|
|
3748
|
+
"indexmap",
|
|
3749
|
+
"log",
|
|
3750
|
+
"serde",
|
|
3751
|
+
"serde_derive",
|
|
3752
|
+
"serde_json",
|
|
3753
|
+
"wasm-encoder",
|
|
3754
|
+
"wasm-metadata",
|
|
3755
|
+
"wasmparser",
|
|
3756
|
+
"wit-parser",
|
|
3757
|
+
]
|
|
3758
|
+
|
|
3759
|
+
[[package]]
|
|
3760
|
+
name = "wit-parser"
|
|
3761
|
+
version = "0.244.0"
|
|
3762
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3763
|
+
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|
3764
|
+
dependencies = [
|
|
3765
|
+
"anyhow",
|
|
3766
|
+
"id-arena",
|
|
3767
|
+
"indexmap",
|
|
3768
|
+
"log",
|
|
3769
|
+
"semver",
|
|
3770
|
+
"serde",
|
|
3771
|
+
"serde_derive",
|
|
3772
|
+
"serde_json",
|
|
3773
|
+
"unicode-xid",
|
|
3774
|
+
"wasmparser",
|
|
3775
|
+
]
|
|
3589
3776
|
|
|
3590
3777
|
[[package]]
|
|
3591
3778
|
name = "writeable"
|
|
@@ -3624,18 +3811,18 @@ dependencies = [
|
|
|
3624
3811
|
|
|
3625
3812
|
[[package]]
|
|
3626
3813
|
name = "zerocopy"
|
|
3627
|
-
version = "0.8.
|
|
3814
|
+
version = "0.8.39"
|
|
3628
3815
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3629
|
-
checksum = "
|
|
3816
|
+
checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a"
|
|
3630
3817
|
dependencies = [
|
|
3631
3818
|
"zerocopy-derive",
|
|
3632
3819
|
]
|
|
3633
3820
|
|
|
3634
3821
|
[[package]]
|
|
3635
3822
|
name = "zerocopy-derive"
|
|
3636
|
-
version = "0.8.
|
|
3823
|
+
version = "0.8.39"
|
|
3637
3824
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3638
|
-
checksum = "
|
|
3825
|
+
checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
|
|
3639
3826
|
dependencies = [
|
|
3640
3827
|
"proc-macro2",
|
|
3641
3828
|
"quote",
|
|
@@ -3724,9 +3911,9 @@ checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3"
|
|
|
3724
3911
|
|
|
3725
3912
|
[[package]]
|
|
3726
3913
|
name = "zmij"
|
|
3727
|
-
version = "1.0.
|
|
3914
|
+
version = "1.0.21"
|
|
3728
3915
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3729
|
-
checksum = "
|
|
3916
|
+
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
|
3730
3917
|
|
|
3731
3918
|
[[package]]
|
|
3732
3919
|
name = "zopfli"
|
data/ext/spikard_rb/Cargo.toml
CHANGED
data/ext/spikard_rb/extconf.rb
CHANGED
|
@@ -7,8 +7,6 @@ default_profile = ENV.fetch('CARGO_PROFILE', 'release')
|
|
|
7
7
|
|
|
8
8
|
create_rust_makefile('spikard_rb') do |config|
|
|
9
9
|
config.profile = default_profile.to_sym
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
# committed Cargo.lock to avoid workspace collision issues during builds.
|
|
13
|
-
config.extra_cargo_args = ['--locked']
|
|
10
|
+
# NOTE: CI vendors internal crates and patches Cargo.toml files before building.
|
|
11
|
+
# That can legitimately require updating Cargo.lock, so we must not force --locked.
|
|
14
12
|
end
|
data/lib/spikard/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "spikard-bindings-shared"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
authors = ["Na'aman Hirschfeld <nhirschfeld@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -38,12 +38,12 @@ ruby-support = ["magnus"]
|
|
|
38
38
|
php-support = ["ext-php-rs"]
|
|
39
39
|
|
|
40
40
|
[dependencies.pyo3]
|
|
41
|
-
version = "0.
|
|
41
|
+
version = "0.28"
|
|
42
42
|
optional = true
|
|
43
43
|
features = ["abi3-py310"]
|
|
44
44
|
|
|
45
45
|
[dependencies.pyo3-async-runtimes]
|
|
46
|
-
version = "0.
|
|
46
|
+
version = "0.28"
|
|
47
47
|
optional = true
|
|
48
48
|
features = ["tokio-runtime"]
|
|
49
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "spikard-core"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
authors = ["Na'aman Hirschfeld <nhirschfeld@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -8,7 +8,11 @@ repository = "https://github.com/Goldziher/spikard"
|
|
|
8
8
|
homepage = "https://github.com/Goldziher/spikard"
|
|
9
9
|
description = "Shared transport-agnostic primitives for Spikard runtimes"
|
|
10
10
|
keywords = ["http", "web", "framework", "validation", "middleware"]
|
|
11
|
-
categories = [
|
|
11
|
+
categories = [
|
|
12
|
+
"web-programming::http-server",
|
|
13
|
+
"web-programming",
|
|
14
|
+
"development-tools",
|
|
15
|
+
]
|
|
12
16
|
documentation = "https://docs.rs/spikard-core"
|
|
13
17
|
readme = "README.md"
|
|
14
18
|
|
|
@@ -31,12 +35,17 @@ flate2 = { version = "=1.1.5", default-features = false, features = ["rust_backe
|
|
|
31
35
|
brotli = "8.0"
|
|
32
36
|
http = "1.4"
|
|
33
37
|
base64 = "0.22"
|
|
34
|
-
serde_qs = "0
|
|
38
|
+
serde_qs = "1.0"
|
|
35
39
|
url = "2.5"
|
|
36
40
|
jiff = "0.2"
|
|
37
|
-
uuid = "1.
|
|
41
|
+
uuid = "1.21"
|
|
38
42
|
indexmap = "2.13"
|
|
39
|
-
tokio = { version = "1", optional = true, default-features = false, features = [
|
|
43
|
+
tokio = { version = "1", optional = true, default-features = false, features = [
|
|
44
|
+
"rt",
|
|
45
|
+
"macros",
|
|
46
|
+
"sync",
|
|
47
|
+
"time",
|
|
48
|
+
] }
|
|
40
49
|
bytes = { version = "1.11", optional = true }
|
|
41
50
|
thiserror = "2.0"
|
|
42
51
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "spikard-http"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
authors = ["Na'aman Hirschfeld <nhirschfeld@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -32,7 +32,7 @@ spikard-core = { path = "../spikard-core" }
|
|
|
32
32
|
futures-util = "0.3"
|
|
33
33
|
futures = "0.3"
|
|
34
34
|
jsonschema = { version = "0.37", default-features = false }
|
|
35
|
-
serde_qs = "0
|
|
35
|
+
serde_qs = "1.0"
|
|
36
36
|
lazy_static = "1.5"
|
|
37
37
|
lru = "0.16"
|
|
38
38
|
regex = "1"
|
|
@@ -41,7 +41,7 @@ urlencoding = "2.1"
|
|
|
41
41
|
url = "2.5"
|
|
42
42
|
mime = "0.3"
|
|
43
43
|
jiff = "0.2"
|
|
44
|
-
uuid = "1.
|
|
44
|
+
uuid = "1.21"
|
|
45
45
|
ahash = "0.8"
|
|
46
46
|
bytes = "1.11"
|
|
47
47
|
http-body-util = "0.1"
|
|
@@ -72,4 +72,4 @@ di = ["spikard-core/di"]
|
|
|
72
72
|
[dev-dependencies]
|
|
73
73
|
chrono = "0.4"
|
|
74
74
|
doc-comment = "0.3"
|
|
75
|
-
tempfile = "3.
|
|
75
|
+
tempfile = "3.25"
|
|
@@ -18,7 +18,7 @@ use url::form_urlencoded;
|
|
|
18
18
|
pub fn parse_urlencoded_to_json(data: &[u8]) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
|
|
19
19
|
if data.contains(&b'[') {
|
|
20
20
|
let body_str = std::str::from_utf8(data)?;
|
|
21
|
-
let config = serde_qs::Config::new(10
|
|
21
|
+
let config = serde_qs::Config::new().max_depth(10).use_form_encoding(true);
|
|
22
22
|
let parsed: HashMap<String, serde_json::Value> = config.deserialize_str(body_str)?;
|
|
23
23
|
let mut json_value = serde_json::to_value(parsed)?;
|
|
24
24
|
convert_types_recursive(&mut json_value);
|
|
@@ -411,9 +411,12 @@ pub fn is_grpc_request(request: &Request<Body>) -> bool {
|
|
|
411
411
|
mod tests {
|
|
412
412
|
use super::*;
|
|
413
413
|
use crate::grpc::handler::{GrpcHandler, GrpcHandlerResult, GrpcRequestData, GrpcResponseData, RpcMode};
|
|
414
|
+
use crate::grpc::streaming::{MessageStream, StreamingRequest, message_stream_from_vec};
|
|
414
415
|
use bytes::Bytes;
|
|
416
|
+
use futures_util::StreamExt;
|
|
415
417
|
use std::future::Future;
|
|
416
418
|
use std::pin::Pin;
|
|
419
|
+
use tonic::metadata::MetadataMap;
|
|
417
420
|
|
|
418
421
|
struct EchoHandler;
|
|
419
422
|
|
|
@@ -625,4 +628,228 @@ mod tests {
|
|
|
625
628
|
assert_eq!(status, StatusCode::PAYLOAD_TOO_LARGE);
|
|
626
629
|
assert!(message.contains("Message exceeds maximum size"));
|
|
627
630
|
}
|
|
631
|
+
|
|
632
|
+
#[tokio::test]
|
|
633
|
+
async fn test_route_grpc_request_server_streaming_success() {
|
|
634
|
+
struct StreamHandler;
|
|
635
|
+
|
|
636
|
+
impl GrpcHandler for StreamHandler {
|
|
637
|
+
fn call(&self, _request: GrpcRequestData) -> Pin<Box<dyn Future<Output = GrpcHandlerResult> + Send>> {
|
|
638
|
+
Box::pin(async { Err(tonic::Status::unimplemented("Use server streaming")) })
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
fn service_name(&self) -> &str {
|
|
642
|
+
"test.StreamService"
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
fn call_server_stream(
|
|
646
|
+
&self,
|
|
647
|
+
_request: GrpcRequestData,
|
|
648
|
+
) -> Pin<Box<dyn Future<Output = Result<MessageStream, tonic::Status>> + Send>> {
|
|
649
|
+
Box::pin(async {
|
|
650
|
+
let messages = vec![Bytes::from("m1"), Bytes::from("m2")];
|
|
651
|
+
Ok(message_stream_from_vec(messages))
|
|
652
|
+
})
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
let mut registry = GrpcRegistry::new();
|
|
657
|
+
registry.register("test.StreamService", Arc::new(StreamHandler), RpcMode::ServerStreaming);
|
|
658
|
+
let registry = Arc::new(registry);
|
|
659
|
+
let config = GrpcConfig::default();
|
|
660
|
+
|
|
661
|
+
let request = Request::builder()
|
|
662
|
+
.uri("/test.StreamService/Stream")
|
|
663
|
+
.header("content-type", "application/grpc")
|
|
664
|
+
.body(Body::from(Bytes::from("ignored")))
|
|
665
|
+
.unwrap();
|
|
666
|
+
|
|
667
|
+
let response = route_grpc_request(registry, &config, request).await.unwrap();
|
|
668
|
+
assert_eq!(response.status(), StatusCode::OK);
|
|
669
|
+
assert_eq!(
|
|
670
|
+
response.headers().get("content-type").unwrap(),
|
|
671
|
+
"application/grpc+proto"
|
|
672
|
+
);
|
|
673
|
+
assert_eq!(response.headers().get("grpc-status").unwrap(), "0");
|
|
674
|
+
|
|
675
|
+
// The body is a stream. For test purposes, just ensure we can read it.
|
|
676
|
+
let body = axum::body::to_bytes(response.into_body(), 1024).await.unwrap();
|
|
677
|
+
assert!(!body.is_empty());
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
#[tokio::test]
|
|
681
|
+
async fn test_route_grpc_request_client_streaming_success_and_response_metadata() {
|
|
682
|
+
struct ClientStreamHandler;
|
|
683
|
+
|
|
684
|
+
impl GrpcHandler for ClientStreamHandler {
|
|
685
|
+
fn call(&self, _request: GrpcRequestData) -> Pin<Box<dyn Future<Output = GrpcHandlerResult> + Send>> {
|
|
686
|
+
Box::pin(async { Err(tonic::Status::unimplemented("Use client streaming")) })
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
fn service_name(&self) -> &str {
|
|
690
|
+
"test.ClientStreamService"
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
fn call_client_stream(
|
|
694
|
+
&self,
|
|
695
|
+
mut request: StreamingRequest,
|
|
696
|
+
) -> Pin<Box<dyn Future<Output = Result<GrpcResponseData, tonic::Status>> + Send>> {
|
|
697
|
+
Box::pin(async move {
|
|
698
|
+
// Make sure routing copied request headers into metadata.
|
|
699
|
+
assert!(request.metadata.get("x-request-id").is_some());
|
|
700
|
+
|
|
701
|
+
let mut first = None;
|
|
702
|
+
while let Some(item) = request.message_stream.next().await {
|
|
703
|
+
first = Some(item?);
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
let payload = first.unwrap_or_else(Bytes::new);
|
|
708
|
+
let mut metadata = MetadataMap::new();
|
|
709
|
+
metadata.insert("x-response-id", "resp-123".parse().unwrap());
|
|
710
|
+
|
|
711
|
+
Ok(GrpcResponseData { payload, metadata })
|
|
712
|
+
})
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
let mut registry = GrpcRegistry::new();
|
|
717
|
+
registry.register(
|
|
718
|
+
"test.ClientStreamService",
|
|
719
|
+
Arc::new(ClientStreamHandler),
|
|
720
|
+
RpcMode::ClientStreaming,
|
|
721
|
+
);
|
|
722
|
+
let registry = Arc::new(registry);
|
|
723
|
+
let config = GrpcConfig::default();
|
|
724
|
+
|
|
725
|
+
// Single gRPC frame: compression=0, length=5, message="hello"
|
|
726
|
+
let frame = vec![
|
|
727
|
+
0x00, // compression: no
|
|
728
|
+
0x00, 0x00, 0x00, 0x05, // length: 5 bytes
|
|
729
|
+
b'h', b'e', b'l', b'l', b'o',
|
|
730
|
+
];
|
|
731
|
+
|
|
732
|
+
let request = Request::builder()
|
|
733
|
+
.uri("/test.ClientStreamService/ClientStream")
|
|
734
|
+
.header("content-type", "application/grpc")
|
|
735
|
+
.header("x-request-id", "req-123")
|
|
736
|
+
.body(Body::from(frame))
|
|
737
|
+
.unwrap();
|
|
738
|
+
|
|
739
|
+
let response = route_grpc_request(registry, &config, request).await.unwrap();
|
|
740
|
+
assert_eq!(response.status(), StatusCode::OK);
|
|
741
|
+
assert_eq!(response.headers().get("grpc-status").unwrap(), "0");
|
|
742
|
+
assert_eq!(response.headers().get("x-response-id").unwrap(), "resp-123");
|
|
743
|
+
|
|
744
|
+
let body = axum::body::to_bytes(response.into_body(), 1024).await.unwrap();
|
|
745
|
+
assert_eq!(body, Bytes::from_static(b"hello"));
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
#[tokio::test]
|
|
749
|
+
async fn test_route_grpc_request_bidi_streaming_success() {
|
|
750
|
+
struct BidiHandler;
|
|
751
|
+
|
|
752
|
+
impl GrpcHandler for BidiHandler {
|
|
753
|
+
fn call(&self, _request: GrpcRequestData) -> Pin<Box<dyn Future<Output = GrpcHandlerResult> + Send>> {
|
|
754
|
+
Box::pin(async { Err(tonic::Status::unimplemented("Use bidi streaming")) })
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
fn service_name(&self) -> &str {
|
|
758
|
+
"test.BidiService"
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
fn call_bidi_stream(
|
|
762
|
+
&self,
|
|
763
|
+
_request: StreamingRequest,
|
|
764
|
+
) -> Pin<Box<dyn Future<Output = Result<MessageStream, tonic::Status>> + Send>> {
|
|
765
|
+
Box::pin(async {
|
|
766
|
+
let messages = vec![Bytes::from("r1")];
|
|
767
|
+
Ok(message_stream_from_vec(messages))
|
|
768
|
+
})
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
let mut registry = GrpcRegistry::new();
|
|
773
|
+
registry.register(
|
|
774
|
+
"test.BidiService",
|
|
775
|
+
Arc::new(BidiHandler),
|
|
776
|
+
RpcMode::BidirectionalStreaming,
|
|
777
|
+
);
|
|
778
|
+
let registry = Arc::new(registry);
|
|
779
|
+
let config = GrpcConfig::default();
|
|
780
|
+
|
|
781
|
+
// Provide a well-formed request frame so the frame parser succeeds.
|
|
782
|
+
let frame = vec![
|
|
783
|
+
0x00, // compression: no
|
|
784
|
+
0x00, 0x00, 0x00, 0x01, // length: 1 byte
|
|
785
|
+
b'x',
|
|
786
|
+
];
|
|
787
|
+
|
|
788
|
+
let request = Request::builder()
|
|
789
|
+
.uri("/test.BidiService/Chat")
|
|
790
|
+
.header("content-type", "application/grpc")
|
|
791
|
+
.body(Body::from(frame))
|
|
792
|
+
.unwrap();
|
|
793
|
+
|
|
794
|
+
let response = route_grpc_request(registry, &config, request).await.unwrap();
|
|
795
|
+
assert_eq!(response.status(), StatusCode::OK);
|
|
796
|
+
assert_eq!(response.headers().get("grpc-status").unwrap(), "0");
|
|
797
|
+
|
|
798
|
+
let body = axum::body::to_bytes(response.into_body(), 1024).await.unwrap();
|
|
799
|
+
assert!(!body.is_empty());
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
#[tokio::test]
|
|
803
|
+
async fn test_route_grpc_request_client_streaming_invalid_compression_flag_maps_to_501() {
|
|
804
|
+
// Use a handler that would succeed, but the request is invalid before handler gets called.
|
|
805
|
+
struct NeverCalledHandler;
|
|
806
|
+
|
|
807
|
+
impl GrpcHandler for NeverCalledHandler {
|
|
808
|
+
fn call(&self, _request: GrpcRequestData) -> Pin<Box<dyn Future<Output = GrpcHandlerResult> + Send>> {
|
|
809
|
+
Box::pin(async { Err(tonic::Status::unimplemented("not used")) })
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
fn service_name(&self) -> &str {
|
|
813
|
+
"test.BadClientStreamService"
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
fn call_client_stream(
|
|
817
|
+
&self,
|
|
818
|
+
_request: StreamingRequest,
|
|
819
|
+
) -> Pin<Box<dyn Future<Output = Result<GrpcResponseData, tonic::Status>> + Send>> {
|
|
820
|
+
Box::pin(async {
|
|
821
|
+
Ok(GrpcResponseData {
|
|
822
|
+
payload: Bytes::from_static(b"ok"),
|
|
823
|
+
metadata: MetadataMap::new(),
|
|
824
|
+
})
|
|
825
|
+
})
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
let mut registry = GrpcRegistry::new();
|
|
830
|
+
registry.register(
|
|
831
|
+
"test.BadClientStreamService",
|
|
832
|
+
Arc::new(NeverCalledHandler),
|
|
833
|
+
RpcMode::ClientStreaming,
|
|
834
|
+
);
|
|
835
|
+
let registry = Arc::new(registry);
|
|
836
|
+
let config = GrpcConfig::default();
|
|
837
|
+
|
|
838
|
+
// Compression flag = 1 => UNIMPLEMENTED per parser.
|
|
839
|
+
let frame = vec![
|
|
840
|
+
0x01, // compression: yes (unsupported)
|
|
841
|
+
0x00, 0x00, 0x00, 0x01, // length: 1 byte
|
|
842
|
+
b'x',
|
|
843
|
+
];
|
|
844
|
+
|
|
845
|
+
let request = Request::builder()
|
|
846
|
+
.uri("/test.BadClientStreamService/ClientStream")
|
|
847
|
+
.header("content-type", "application/grpc")
|
|
848
|
+
.body(Body::from(frame))
|
|
849
|
+
.unwrap();
|
|
850
|
+
|
|
851
|
+
let err = route_grpc_request(registry, &config, request).await.unwrap_err();
|
|
852
|
+
assert_eq!(err.0, StatusCode::NOT_IMPLEMENTED);
|
|
853
|
+
assert!(err.1.contains("compression") || err.1.contains("supported"));
|
|
854
|
+
}
|
|
628
855
|
}
|
|
@@ -507,11 +507,7 @@ fn build_router_with_handlers_inner(
|
|
|
507
507
|
for (route, handler) in route_handlers {
|
|
508
508
|
#[cfg(feature = "di")]
|
|
509
509
|
let handler = if let Some(ref container) = di_container {
|
|
510
|
-
let
|
|
511
|
-
if required_deps.is_empty() {
|
|
512
|
-
required_deps = container.keys();
|
|
513
|
-
}
|
|
514
|
-
|
|
510
|
+
let required_deps = extract_handler_dependencies(&route);
|
|
515
511
|
if !required_deps.is_empty() {
|
|
516
512
|
Arc::new(crate::di_handler::DependencyInjectingHandler::new(
|
|
517
513
|
handler,
|
|
@@ -720,7 +716,7 @@ pub fn build_router_with_handlers_and_config(
|
|
|
720
716
|
config: ServerConfig,
|
|
721
717
|
route_metadata: Vec<crate::RouteMetadata>,
|
|
722
718
|
) -> Result<AxumRouter, String> {
|
|
723
|
-
#[cfg(feature = "di")]
|
|
719
|
+
#[cfg(all(feature = "di", debug_assertions))]
|
|
724
720
|
if let Some(di_container) = config.di_container.as_ref() {
|
|
725
721
|
eprintln!(
|
|
726
722
|
"[spikard-di] build_router: di_container has keys: {:?}",
|
|
@@ -1093,14 +1089,19 @@ impl Server {
|
|
|
1093
1089
|
}
|
|
1094
1090
|
|
|
1095
1091
|
/// Initialize logging
|
|
1092
|
+
///
|
|
1093
|
+
/// This function is idempotent - calling it multiple times is safe.
|
|
1094
|
+
/// It uses `try_init()` instead of `init()` to avoid panics when the
|
|
1095
|
+
/// global subscriber has already been set (e.g., by a language runtime
|
|
1096
|
+
/// or a previous call).
|
|
1096
1097
|
pub fn init_logging() {
|
|
1097
|
-
tracing_subscriber::registry()
|
|
1098
|
+
let _ = tracing_subscriber::registry()
|
|
1098
1099
|
.with(
|
|
1099
1100
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
1100
1101
|
.unwrap_or_else(|_| "spikard=info,tower_http=info".into()),
|
|
1101
1102
|
)
|
|
1102
1103
|
.with(tracing_subscriber::fmt::layer())
|
|
1103
|
-
.
|
|
1104
|
+
.try_init();
|
|
1104
1105
|
}
|
|
1105
1106
|
|
|
1106
1107
|
/// Start the server
|
|
@@ -170,6 +170,46 @@ pub async fn snapshot_http_response(
|
|
|
170
170
|
})
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
/// Convert an Axum response into a reusable [`ResponseSnapshot`], allowing body stream errors.
|
|
174
|
+
///
|
|
175
|
+
/// This is useful for streaming responses where a producer might abort mid-stream (for example,
|
|
176
|
+
/// a JavaScript async generator throwing). In those cases, collecting the whole body can fail
|
|
177
|
+
/// with a "Stream error". This helper returns the bytes read up to the first stream error.
|
|
178
|
+
pub async fn snapshot_http_response_allow_body_errors(
|
|
179
|
+
response: axum::response::Response<Body>,
|
|
180
|
+
) -> Result<ResponseSnapshot, SnapshotError> {
|
|
181
|
+
let (parts, mut body) = response.into_parts();
|
|
182
|
+
let status = parts.status.as_u16();
|
|
183
|
+
|
|
184
|
+
let mut headers = HashMap::new();
|
|
185
|
+
for (name, value) in parts.headers.iter() {
|
|
186
|
+
let header_value = value
|
|
187
|
+
.to_str()
|
|
188
|
+
.map_err(|e| SnapshotError::InvalidHeader(e.to_string()))?;
|
|
189
|
+
headers.insert(name.to_string().to_ascii_lowercase(), header_value.to_string());
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let mut bytes = Vec::<u8>::new();
|
|
193
|
+
while let Some(frame_result) = body.frame().await {
|
|
194
|
+
match frame_result {
|
|
195
|
+
Ok(frame) => {
|
|
196
|
+
if let Ok(data) = frame.into_data() {
|
|
197
|
+
bytes.extend_from_slice(&data);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
Err(_) => break,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let decoded_body = decode_body(&headers, bytes)?;
|
|
205
|
+
|
|
206
|
+
Ok(ResponseSnapshot {
|
|
207
|
+
status,
|
|
208
|
+
headers,
|
|
209
|
+
body: decoded_body,
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
173
213
|
fn decode_body(headers: &HashMap<String, String>, body: Vec<u8>) -> Result<Vec<u8>, SnapshotError> {
|
|
174
214
|
let encoding = headers
|
|
175
215
|
.get("content-encoding")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "spikard-rb"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
authors = ["Na'aman Hirschfeld <nhirschfeld@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -40,7 +40,7 @@ tokio = { version = "1", features = ["full"] }
|
|
|
40
40
|
tonic = { version = "0.14", features = ["transport", "codegen", "gzip"] }
|
|
41
41
|
tungstenite = "0.28"
|
|
42
42
|
tracing = "0.1"
|
|
43
|
-
serde_qs = "0
|
|
43
|
+
serde_qs = "1.0"
|
|
44
44
|
urlencoding = "2.1"
|
|
45
45
|
once_cell = "1.21"
|
|
46
46
|
async-stream = "0.3"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spikard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Na'aman Hirschfeld
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: base64
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: rb_sys
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|