diff --git a/Cargo.lock b/Cargo.lock index 4519e474..f16c9736 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,43 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-siv" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e08d0cdb774acd1e4dac11478b1a0c0d203134b2aab0ba25eb430de9b18f8b9" +dependencies = [ + "aead", + "aes", + "cipher", + "cmac", + "ctr", + "dbl", + "digest", + "zeroize", +] + [[package]] name = "ahash" version = "0.8.12" @@ -36,6 +73,7 @@ dependencies = [ "cfg-if", "getrandom 0.3.3", "once_cell", + "serde", "version_check", "zerocopy", ] @@ -70,18 +108,83 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "arraydeque" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii-canvas" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1e3e699d84ab1b0911a1010c5c106aa34ae89aeac103be5ce0c3859db1e891" +dependencies = [ + "term", +] + [[package]] name = "ascii_utils" version = "0.9.3" @@ -316,9 +419,21 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + +[[package]] +name = "base62" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adf9755786e27479693dedd3271691a92b5e242ab139cacb9fb8e7fb5381111" + [[package]] name = "base64" version = "0.21.7" @@ -331,6 +446,37 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.4" @@ -349,12 +495,33 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borrow-or-share" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" + [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + [[package]] name = "bytes" version = "1.10.1" @@ -370,6 +537,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.38" @@ -377,9 +553,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] +[[package]] +name = "cfb-mode" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" +dependencies = [ + "cipher", +] + [[package]] name = "cfg-if" version = "1.0.3" @@ -392,6 +579,40 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "charset" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" +dependencies = [ + "base64 0.22.1", + "encoding_rs", +] + [[package]] name = "chrono" version = "0.4.42" @@ -399,11 +620,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-link 0.2.0", ] +[[package]] +name = "chrono-tz" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" +dependencies = [ + "chrono", + "phf", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -431,6 +664,23 @@ dependencies = [ "half", ] +[[package]] +name = "cidr" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd1b64030216239a2e7c364b13cd96a2097ebf0dfe5025f2dedee14a23f2ab60" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clap" version = "4.5.48" @@ -438,6 +688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -446,8 +697,22 @@ version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] @@ -456,6 +721,34 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +[[package]] +name = "cmac" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" +dependencies = [ + "cipher", + "dbl", + "digest", +] + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "combine" version = "4.6.7" @@ -466,6 +759,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "community-id" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48629740a3480b865d4083ff45f826a253bd5ce28db618d89359b0e95dc750c3" +dependencies = [ + "base64 0.22.1", + "hex", + "sha1", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -482,7 +786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cef036f0ecf99baef11555578630e2cca559909b4c50822dbba828c252d21c49" dependencies = [ "async-trait", - "convert_case", + "convert_case 0.6.0", "json5", "pathdiff", "ron", @@ -546,6 +850,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -556,6 +869,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -582,6 +905,30 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "criterion" version = "0.7.0" @@ -593,7 +940,7 @@ dependencies = [ "ciborium", "clap", "criterion-plot", - "itertools", + "itertools 0.13.0", "num-traits", "oorandom", "plotters", @@ -613,7 +960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", - "itertools", + "itertools 0.13.0", ] [[package]] @@ -663,9 +1010,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "ctrlc" version = "3.5.0" @@ -758,7 +1151,7 @@ dependencies = [ "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.11", ] [[package]] @@ -767,6 +1160,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "dbl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" +dependencies = [ + "generic-array", +] + [[package]] name = "deranged" version = "0.5.3" @@ -778,13 +1180,25 @@ dependencies = [ ] [[package]] -name = "digest" -version = "0.10.7" +name = "derivative" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "block-buffer", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -793,6 +1207,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "dlv-list" version = "0.5.2" @@ -802,6 +1227,57 @@ dependencies = [ "const-random", ] +[[package]] +name = "dns-lookup" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5597a4b7fe5275fc9dcf88ce26326bc8e4cb87d0130f33752d4c5f717793cf" +dependencies = [ + "cfg-if", + "libc", + "socket2 0.6.0", + "windows-sys 0.60.2", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "domain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11dd7f04a6a6d2aea0153c6e31f5ea7af8b2efdf52cdaeea7a9a592c7fefef9" +dependencies = [ + "bumpalo", + "bytes", + "domain-macros", + "futures-util", + "hashbrown 0.14.5", + "log", + "moka", + "octseq", + "rand 0.8.5", + "serde", + "smallvec", + "time", + "tokio", + "tracing", +] + +[[package]] +name = "domain-macros" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e197fdfd2cdb5fdeb7f8ddcf3aed5d5d04ecde2890d448b14ffb716f7376b70" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "dyn-clone" version = "1.0.20" @@ -814,6 +1290,24 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "email_address" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +dependencies = [ + "serde", +] + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -896,6 +1390,29 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fancy-regex" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6215aee357f8c7c989ebb4b8466ca4d7dc93b3957039f2fc3ea2ade8ea5f279" +dependencies = [ + "bit-set", + "derivative", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fancy-regex" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998b056554fbe42e03ae0e152895cd1a7e1002aec800fdc6635d20270260c46f" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + [[package]] name = "fast_chemail" version = "0.9.6" @@ -935,6 +1452,28 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "libz-rs-sys", + "miniz_oxide", +] + +[[package]] +name = "fluent-uri" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1918b65d96df47d3591bed19c5cca17e3fa5d0707318e4b5ef2eae01764df7e5" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + [[package]] name = "fnv" version = "1.0.7" @@ -971,6 +1510,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fraction" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "futures" version = "0.3.31" @@ -1088,6 +1637,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1097,8 +1647,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1108,9 +1660,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.7+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1119,6 +1673,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "graphql-parser" version = "0.4.1" @@ -1142,6 +1702,16 @@ dependencies = [ "serde_with", ] +[[package]] +name = "grok" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e2d7bd791814b06a609b74361ac35b448eb4718548937c6de718554a4348577" +dependencies = [ + "glob", + "onig", +] + [[package]] name = "h2" version = "0.4.12" @@ -1196,6 +1766,9 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "allocator-api2", +] [[package]] name = "hashbrown" @@ -1223,6 +1796,12 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1259,7 +1838,7 @@ dependencies = [ "mimalloc", "moka", "ntex", - "rand", + "rand 0.9.2", "serde", "sonic-rs", "thiserror 2.0.16", @@ -1316,6 +1895,7 @@ dependencies = [ "thiserror 2.0.16", "tokio", "tracing", + "vrl", "xxhash-rust", ] @@ -1323,14 +1903,14 @@ dependencies = [ name = "hive-router-query-planner" version = "1.0.0" dependencies = [ - "bitflags", + "bitflags 2.9.4", "criterion", "graphql-parser", "graphql-tools", "insta", "lazy-init", "lazy_static", - "petgraph", + "petgraph 0.8.2", "rustc-hash", "serde", "sonic-rs", @@ -1341,6 +1921,26 @@ dependencies = [ "tracing-tree", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hostname" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" +dependencies = [ + "cfg-if", + "libc", + "windows-link 0.1.3", +] + [[package]] name = "http" version = "1.3.1" @@ -1426,6 +2026,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1448,6 +2065,7 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", "futures-core", @@ -1455,7 +2073,9 @@ dependencies = [ "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2 0.6.0", "tokio", @@ -1487,12 +2107,119 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1516,6 +2243,35 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "influxdb-line-protocol" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fa7ee6be451ea0b1912b962c91c8380835e97cf1584a77e18264e908448dcb" +dependencies = [ + "bytes", + "log", + "nom 7.1.3", + "smallvec", + "snafu 0.7.5", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "insta" version = "1.43.2" @@ -1527,58 +2283,186 @@ dependencies = [ "similar", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "io-uring" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags", + "bitflags 2.9.4", "cfg-if", "libc", ] [[package]] -name = "itertools" -version = "0.13.0" +name = "ipcrypt-rs" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +checksum = "96e4f67dbfc0f75d7b65953ecf0be3fd84ee0cb1ae72a00a4aa9a2f5518a2c80" dependencies = [ - "either", + "aes", ] [[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "js-sys" -version = "0.3.80" +name = "ipnet" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" -dependencies = [ - "once_cell", - "wasm-bindgen", -] +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] -name = "json5" -version = "0.4.1" +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" dependencies = [ - "pest", - "pest_derive", + "memchr", "serde", ] [[package]] -name = "lazy-init" -version = "0.5.1" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f40963626ac12dcaf92afc15e4c3db624858c92fd9f8ba2125eaada3ac2706f" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "jsonschema" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24690c68dfcdde5980d676b0f1820981841016b1f29eecb4c42ad48ab4118681" +dependencies = [ + "ahash", + "base64 0.22.1", + "bytecount", + "email_address", + "fancy-regex 0.16.2", + "fraction", + "idna", + "itoa", + "num-cmp", + "num-traits", + "once_cell", + "percent-encoding", + "referencing", + "regex", + "regex-syntax", + "serde", + "serde_json", + "uuid-simd", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.14.0", + "lalrpop-util", + "petgraph 0.7.1", + "regex", + "regex-syntax", + "sha3", + "string_cache", + "term", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" +dependencies = [ + "regex-automata", + "rustversion", +] + +[[package]] +name = "lazy-init" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f40963626ac12dcaf92afc15e4c3db624858c92fd9f8ba2125eaada3ac2706f" [[package]] name = "lazy_static" @@ -1602,12 +2486,27 @@ dependencies = [ "libc", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" +dependencies = [ + "zlib-rs", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + [[package]] name = "lock_api" version = "0.4.13" @@ -1637,6 +2536,21 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +dependencies = [ + "twox-hash", +] + [[package]] name = "matchers" version = "0.2.0" @@ -1652,6 +2566,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.5" @@ -1683,6 +2607,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1716,7 +2646,7 @@ dependencies = [ "event-listener", "futures-util", "loom", - "parking_lot", + "parking_lot 0.12.4", "portable-atomic", "rustc_version", "smallvec", @@ -1780,23 +2710,63 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nix" version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags", + "bitflags 2.9.4", "cfg-if", "cfg_aliases", "libc", ] +[[package]] +name = "nohash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f889fb66f7acdf83442c35775764b51fed3c606ab9cee51500dbde2cf528ca" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom-language" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29" +dependencies = [ + "nom 8.0.0", +] + [[package]] name = "ntex" version = "2.16.0" @@ -1804,7 +2774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4b41d1af2e11a7c29499395c2505550507749c35b29fa4a31234130abdb2285" dependencies = [ "base64 0.22.1", - "bitflags", + "bitflags 2.9.4", "encoding_rs", "env_logger", "httparse", @@ -1842,7 +2812,7 @@ version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d23b86ef2f4a947e29e959a61bdae71c9d52a80df02936a9992bc6dbda9ddb" dependencies = [ - "bitflags", + "bitflags 2.9.4", "bytes", "futures-core", "serde", @@ -1864,7 +2834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bfa6c16696b2b08cef057d581b67726213b71b42be69cda1977e351b9a36e5c" dependencies = [ "ahash", - "bitflags", + "bitflags 2.9.4", "log", "nanorand", "ntex-bytes", @@ -1900,7 +2870,7 @@ version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55eb13ef2e89f799ef0395911b6365052cab4cea65a7d2ef870e39732bf346b2" dependencies = [ - "bitflags", + "bitflags 2.9.4", "log", "ntex-bytes", "ntex-codec", @@ -1926,7 +2896,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e25de68e90b2f1f15a765366e170b0d5b2d2fe0f81db03673505998a009f991" dependencies = [ - "bitflags", + "bitflags 2.9.4", "cfg-if", "libc", "log", @@ -2032,7 +3002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7811bcf3c3228631b0b20d12e5786c20c4cc76fb2d2b2733a6ab421641f81b6a" dependencies = [ "ahash", - "bitflags", + "bitflags 2.9.4", "futures-core", "futures-timer", "log", @@ -2053,12 +3023,82 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2087,31 +3127,85 @@ dependencies = [ "memchr", ] +[[package]] +name = "octseq" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126c3ca37c9c44cec575247f43a3e4374d8927684f129d2beeb0d2cef262fe12" +dependencies = [ + "bytes", + "serde", + "smallvec", +] + +[[package]] +name = "ofb" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc40678e045ff4eb1666ea6c0f994b133c31f673c09aed292261b6d5b6963a0" +dependencies = [ + "cipher", +] + [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "oneshot" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ce411919553d3f9fa53a0880544cda985a112117a0444d5ff1e870a893d6ea" +[[package]] +name = "onig" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" +dependencies = [ + "bitflags 2.9.4", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "oorandom" version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags", + "bitflags 2.9.4", "cfg-if", "foreign-types", "libc", @@ -2159,6 +3253,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-multimap" version = "0.7.3" @@ -2169,12 +3272,29 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + [[package]] name = "parking" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.4" @@ -2182,7 +3302,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.11", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -2193,17 +3327,29 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.17", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] +[[package]] +name = "parse-size" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" + [[package]] name = "pathdiff" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "peeking_take_while" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9ed2178b0575fff8e1b83b58ba6f75e727aafac2e1b6c795169ad3b17eb518" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2254,6 +3400,16 @@ dependencies = [ "sha2", ] +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap 2.11.4", +] + [[package]] name = "petgraph" version = "0.8.2" @@ -2266,6 +3422,33 @@ dependencies = [ "serde", ] +[[package]] +name = "phf" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" +dependencies = [ + "phf_shared 0.12.1", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2326,12 +3509,32 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2347,6 +3550,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -2365,6 +3574,64 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "prost-reflect" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5edd582b62f5cde844716e66d92565d7faf7ab1445c8cebce6e00fba83ddb2" +dependencies = [ + "once_cell", + "prost", + "prost-types", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost", +] + +[[package]] +name = "psl" +version = "2.1.144" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b68d05319870d64ad7b885dbdb3437a62c6efbf223f07bb6fb90a20baf3cad" +dependencies = [ + "psl-types", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + [[package]] name = "ptr_meta" version = "0.3.0" @@ -2385,6 +3652,16 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" +dependencies = [ + "idna", + "psl-types", +] + [[package]] name = "qp-dev-cli" version = "0.0.0" @@ -2407,6 +3684,61 @@ dependencies = [ "web-sys", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.0", + "thiserror 2.0.16", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.16", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.0", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.40" @@ -2416,6 +3748,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quoted_printable" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" + [[package]] name = "r-efi" version = "5.3.0" @@ -2431,14 +3769,35 @@ dependencies = [ "ptr_meta", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -2448,7 +3807,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", ] [[package]] @@ -2480,13 +3848,22 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags", + "bitflags 2.9.4", ] [[package]] @@ -2509,6 +3886,20 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "referencing" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3d769362109497b240e66462606bc28af68116436c8669bac17069533b908e" +dependencies = [ + "ahash", + "fluent-uri", + "once_cell", + "parking_lot 0.12.4", + "percent-encoding", + "serde_json", +] + [[package]] name = "regex" version = "1.11.2" @@ -2532,6 +3923,20 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-filtered" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c11639076bf147be211b90e47790db89f4c22b6c8a9ca6e960833869da67166" +dependencies = [ + "aho-corasick", + "indexmap 2.11.4", + "itertools 0.13.0", + "nohash", + "regex", + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.8.6" @@ -2544,6 +3949,104 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" +[[package]] +name = "reqwest" +version = "0.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "reqwest-middleware" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" +dependencies = [ + "anyhow", + "async-trait", + "http", + "reqwest", + "serde", + "thiserror 1.0.69", + "tower-service", +] + +[[package]] +name = "reqwest-retry" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c73e4195a6bfbcb174b790d9b3407ab90646976c55de58a6515da25d851178" +dependencies = [ + "anyhow", + "async-trait", + "futures", + "getrandom 0.2.16", + "http", + "hyper", + "parking_lot 0.11.2", + "reqwest", + "reqwest-middleware", + "retry-policies", + "thiserror 1.0.69", + "tokio", + "wasm-timer", +] + +[[package]] +name = "retry-policies" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5875471e6cab2871bc150ecb8c727db5113c9338cc3354dc5ee3425b6aa40a1c" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rkyv" version = "0.8.11" @@ -2580,11 +4083,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags", + "bitflags 2.9.4", "serde", "serde_derive", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rust-ini" version = "0.21.3" @@ -2595,6 +4104,16 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust_decimal" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" +dependencies = [ + "arrayvec", + "num-traits", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -2622,13 +4141,60 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags", + "bitflags 2.9.4", "errno", "libc", "linux-raw-sys", "windows-sys 0.61.0", ] +[[package]] +name = "rustls" +version = "0.23.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.5.0", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -2641,6 +4207,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -2708,14 +4283,33 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", - "core-foundation", + "bitflags 2.9.4", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc198e42d9b7510827939c9a15f5062a0c913f3371d765977e586d2fe6c16f4a" +dependencies = [ + "bitflags 2.9.4", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -2867,6 +4461,30 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.11.4", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2889,6 +4507,16 @@ dependencies = [ "digest", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2935,6 +4563,12 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.11" @@ -2947,6 +4581,55 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "snafu" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" +dependencies = [ + "doc-comment", + "snafu-derive 0.7.5", +] + +[[package]] +name = "snafu" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" +dependencies = [ + "snafu-derive 0.8.9", +] + +[[package]] +name = "snafu-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "snafu-derive" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + [[package]] name = "socket2" version = "0.5.10" @@ -3012,12 +4695,39 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions_next" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot 0.12.4", + "phf_shared 0.11.3", + "precomputed-hash", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -3039,7 +4749,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -3054,10 +4764,16 @@ dependencies = [ "async-graphql-axum", "axum", "lazy_static", - "rand", + "rand 0.9.2", "tokio", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -3085,6 +4801,30 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "syslog_loose" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ec4df26907adce53e94eac201a9ba38744baea3bc97f34ffd591d5646231a6" +dependencies = [ + "chrono", + "nom 8.0.0", +] [[package]] name = "tagptr" @@ -3105,6 +4845,24 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "term" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2111ef44dae28680ae9752bb89409e7310ca33a8c621ebe7b106cf5c928b3ac0" +dependencies = [ + "windows-sys 0.61.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -3194,6 +4952,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -3230,7 +4998,7 @@ dependencies = [ "io-uring", "libc", "mio", - "parking_lot", + "parking_lot 0.12.4", "pin-project-lite", "signal-hook-registry", "slab", @@ -3260,6 +5028,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -3356,6 +5134,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -3473,12 +5269,18 @@ dependencies = [ "http", "httparse", "log", - "rand", + "rand 0.9.2", "sha1", "thiserror 2.0.16", "utf-8", ] +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + [[package]] name = "typeid" version = "1.0.3" @@ -3491,6 +5293,17 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "ua-parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c06b979bd5606d182759ff9cd3dda2b034b584a1ed41116407cb92abf3c995a" +dependencies = [ + "regex", + "regex-filtered", + "serde", +] + [[package]] name = "ucd-trie" version = "0.1.7" @@ -3503,7 +5316,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ - "rand", + "rand 0.9.2", "web-time", ] @@ -3519,12 +5332,76 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.18.1" @@ -3536,6 +5413,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + [[package]] name = "valuable" version = "0.1.1" @@ -3565,6 +5453,122 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vrl" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374906b686967832d85e5ce8f43581924e8382787e538c61c1e2158e09fc6518" +dependencies = [ + "aes", + "aes-siv", + "base16", + "base62", + "base64-simd", + "bytes", + "cbc", + "cfb-mode", + "cfg-if", + "chacha20poly1305", + "charset", + "chrono", + "chrono-tz", + "ciborium", + "cidr", + "clap", + "codespan-reporting", + "community-id", + "convert_case 0.7.1", + "crc", + "crypto_secretbox", + "csv", + "ctr", + "digest", + "dns-lookup", + "domain", + "dyn-clone", + "encoding_rs", + "fancy-regex 0.15.0", + "flate2", + "grok", + "hex", + "hmac", + "hostname", + "iana-time-zone", + "idna", + "indexmap 2.11.4", + "indoc", + "influxdb-line-protocol", + "ipcrypt-rs", + "itertools 0.14.0", + "jsonschema", + "lalrpop", + "lalrpop-util", + "lz4_flex", + "md-5", + "nom 8.0.0", + "nom-language", + "ofb", + "onig", + "ordered-float", + "parse-size", + "peeking_take_while", + "percent-encoding", + "pest", + "pest_derive", + "prost", + "prost-reflect", + "psl", + "psl-types", + "publicsuffix", + "quoted_printable", + "rand 0.8.5", + "regex", + "reqwest", + "reqwest-middleware", + "reqwest-retry", + "roxmltree", + "rust_decimal", + "seahash", + "serde", + "serde_json", + "serde_yaml", + "sha-1", + "sha2", + "sha3", + "simdutf8", + "snafu 0.8.9", + "snap", + "strip-ansi-escapes", + "syslog_loose", + "termcolor", + "thiserror 2.0.16", + "tokio", + "tracing", + "ua-parser", + "unicode-segmentation", + "url", + "utf8-width", + "uuid", + "woothee", + "xxhash-rust", + "zstd", +] + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -3704,6 +5708,21 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.80" @@ -3900,7 +5919,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3909,7 +5928,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -3927,14 +5955,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link 0.1.3", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -3952,48 +5997,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.13" @@ -4009,6 +6102,22 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "woothee" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "896174c6a4779d4d7d4523dd27aef7d46609eda2497e370f6c998325c6bf6971" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "xxhash-rust" version = "0.8.15" @@ -4026,6 +6135,30 @@ dependencies = [ "hashlink", ] +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.8.27" @@ -4045,3 +6178,97 @@ dependencies = [ "quote", "syn 2.0.106", ] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zlib-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/bin/router/src/pipeline/execution.rs b/bin/router/src/pipeline/execution.rs index 537eaf4f..1c902097 100644 --- a/bin/router/src/pipeline/execution.rs +++ b/bin/router/src/pipeline/execution.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -6,9 +7,12 @@ use crate::pipeline::error::{PipelineError, PipelineErrorFromAcceptHeader, Pipel use crate::pipeline::normalize::GraphQLNormalizationPayload; use crate::shared_state::RouterSharedState; use hive_router_plan_executor::execute_query_plan; -use hive_router_plan_executor::execution::plan::{PlanExecutionOutput, QueryPlanExecutionContext}; +use hive_router_plan_executor::execution::plan::{ + ClientRequestDetails, OperationDetails, PlanExecutionOutput, QueryPlanExecutionContext, +}; use hive_router_plan_executor::introspection::resolve::IntrospectionContext; use hive_router_query_planner::planner::plan_nodes::QueryPlan; +use hive_router_query_planner::state::supergraph_state::OperationKind; use http::HeaderName; use ntex::web::HttpRequest; @@ -22,8 +26,9 @@ enum ExposeQueryPlanMode { } #[inline] -pub async fn execute_plan( +pub async fn execute_plan<'a>( req: &mut HttpRequest, + query: Cow<'a, str>, app_state: &Arc, normalized_payload: &Arc, query_plan_payload: &Arc, @@ -66,7 +71,21 @@ pub async fn execute_plan( headers_plan: &app_state.headers_plan, variable_values: &variable_payload.variables_map, extensions, - upstream_headers: req.headers(), + client_request: ClientRequestDetails { + method: req.method().clone(), + url: req.uri().clone(), + headers: req.headers(), + operation: OperationDetails { + name: normalized_payload.operation_for_plan.name.clone(), + kind: match normalized_payload.operation_for_plan.operation_kind { + Some(OperationKind::Query) => "query", + Some(OperationKind::Mutation) => "mutation", + Some(OperationKind::Subscription) => "subscription", + None => "query", + }, + query, + }, + }, introspection_context: &introspection_context, operation_type_name: normalized_payload.root_type_name, executors: &app_state.subgraph_executor_map, diff --git a/bin/router/src/pipeline/mod.rs b/bin/router/src/pipeline/mod.rs index f555221f..671730d5 100644 --- a/bin/router/src/pipeline/mod.rs +++ b/bin/router/src/pipeline/mod.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use hive_router_plan_executor::execution::plan::PlanExecutionOutput; use hive_router_query_planner::utils::cancellation::CancellationToken; @@ -92,6 +92,7 @@ pub async fn execute_pipeline( let progressive_override_ctx = request_override_context()?; let normalize_payload = normalize_request_with_cache(req, state, &execution_request, &parser_payload).await?; + let query = Cow::Owned(execution_request.query.clone()); let variable_payload = coerce_request_variables(req, state, execution_request, &normalize_payload)?; @@ -109,6 +110,7 @@ pub async fn execute_pipeline( let execution_result = execute_plan( req, + query, state, &normalize_payload, &query_plan_payload, diff --git a/docs/README.md b/docs/README.md index ff60b72f..6ed3c358 100644 --- a/docs/README.md +++ b/docs/README.md @@ -321,6 +321,34 @@ Static value provided in the config. |**value**|`string`||yes| +  +**Option 2 (optional):** +A dynamic value computed by a VRL expression. + +This allows you to generate header values based on the incoming request, +subgraph name, and (for response rules) subgraph response headers. +The expression has access to a context object with `.request`, `.subgraph`, +and `.response` fields. + +For more information on the available functions and syntax, see the +[VRL documentation](https://vrl.dev/). + +### Example +```yaml +# Insert a header with a value derived from another header. +- insert: + name: x-auth-scheme + expression: 'split(.request.headers.authorization, " ")[0] ?? "none"' +``` + + +**Properties** + +|Name|Type|Description|Required| +|----|----|-----------|--------| +|**expression**|`string`||yes| + + #### headers\.all\.response\[\]: array,null @@ -405,7 +433,8 @@ For never-join headers, appends another occurrence (multiple lines). **Example** ```yaml -insert: {} +insert: + algorithm: null ``` @@ -549,6 +578,7 @@ Insert a header with a static value. |Name|Type|Description|Required| |----|----|-----------|--------| +|**algorithm**||How to merge values across multiple subgraph responses.
Default: `Last` (overwrite).
|no| |**name**|`string`|Header name to insert or overwrite (case-insensitive).
|yes|   @@ -563,6 +593,41 @@ Static value provided in the config. |**value**|`string`||yes| +  +**Option 2 (optional):** +A dynamic value computed by a VRL expression. + +This allows you to generate header values based on the incoming request, +subgraph name, and (for response rules) subgraph response headers. +The expression has access to a context object with `.request`, `.subgraph`, +and `.response` fields. + +For more information on the available functions and syntax, see the +[VRL documentation](https://vrl.dev/). + +### Example +```yaml +# Insert a header with a value derived from another header. +- insert: + name: x-auth-scheme + expression: 'split(.request.headers.authorization, " ")[0] ?? "none"' +``` + + +**Properties** + +|Name|Type|Description|Required| +|----|----|-----------|--------| +|**expression**|`string`||yes| + + +**Example** + +```yaml +algorithm: null + +``` + ### headers\.subgraphs: object,null @@ -852,6 +917,34 @@ Static value provided in the config. |**value**|`string`||yes| +  +**Option 2 (optional):** +A dynamic value computed by a VRL expression. + +This allows you to generate header values based on the incoming request, +subgraph name, and (for response rules) subgraph response headers. +The expression has access to a context object with `.request`, `.subgraph`, +and `.response` fields. + +For more information on the available functions and syntax, see the +[VRL documentation](https://vrl.dev/). + +### Example +```yaml +# Insert a header with a value derived from another header. +- insert: + name: x-auth-scheme + expression: 'split(.request.headers.authorization, " ")[0] ?? "none"' +``` + + +**Properties** + +|Name|Type|Description|Required| +|----|----|-----------|--------| +|**expression**|`string`||yes| + + ##### headers\.subgraphs\.additionalProperties\.response\[\]: array,null @@ -936,7 +1029,8 @@ For never-join headers, appends another occurrence (multiple lines). **Example** ```yaml -insert: {} +insert: + algorithm: null ``` @@ -1080,6 +1174,7 @@ Insert a header with a static value. |Name|Type|Description|Required| |----|----|-----------|--------| +|**algorithm**||How to merge values across multiple subgraph responses.
Default: `Last` (overwrite).
|no| |**name**|`string`|Header name to insert or overwrite (case-insensitive).
|yes|   @@ -1094,6 +1189,41 @@ Static value provided in the config. |**value**|`string`||yes| +  +**Option 2 (optional):** +A dynamic value computed by a VRL expression. + +This allows you to generate header values based on the incoming request, +subgraph name, and (for response rules) subgraph response headers. +The expression has access to a context object with `.request`, `.subgraph`, +and `.response` fields. + +For more information on the available functions and syntax, see the +[VRL documentation](https://vrl.dev/). + +### Example +```yaml +# Insert a header with a value derived from another header. +- insert: + name: x-auth-scheme + expression: 'split(.request.headers.authorization, " ")[0] ?? "none"' +``` + + +**Properties** + +|Name|Type|Description|Required| +|----|----|-----------|--------| +|**expression**|`string`||yes| + + +**Example** + +```yaml +algorithm: null + +``` + ## http: object diff --git a/lib/executor/Cargo.toml b/lib/executor/Cargo.toml index 768bc63a..832dfbfa 100644 --- a/lib/executor/Cargo.toml +++ b/lib/executor/Cargo.toml @@ -31,6 +31,7 @@ tokio = { workspace = true, features = ["sync"] } dashmap = { workspace = true } ahash = "0.8.12" regex-automata = "0.4.10" +vrl = { version = "0.27.0", features = ["compiler", "parser", "value", "diagnostic", "stdlib", "core"] } ntex-http = "0.1.15" hyper-tls = { version = "0.6.0", features = ["vendored"] } diff --git a/lib/executor/src/execution/error.rs b/lib/executor/src/execution/error.rs index 52b5d0bd..7ee290c5 100644 --- a/lib/executor/src/execution/error.rs +++ b/lib/executor/src/execution/error.rs @@ -1,13 +1,9 @@ -use crate::projection::error::ProjectionError; +use crate::{headers::errors::HeaderRuleRuntimeError, projection::error::ProjectionError}; #[derive(thiserror::Error, Debug, Clone)] pub enum PlanExecutionError { #[error("Projection faiure: {0}")] - ProjectionFailure(ProjectionError), -} - -impl From for PlanExecutionError { - fn from(error: ProjectionError) -> Self { - PlanExecutionError::ProjectionFailure(error) - } + ProjectionFailure(#[from] ProjectionError), + #[error(transparent)] + HeaderPropagation(#[from] HeaderRuleRuntimeError), } diff --git a/lib/executor/src/execution/plan.rs b/lib/executor/src/execution/plan.rs index 73832b05..723d5e52 100644 --- a/lib/executor/src/execution/plan.rs +++ b/lib/executor/src/execution/plan.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{borrow::Cow, collections::HashMap}; use bytes::{BufMut, Bytes}; use futures::{future::BoxFuture, stream::FuturesUnordered, StreamExt}; @@ -6,7 +6,7 @@ use hive_router_query_planner::planner::plan_nodes::{ ConditionNode, FetchNode, FetchRewrite, FlattenNode, FlattenNodePath, ParallelNode, PlanNode, QueryPlan, SequenceNode, }; -use http::HeaderMap; +use http::{HeaderMap, Method}; use ntex_http::HeaderMap as NtexHeaderMap; use serde::Deserialize; use sonic_rs::ValueRef; @@ -42,13 +42,26 @@ use crate::{ }, }; +pub struct OperationDetails<'a> { + pub name: Option, + pub query: Cow<'a, str>, + pub kind: &'a str, +} + +pub struct ClientRequestDetails<'a> { + pub method: Method, + pub url: http::Uri, + pub headers: &'a NtexHeaderMap, + pub operation: OperationDetails<'a>, +} + pub struct QueryPlanExecutionContext<'exec> { pub query_plan: &'exec QueryPlan, pub projection_plan: &'exec Vec, pub headers_plan: &'exec HeaderRulesPlan, pub variable_values: &'exec Option>, pub extensions: Option>, - pub upstream_headers: &'exec NtexHeaderMap, + pub client_request: ClientRequestDetails<'exec>, pub introspection_context: &'exec IntrospectionContext<'exec, 'static>, pub operation_type_name: &'exec str, pub executors: &'exec SubgraphExecutorMap, @@ -73,20 +86,20 @@ pub async fn execute_query_plan<'exec>( ctx.variable_values, ctx.executors, ctx.introspection_context.metadata, - // Deduplicate subgraph requests only if the operation type is a query - ctx.upstream_headers, + &ctx.client_request, ctx.headers_plan, + // Deduplicate subgraph requests only if the operation type is a query ctx.operation_type_name == "Query", ); if ctx.query_plan.node.is_some() { executor .execute(&mut exec_ctx, ctx.query_plan.node.as_ref()) - .await; + .await?; } let mut response_headers = HeaderMap::new(); - modify_client_response_headers(exec_ctx.response_headers_aggregator, &mut response_headers); + modify_client_response_headers(exec_ctx.response_headers_aggregator, &mut response_headers)?; let final_response = &exec_ctx.final_response; let body = project_by_operation( @@ -109,7 +122,7 @@ pub struct Executor<'exec> { variable_values: &'exec Option>, schema_metadata: &'exec SchemaMetadata, executors: &'exec SubgraphExecutorMap, - upstream_headers: &'exec NtexHeaderMap, + client_request: &'exec ClientRequestDetails<'exec>, headers_plan: &'exec HeaderRulesPlan, dedupe_subgraph_requests: bool, } @@ -203,7 +216,7 @@ impl<'exec> Executor<'exec> { variable_values: &'exec Option>, executors: &'exec SubgraphExecutorMap, schema_metadata: &'exec SchemaMetadata, - upstream_headers: &'exec NtexHeaderMap, + client_request: &'exec ClientRequestDetails<'exec>, headers_plan: &'exec HeaderRulesPlan, dedupe_subgraph_requests: bool, ) -> Self { @@ -211,44 +224,65 @@ impl<'exec> Executor<'exec> { variable_values, executors, schema_metadata, - upstream_headers, + client_request, headers_plan, dedupe_subgraph_requests, } } - pub async fn execute(&self, ctx: &mut ExecutionContext<'exec>, plan: Option<&PlanNode>) { + pub async fn execute( + &self, + ctx: &mut ExecutionContext<'exec>, + plan: Option<&PlanNode>, + ) -> Result<(), PlanExecutionError> { match plan { Some(PlanNode::Fetch(node)) => self.execute_fetch_wave(ctx, node).await, Some(PlanNode::Parallel(node)) => self.execute_parallel_wave(ctx, node).await, Some(PlanNode::Sequence(node)) => self.execute_sequence_wave(ctx, node).await, // Plans produced by our Query Planner can only start with: Fetch, Sequence or Parallel. // Any other node type at the root is not supported, do nothing - Some(_) => (), + Some(_) => Ok(()), // An empty plan is valid, just do nothing - None => (), + None => Ok(()), } } - async fn execute_fetch_wave(&self, ctx: &mut ExecutionContext<'exec>, node: &FetchNode) { + async fn execute_fetch_wave( + &self, + ctx: &mut ExecutionContext<'exec>, + node: &FetchNode, + ) -> Result<(), PlanExecutionError> { match self.execute_fetch_node(node, None).await { Ok(result) => self.process_job_result(ctx, result), - Err(err) => ctx.errors.push(GraphQLError { - message: err.to_string(), - locations: None, - path: None, - extensions: None, - }), + Err(err) => { + ctx.errors.push(GraphQLError { + message: err.to_string(), + locations: None, + path: None, + extensions: None, + }); + Ok(()) + } } } - async fn execute_sequence_wave(&self, ctx: &mut ExecutionContext<'exec>, node: &SequenceNode) { + async fn execute_sequence_wave( + &self, + ctx: &mut ExecutionContext<'exec>, + node: &SequenceNode, + ) -> Result<(), PlanExecutionError> { for child in &node.nodes { - Box::pin(self.execute_plan_node(ctx, child)).await; + Box::pin(self.execute_plan_node(ctx, child)).await?; } + + Ok(()) } - async fn execute_parallel_wave(&self, ctx: &mut ExecutionContext<'exec>, node: &ParallelNode) { + async fn execute_parallel_wave( + &self, + ctx: &mut ExecutionContext<'exec>, + node: &ParallelNode, + ) -> Result<(), PlanExecutionError> { let mut scope = ConcurrencyScope::new(); for child in &node.nodes { @@ -261,7 +295,7 @@ impl<'exec> Executor<'exec> { for result in results { match result { Ok(job) => { - self.process_job_result(ctx, job); + self.process_job_result(ctx, job)?; } Err(err) => ctx.errors.push(GraphQLError { message: err.to_string(), @@ -271,13 +305,19 @@ impl<'exec> Executor<'exec> { }), } } + + Ok(()) } - async fn execute_plan_node(&self, ctx: &mut ExecutionContext<'exec>, node: &PlanNode) { + async fn execute_plan_node( + &self, + ctx: &mut ExecutionContext<'exec>, + node: &PlanNode, + ) -> Result<(), PlanExecutionError> { match node { PlanNode::Fetch(fetch_node) => match self.execute_fetch_node(fetch_node, None).await { Ok(job) => { - self.process_job_result(ctx, job); + self.process_job_result(ctx, job)?; } Err(err) => ctx.errors.push(GraphQLError { message: err.to_string(), @@ -287,7 +327,7 @@ impl<'exec> Executor<'exec> { }), }, PlanNode::Parallel(parallel_node) => { - self.execute_parallel_wave(ctx, parallel_node).await; + self.execute_parallel_wave(ctx, parallel_node).await?; } PlanNode::Flatten(flatten_node) => { match self.prepare_flatten_data(&ctx.final_response, flatten_node) { @@ -302,7 +342,7 @@ impl<'exec> Executor<'exec> { .await { Ok(job) => { - self.process_job_result(ctx, job); + self.process_job_result(ctx, job)?; } Err(err) => { ctx.errors.push(GraphQLError { @@ -326,18 +366,20 @@ impl<'exec> Executor<'exec> { } } PlanNode::Sequence(sequence_node) => { - self.execute_sequence_wave(ctx, sequence_node).await; + self.execute_sequence_wave(ctx, sequence_node).await?; } PlanNode::Condition(condition_node) => { if let Some(node) = condition_node_by_variables(condition_node, self.variable_values) { - Box::pin(self.execute_plan_node(ctx, node)).await; + Box::pin(self.execute_plan_node(ctx, node)).await?; } } // An unsupported plan node was found, do nothing. _ => {} } + + Ok(()) } fn prepare_job_future<'wave>( @@ -412,15 +454,20 @@ impl<'exec> Executor<'exec> { Some((response.data, output_rewrites)) } - fn process_job_result(&self, ctx: &mut ExecutionContext<'exec>, job: ExecutionJob) { - match job { + fn process_job_result( + &self, + ctx: &mut ExecutionContext<'exec>, + job: ExecutionJob, + ) -> Result<(), PlanExecutionError> { + let _: () = match job { ExecutionJob::Fetch(job) => { apply_subgraph_response_headers( self.headers_plan, &job.subgraph_name, &job.response.headers, + self.client_request, &mut ctx.response_headers_aggregator, - ); + )?; if let Some((mut data, output_rewrites)) = self.process_subgraph_response(ctx, job.response.body, job.fetch_node_id) @@ -439,8 +486,9 @@ impl<'exec> Executor<'exec> { self.headers_plan, &job.subgraph_name, &job.response.headers, + self.client_request, &mut ctx.response_headers_aggregator, - ); + )?; if let Some((mut data, output_rewrites)) = self.process_subgraph_response(ctx, job.response.body, job.fetch_node_id) @@ -484,7 +532,8 @@ impl<'exec> Executor<'exec> { ExecutionJob::None => { // nothing to do } - } + }; + Ok(()) } fn prepare_flatten_data( @@ -599,9 +648,9 @@ impl<'exec> Executor<'exec> { modify_subgraph_request_headers( self.headers_plan, &node.service_name, - self.upstream_headers, + self.client_request, &mut headers_map, - ); + )?; Ok(ExecutionJob::Fetch(FetchJob { fetch_node_id: node.id, diff --git a/lib/executor/src/headers/compile.rs b/lib/executor/src/headers/compile.rs index 7474a5be..5b1b14a9 100644 --- a/lib/executor/src/headers/compile.rs +++ b/lib/executor/src/headers/compile.rs @@ -2,22 +2,53 @@ use crate::headers::{ errors::HeaderRuleCompileError, plan::{ HeaderAggregationStrategy, HeaderRulesPlan, RequestHeaderRule, RequestHeaderRules, - RequestInsertStatic, RequestPropagateNamed, RequestPropagateRegex, RequestRemoveNamed, - RequestRemoveRegex, ResponseHeaderRule, ResponseHeaderRules, ResponseInsertStatic, - ResponsePropagateNamed, ResponsePropagateRegex, ResponseRemoveNamed, ResponseRemoveRegex, + RequestInsertExpression, RequestInsertStatic, RequestPropagateNamed, RequestPropagateRegex, + RequestRemoveNamed, RequestRemoveRegex, ResponseHeaderRule, ResponseHeaderRules, + ResponseInsertExpression, ResponseInsertStatic, ResponsePropagateNamed, + ResponsePropagateRegex, ResponseRemoveNamed, ResponseRemoveRegex, }, }; use hive_router_config::headers as config; use http::HeaderName; use regex_automata::{meta, util::syntax::Config as SyntaxConfig}; +use vrl::{ + compiler::compile as vrl_compile, prelude::Function as VrlFunction, + stdlib::all as vrl_build_functions, +}; + +pub struct HeaderRuleCompilerContext { + vrl_functions: Vec>, +} + +impl Default for HeaderRuleCompilerContext { + fn default() -> Self { + Self::new() + } +} + +impl HeaderRuleCompilerContext { + pub fn new() -> Self { + Self { + vrl_functions: vrl_build_functions(), + } + } +} pub trait HeaderRuleCompiler { - fn compile(&self, actions: &mut A) -> Result<(), HeaderRuleCompileError>; + fn compile( + &self, + ctx: &HeaderRuleCompilerContext, + actions: &mut A, + ) -> Result<(), HeaderRuleCompileError>; } impl HeaderRuleCompiler> for config::RequestHeaderRule { - fn compile(&self, actions: &mut Vec) -> Result<(), HeaderRuleCompileError> { + fn compile( + &self, + ctx: &HeaderRuleCompilerContext, + actions: &mut Vec, + ) -> Result<(), HeaderRuleCompileError> { match self { config::RequestHeaderRule::Propagate(rule) => { let spec = materialize_match_spec( @@ -40,13 +71,27 @@ impl HeaderRuleCompiler> for config::RequestHeaderRule { })); } } - config::RequestHeaderRule::Insert(rule) => { - let config::InsertSource::Value { value } = &rule.source; - actions.push(RequestHeaderRule::InsertStatic(RequestInsertStatic { - name: build_header_name(&rule.name)?, - value: build_header_value(&rule.name, value)?, - })); - } + config::RequestHeaderRule::Insert(rule) => match &rule.source { + config::InsertSource::Value { value } => { + actions.push(RequestHeaderRule::InsertStatic(RequestInsertStatic { + name: build_header_name(&rule.name)?, + value: build_header_value(&rule.name, value)?, + })); + } + config::InsertSource::Expression { expression } => { + let compilation_result = + vrl_compile(expression, &ctx.vrl_functions).map_err(|e| { + HeaderRuleCompileError::new_expression_build(rule.name.clone(), e) + })?; + + actions.push(RequestHeaderRule::InsertExpression( + RequestInsertExpression { + name: build_header_name(&rule.name)?, + expression: Box::new(compilation_result.program), + }, + )); + } + }, config::RequestHeaderRule::Remove(rule) => { let spec = materialize_match_spec(&rule.spec, None, None)?; if !spec.header_names.is_empty() { @@ -67,14 +112,14 @@ impl HeaderRuleCompiler> for config::RequestHeaderRule { } impl HeaderRuleCompiler> for config::ResponseHeaderRule { - fn compile(&self, actions: &mut Vec) -> Result<(), HeaderRuleCompileError> { + fn compile( + &self, + ctx: &HeaderRuleCompilerContext, + actions: &mut Vec, + ) -> Result<(), HeaderRuleCompileError> { match self { config::ResponseHeaderRule::Propagate(rule) => { - let aggregation_strategy = match rule.algorithm { - config::AggregationAlgo::First => HeaderAggregationStrategy::First, - config::AggregationAlgo::Last => HeaderAggregationStrategy::Last, - config::AggregationAlgo::Append => HeaderAggregationStrategy::Append, - }; + let aggregation_strategy = rule.algorithm.into(); let spec = materialize_match_spec( &rule.spec, rule.rename.as_ref(), @@ -99,11 +144,35 @@ impl HeaderRuleCompiler> for config::ResponseHeaderRule } } config::ResponseHeaderRule::Insert(rule) => { - let config::InsertSource::Value { value } = &rule.source; - actions.push(ResponseHeaderRule::InsertStatic(ResponseInsertStatic { - name: build_header_name(&rule.name)?, - value: build_header_value(&rule.name, value)?, - })); + let aggregation_strategy = rule.algorithm.into(); + match &rule.source { + config::InsertSource::Value { value } => { + actions.push(ResponseHeaderRule::InsertStatic(ResponseInsertStatic { + name: build_header_name(&rule.name)?, + value: build_header_value(&rule.name, value)?, + strategy: aggregation_strategy, + })); + } + config::InsertSource::Expression { expression } => { + // NOTE: In case we ever need to improve performance and not pass the whole context + // to VRL expressions, we can use: + // - compilation_result.program.info().target_assignments + // - compilation_result.program.info().target_queries + // to determine what parts of the context are actually needed by the expression + let compilation_result = vrl_compile(expression, &ctx.vrl_functions) + .map_err(|e| { + HeaderRuleCompileError::new_expression_build(rule.name.clone(), e) + })?; + + actions.push(ResponseHeaderRule::InsertExpression( + ResponseInsertExpression { + name: build_header_name(&rule.name)?, + expression: Box::new(compilation_result.program), + strategy: aggregation_strategy, + }, + )); + } + } } config::ResponseHeaderRule::Remove(rule) => { let spec = materialize_match_spec(&rule.spec, None, None)?; @@ -127,18 +196,19 @@ impl HeaderRuleCompiler> for config::ResponseHeaderRule pub fn compile_headers_plan( cfg: &config::HeadersConfig, ) -> Result { + let ctx = HeaderRuleCompilerContext::new(); let mut request_plan = RequestHeaderRules::default(); let mut response_plan = ResponseHeaderRules::default(); if let Some(global_rules) = &cfg.all { - request_plan.global = compile_request_header_rules(global_rules)?; - response_plan.global = compile_response_header_rules(global_rules)?; + request_plan.global = compile_request_header_rules(&ctx, global_rules)?; + response_plan.global = compile_response_header_rules(&ctx, global_rules)?; } if let Some(subgraph_rules_map) = &cfg.subgraphs { for (subgraph_name, subgraph_rules) in subgraph_rules_map { - let request_actions = compile_request_header_rules(subgraph_rules)?; - let response_actions = compile_response_header_rules(subgraph_rules)?; + let request_actions = compile_request_header_rules(&ctx, subgraph_rules)?; + let response_actions = compile_response_header_rules(&ctx, subgraph_rules)?; request_plan .by_subgraph .insert(subgraph_name.clone(), request_actions); @@ -155,24 +225,26 @@ pub fn compile_headers_plan( } fn compile_request_header_rules( + ctx: &HeaderRuleCompilerContext, header_rules: &config::HeaderRules, ) -> Result, HeaderRuleCompileError> { let mut request_actions = Vec::new(); if let Some(request_rule_entries) = &header_rules.request { for request_rule in request_rule_entries { - request_rule.compile(&mut request_actions)?; + request_rule.compile(ctx, &mut request_actions)?; } } Ok(request_actions) } fn compile_response_header_rules( + ctx: &HeaderRuleCompilerContext, header_rules: &config::HeaderRules, ) -> Result, HeaderRuleCompileError> { let mut response_actions = Vec::new(); if let Some(response_rule_entries) = &header_rules.response { for response_rule in response_rule_entries { - response_rule.compile(&mut response_actions)?; + response_rule.compile(ctx, &mut response_actions)?; } } Ok(response_actions) @@ -259,13 +331,34 @@ fn build_regex_many(patterns: &[String]) -> Result, HeaderRu .map_err(|e| Box::new(e).into()) } +impl From for HeaderAggregationStrategy { + fn from(algo: config::AggregationAlgo) -> Self { + match algo { + config::AggregationAlgo::First => HeaderAggregationStrategy::First, + config::AggregationAlgo::Last => HeaderAggregationStrategy::Last, + config::AggregationAlgo::Append => HeaderAggregationStrategy::Append, + } + } +} + +impl From> for HeaderAggregationStrategy { + fn from(algo: Option) -> Self { + match algo { + Some(config::AggregationAlgo::First) => HeaderAggregationStrategy::First, + Some(config::AggregationAlgo::Last) => HeaderAggregationStrategy::Last, + Some(config::AggregationAlgo::Append) => HeaderAggregationStrategy::Append, + None => HeaderAggregationStrategy::Last, + } + } +} + #[cfg(test)] mod tests { use hive_router_config::headers as config; use http::HeaderName; use crate::headers::{ - compile::{build_header_value, HeaderRuleCompiler}, + compile::{build_header_value, HeaderRuleCompiler, HeaderRuleCompilerContext}, errors::HeaderRuleCompileError, plan::{HeaderAggregationStrategy, RequestHeaderRule, ResponseHeaderRule}, }; @@ -285,8 +378,9 @@ mod tests { rename: None, default: None, }); + let ctx = HeaderRuleCompilerContext::new(); let mut actions = Vec::new(); - rule.compile(&mut actions).unwrap(); + rule.compile(&ctx, &mut actions).unwrap(); assert_eq!(actions.len(), 1); match &actions[0] { RequestHeaderRule::PropagateNamed(data) => { @@ -300,14 +394,15 @@ mod tests { #[test] fn test_set_request() { - let rule = config::RequestHeaderRule::Insert(config::InsertRule { + let rule = config::RequestHeaderRule::Insert(config::RequestInsertRule { name: "x-set".to_string(), source: config::InsertSource::Value { value: "abc".to_string(), }, }); let mut actions = Vec::new(); - rule.compile(&mut actions).unwrap(); + let ctx = HeaderRuleCompilerContext::new(); + rule.compile(&ctx, &mut actions).unwrap(); assert_eq!(actions.len(), 1); match &actions[0] { RequestHeaderRule::InsertStatic(data) => { @@ -328,7 +423,8 @@ mod tests { }, }); let mut actions = Vec::new(); - rule.compile(&mut actions).unwrap(); + let ctx = HeaderRuleCompilerContext::new(); + rule.compile(&ctx, &mut actions).unwrap(); assert_eq!(actions.len(), 1); match &actions[0] { RequestHeaderRule::RemoveNamed(data) => { @@ -353,7 +449,8 @@ mod tests { default: Some("def".to_string()), }); let mut actions = Vec::new(); - let err = rule.compile(&mut actions).unwrap_err(); + let ctx = HeaderRuleCompilerContext::new(); + let err = rule.compile(&ctx, &mut actions).unwrap_err(); match err { HeaderRuleCompileError::InvalidDefault => {} _ => panic!("Expected InvalidDefault error"), @@ -373,7 +470,8 @@ mod tests { algorithm: config::AggregationAlgo::First, }); let mut actions = Vec::new(); - rule.compile(&mut actions).unwrap(); + let ctx = HeaderRuleCompilerContext::new(); + rule.compile(&ctx, &mut actions).unwrap(); assert_eq!(actions.len(), 1); match &actions[0] { ResponseHeaderRule::PropagateNamed(data) => { diff --git a/lib/executor/src/headers/errors.rs b/lib/executor/src/headers/errors.rs index 31ab324a..36d21287 100644 --- a/lib/executor/src/headers/errors.rs +++ b/lib/executor/src/headers/errors.rs @@ -1,5 +1,6 @@ use http::header::{InvalidHeaderName, InvalidHeaderValue}; use regex_automata::meta::BuildError; +use vrl::{diagnostic::DiagnosticList, prelude::ExpressionError}; #[derive(thiserror::Error, Debug)] pub enum HeaderRuleCompileError { @@ -13,4 +14,34 @@ pub enum HeaderRuleCompileError { InvalidDefault, #[error("Failed to build regex for header matching. Please check your regex patterns for syntax errors. Reason: {0}")] RegexBuild(#[from] Box), + #[error("Failed to compile VRL expression for header '{0}'. Please check your VRL expression for syntax errors. Diagnostic: {1}")] + ExpressionBuild(String, String), +} + +#[derive(thiserror::Error, Debug, Clone)] +pub enum HeaderRuleRuntimeError { + #[error("Failed to evaluate VRL expression for header '{0}'. Reason: {1}")] + ExpressionEvaluation(String, Box), + #[error("Invalid header value for header '{0}'.")] + BadHeaderValue(String), +} + +impl HeaderRuleCompileError { + pub fn new_expression_build(header_name: String, diagnostics: DiagnosticList) -> Self { + HeaderRuleCompileError::ExpressionBuild( + header_name, + diagnostics + .errors() + .into_iter() + .map(|d| d.message.clone()) + .collect::>() + .join(", "), + ) + } +} + +impl HeaderRuleRuntimeError { + pub fn new_expression_evaluation(header_name: String, error: Box) -> Self { + HeaderRuleRuntimeError::ExpressionEvaluation(header_name, error) + } } diff --git a/lib/executor/src/headers/expression.rs b/lib/executor/src/headers/expression.rs new file mode 100644 index 00000000..54186330 --- /dev/null +++ b/lib/executor/src/headers/expression.rs @@ -0,0 +1,147 @@ +use std::collections::BTreeMap; + +use bytes::Bytes; +use http::{HeaderMap, HeaderValue}; +use tracing::warn; +use vrl::core::Value; + +use crate::{ + execution::plan::ClientRequestDetails, + headers::{request::RequestExpressionContext, response::ResponseExpressionContext}, +}; + +fn warn_unsupported_conversion_option(type_name: &str) -> Option { + warn!( + "Cannot convert VRL {} value to a header value. Please convert it to a string first.", + type_name + ); + + None +} + +pub fn vrl_value_to_header_value(value: Value) -> Option { + match value { + Value::Bytes(bytes) => HeaderValue::from_bytes(&bytes).ok(), + Value::Float(f) => HeaderValue::from_str(&f.to_string()).ok(), + Value::Boolean(b) => HeaderValue::from_str(if b { "true" } else { "false" }).ok(), + Value::Integer(i) => HeaderValue::from_str(&i.to_string()).ok(), + Value::Array(_) => warn_unsupported_conversion_option("Array"), + Value::Regex(_) => warn_unsupported_conversion_option("Regex"), + Value::Timestamp(_) => warn_unsupported_conversion_option("Timestamp"), + Value::Object(_) => warn_unsupported_conversion_option("Object"), + Value::Null => { + warn!("Cannot convert VRL Null value to a header value."); + None + } + } +} + +fn header_map_to_vrl_value(headers: &HeaderMap) -> Value { + let mut obj = BTreeMap::new(); + for (header_name, header_value) in headers.iter() { + if let Ok(value) = header_value.to_str() { + obj.insert( + header_name.as_str().into(), + Value::Bytes(Bytes::from(value.to_owned())), + ); + } + } + Value::Object(obj) +} + +fn client_header_map_to_vrl_value(headers: &ntex_http::HeaderMap) -> Value { + let mut obj = BTreeMap::new(); + for (header_name, header_value) in headers.iter() { + if let Ok(value) = header_value.to_str() { + obj.insert( + header_name.as_str().into(), + Value::Bytes(Bytes::from(value.to_owned())), + ); + } + } + Value::Object(obj) +} + +impl From<&RequestExpressionContext<'_>> for Value { + /// NOTE: If performance becomes an issue, consider pre-computing parts of this context that do not change + fn from(ctx: &RequestExpressionContext) -> Self { + // .subgraph + let subgraph_value = { + let value = Self::Bytes(Bytes::from(ctx.subgraph_name.to_owned())); + Self::Object(BTreeMap::from([("name".into(), value)])) + }; + + // .request + let request_value: Self = ctx.client_request.into(); + + Self::Object(BTreeMap::from([ + ("subgraph".into(), subgraph_value), + ("request".into(), request_value), + ])) + } +} + +impl From<&ResponseExpressionContext<'_>> for Value { + /// NOTE: If performance becomes an issue, consider pre-computing parts of this context that do not change + fn from(ctx: &ResponseExpressionContext) -> Self { + // .subgraph + let subgraph_value = Self::Object(BTreeMap::from([( + "name".into(), + Self::Bytes(Bytes::from(ctx.subgraph_name.to_owned())), + )])); + // .response + let response_value = header_map_to_vrl_value(ctx.subgraph_headers); + // .request + let request_value: Self = ctx.client_request.into(); + + Self::Object(BTreeMap::from([ + ("subgraph".into(), subgraph_value), + ("response".into(), response_value), + ("request".into(), request_value), + ])) + } +} + +impl From<&ClientRequestDetails<'_>> for Value { + fn from(details: &ClientRequestDetails) -> Self { + // .request.headers + let headers_value = client_header_map_to_vrl_value(details.headers); + + // .request.url + let url_value = Self::Object(BTreeMap::from([ + ( + "host".into(), + details.url.host().unwrap_or("unknown").into(), + ), + ("path".into(), details.url.path().into()), + ( + "port".into(), + details + .url + .port_u16() + .unwrap_or_else(|| { + if details.url.scheme() == Some(&http::uri::Scheme::HTTPS) { + 443 + } else { + 80 + } + }) + .into(), + ), + ])); + + // .request.operation + let operation_value = Self::Object(BTreeMap::from([ + ("name".into(), details.operation.name.clone().into()), + ("type".into(), details.operation.kind.into()), + ("query".into(), details.operation.query.clone().into()), + ])); + + Self::Object(BTreeMap::from([ + ("method".into(), details.method.as_str().into()), + ("headers".into(), headers_value), + ("url".into(), url_value), + ("operation".into(), operation_value), + ])) + } +} diff --git a/lib/executor/src/headers/mod.rs b/lib/executor/src/headers/mod.rs index d8f9c610..8fe11876 100644 --- a/lib/executor/src/headers/mod.rs +++ b/lib/executor/src/headers/mod.rs @@ -1,5 +1,6 @@ pub mod compile; pub mod errors; +pub mod expression; pub mod plan; pub mod request; pub mod response; @@ -7,11 +8,14 @@ pub mod sanitizer; #[cfg(test)] mod tests { - use crate::headers::{ - compile::compile_headers_plan, - plan::ResponseHeaderAggregator, - request::modify_subgraph_request_headers, - response::{apply_subgraph_response_headers, modify_client_response_headers}, + use crate::{ + execution::plan::{ClientRequestDetails, OperationDetails}, + headers::{ + compile::compile_headers_plan, + plan::ResponseHeaderAggregator, + request::modify_subgraph_request_headers, + response::{apply_subgraph_response_headers, modify_client_response_headers}, + }, }; use hive_router_config::parse_yaml_config; use http::{HeaderMap, HeaderName, HeaderValue}; @@ -47,8 +51,19 @@ mod tests { header_value_owned("abc").into(), ); + let client_details = ClientRequestDetails { + method: http::Method::POST, + url: "http://example.com".parse().unwrap(), + headers: &client_headers, + operation: OperationDetails { + name: None, + query: "{ __typename }".to_string().into(), + kind: "query", + }, + }; + let mut out = HeaderMap::new(); - modify_subgraph_request_headers(&plan, "any", &client_headers, &mut out); + modify_subgraph_request_headers(&plan, "any", &client_details, &mut out).unwrap(); assert_eq!(out.get("x-renamed").unwrap(), &header_value_owned("abc")); assert_eq!(out.get("x-set").unwrap(), &header_value_owned("set-value")); @@ -67,8 +82,18 @@ mod tests { let config = parse_yaml_config(String::from(yaml_str)).unwrap(); let plan = compile_headers_plan(&config.headers).unwrap(); let client_headers = NtexHeaderMap::new(); + let client_details = ClientRequestDetails { + method: http::Method::POST, + url: "http://example.com".parse().unwrap(), + headers: &client_headers, + operation: OperationDetails { + name: None, + query: "{ __typename }".to_string().into(), + kind: "query", + }, + }; let mut out = HeaderMap::new(); - modify_subgraph_request_headers(&plan, "any", &client_headers, &mut out); + modify_subgraph_request_headers(&plan, "any", &client_details, &mut out).unwrap(); assert_eq!( out.get("x-missing").unwrap(), @@ -88,6 +113,17 @@ mod tests { "#; let config = parse_yaml_config(String::from(yaml_str)).unwrap(); let plan = compile_headers_plan(&config.headers).unwrap(); + let client_headers = NtexHeaderMap::new(); + let client_details = ClientRequestDetails { + method: http::Method::POST, + url: "http://example.com".parse().unwrap(), + headers: &client_headers, + operation: OperationDetails { + name: None, + query: "{ __typename }".to_string().into(), + kind: "query", + }, + }; let mut accumulator = ResponseHeaderAggregator::default(); @@ -96,7 +132,14 @@ mod tests { header_name_owned("x-resp"), header_value_owned("resp-value-1"), ); - apply_subgraph_response_headers(&plan, "any", &subgraph_headers, &mut accumulator); + apply_subgraph_response_headers( + &plan, + "any", + &subgraph_headers, + &client_details, + &mut accumulator, + ) + .unwrap(); let mut subgraph_headers = HeaderMap::new(); subgraph_headers.insert( @@ -104,10 +147,17 @@ mod tests { header_value_owned("resp-value-2"), ); - apply_subgraph_response_headers(&plan, "any", &subgraph_headers, &mut accumulator); + apply_subgraph_response_headers( + &plan, + "any", + &subgraph_headers, + &client_details, + &mut accumulator, + ) + .unwrap(); let mut final_headers = HeaderMap::new(); - modify_client_response_headers(accumulator, &mut final_headers); + modify_client_response_headers(accumulator, &mut final_headers).unwrap(); assert_eq!( final_headers.get("x-resp").unwrap(), @@ -130,14 +180,26 @@ mod tests { let plan = compile_headers_plan(&config.headers).unwrap(); let mut client_headers = NtexHeaderMap::new(); + client_headers.insert( header_name_owned("x-remove"), header_value_owned("bye").into(), ); client_headers.insert(header_name_owned("x-keep"), header_value_owned("hi").into()); + let client_details = ClientRequestDetails { + method: http::Method::POST, + url: "http://example.com".parse().unwrap(), + headers: &client_headers, + operation: OperationDetails { + name: None, + query: "{ __typename }".to_string().into(), + kind: "query", + }, + }; + let mut out = HeaderMap::new(); - modify_subgraph_request_headers(&plan, "any", &client_headers, &mut out); + modify_subgraph_request_headers(&plan, "any", &client_details, &mut out).unwrap(); assert!(out.get("x-remove").is_none()); assert_eq!(out.get("x-keep").unwrap(), &header_value_owned("hi")); diff --git a/lib/executor/src/headers/plan.rs b/lib/executor/src/headers/plan.rs index 3323ced1..a1a3cf99 100644 --- a/lib/executor/src/headers/plan.rs +++ b/lib/executor/src/headers/plan.rs @@ -1,6 +1,7 @@ use ahash::HashMap; use http::{HeaderName, HeaderValue}; use regex_automata::meta::Regex; +use vrl::compiler::Program as VrlProgram; #[derive(Clone)] pub struct HeaderRulesPlan { @@ -27,6 +28,7 @@ pub enum RequestHeaderRule { PropagateNamed(RequestPropagateNamed), PropagateRegex(RequestPropagateRegex), InsertStatic(RequestInsertStatic), + InsertExpression(RequestInsertExpression), RemoveNamed(RequestRemoveNamed), RemoveRegex(RequestRemoveRegex), } @@ -54,6 +56,20 @@ pub struct RequestInsertStatic { pub struct ResponseInsertStatic { pub name: HeaderName, pub value: HeaderValue, + pub strategy: HeaderAggregationStrategy, +} + +#[derive(Clone)] +pub struct RequestInsertExpression { + pub name: HeaderName, + pub expression: Box, +} + +#[derive(Clone)] +pub struct ResponseInsertExpression { + pub name: HeaderName, + pub expression: Box, + pub strategy: HeaderAggregationStrategy, } #[derive(Clone)] @@ -81,6 +97,7 @@ pub enum ResponseHeaderRule { PropagateNamed(ResponsePropagateNamed), PropagateRegex(ResponsePropagateRegex), InsertStatic(ResponseInsertStatic), + InsertExpression(ResponseInsertExpression), RemoveNamed(ResponseRemoveNamed), RemoveRegex(ResponseRemoveRegex), } diff --git a/lib/executor/src/headers/request.rs b/lib/executor/src/headers/request.rs index a7278c1a..ebc91244 100644 --- a/lib/executor/src/headers/request.rs +++ b/lib/executor/src/headers/request.rs @@ -1,51 +1,76 @@ +use std::collections::BTreeMap; + use http::HeaderMap; -use ntex_http::HeaderMap as NtexHeaderMap; +use vrl::{ + compiler::TargetValue as VrlTargetValue, + core::Value as VrlValue, + prelude::{state::RuntimeState as VrlState, Context as VrlContext, TimeZone as VrlTimeZone}, + value::Secrets as VrlSecrets, +}; -use crate::headers::{ - plan::{ - HeaderRulesPlan, RequestHeaderRule, RequestInsertStatic, RequestPropagateNamed, - RequestPropagateRegex, RequestRemoveNamed, RequestRemoveRegex, +use crate::{ + execution::plan::ClientRequestDetails, + headers::{ + errors::HeaderRuleRuntimeError, + expression::vrl_value_to_header_value, + plan::{ + HeaderRulesPlan, RequestHeaderRule, RequestInsertExpression, RequestInsertStatic, + RequestPropagateNamed, RequestPropagateRegex, RequestRemoveNamed, RequestRemoveRegex, + }, + sanitizer::{is_denied_header, is_never_join_header}, }, - sanitizer::{is_denied_header, is_never_join_header}, }; pub fn modify_subgraph_request_headers( header_rule_plan: &HeaderRulesPlan, subgraph_name: &str, - client_headers: &NtexHeaderMap, + client_request: &ClientRequestDetails, output_headers: &mut HeaderMap, -) { +) -> Result<(), HeaderRuleRuntimeError> { let global_actions = &header_rule_plan.request.global; let subgraph_actions = header_rule_plan.request.by_subgraph.get(subgraph_name); + let ctx = RequestExpressionContext { + subgraph_name, + client_request, + }; + for action in global_actions .iter() .chain(subgraph_actions.into_iter().flatten()) { - action.apply_request_headers(client_headers, output_headers); + action.apply_request_headers(&ctx, output_headers)?; } + + Ok(()) +} + +pub struct RequestExpressionContext<'a> { + pub subgraph_name: &'a str, + pub client_request: &'a ClientRequestDetails<'a>, } trait ApplyRequestHeader { - fn apply_request_headers(&self, client_headers: &NtexHeaderMap, output_headers: &mut HeaderMap); + fn apply_request_headers( + &self, + ctx: &RequestExpressionContext, + output_headers: &mut HeaderMap, + ) -> Result<(), HeaderRuleRuntimeError>; } impl ApplyRequestHeader for RequestHeaderRule { fn apply_request_headers( &self, - client_headers: &NtexHeaderMap, + ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { match self { - Self::PropagateNamed(data) => { - data.apply_request_headers(client_headers, output_headers) - } - Self::PropagateRegex(data) => { - data.apply_request_headers(client_headers, output_headers) - } - Self::InsertStatic(data) => data.apply_request_headers(client_headers, output_headers), - Self::RemoveNamed(data) => data.apply_request_headers(client_headers, output_headers), - Self::RemoveRegex(data) => data.apply_request_headers(client_headers, output_headers), + Self::PropagateNamed(data) => data.apply_request_headers(ctx, output_headers), + Self::PropagateRegex(data) => data.apply_request_headers(ctx, output_headers), + Self::InsertStatic(data) => data.apply_request_headers(ctx, output_headers), + Self::InsertExpression(data) => data.apply_request_headers(ctx, output_headers), + Self::RemoveNamed(data) => data.apply_request_headers(ctx, output_headers), + Self::RemoveRegex(data) => data.apply_request_headers(ctx, output_headers), } } } @@ -53,16 +78,16 @@ impl ApplyRequestHeader for RequestHeaderRule { impl ApplyRequestHeader for RequestPropagateNamed { fn apply_request_headers( &self, - client_headers: &NtexHeaderMap, + ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { let mut matched = false; for header_name in &self.names { if is_denied_header(header_name) { continue; } - if let Some(header_value) = client_headers.get(header_name) { + if let Some(header_value) = ctx.client_request.headers.get(header_name) { let destination_name = self.rename.as_ref().unwrap_or(header_name); output_headers.append(destination_name, header_value.into()); matched = true; @@ -75,22 +100,24 @@ impl ApplyRequestHeader for RequestPropagateNamed { let destination_name = self.rename.as_ref().unwrap_or(first_name); if is_denied_header(destination_name) { - return; + return Ok(()); } output_headers.append(destination_name, default_value.clone()); } } + + Ok(()) } } impl ApplyRequestHeader for RequestPropagateRegex { fn apply_request_headers( &self, - client_headers: &NtexHeaderMap, + ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { - for (header_name, header_value) in client_headers { + ) -> Result<(), HeaderRuleRuntimeError> { + for (header_name, header_value) in ctx.client_request.headers { if is_denied_header(header_name) { continue; } @@ -115,15 +142,17 @@ impl ApplyRequestHeader for RequestPropagateRegex { output_headers.append(header_name, header_value.into()); } + + Ok(()) } } impl ApplyRequestHeader for RequestInsertStatic { fn apply_request_headers( &self, - _client_headers: &NtexHeaderMap, + _ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { if !is_denied_header(&self.name) { if is_never_join_header(&self.name) { output_headers.append(self.name.clone(), self.value.clone()); @@ -131,30 +160,69 @@ impl ApplyRequestHeader for RequestInsertStatic { output_headers.insert(self.name.clone(), self.value.clone()); } } + + Ok(()) + } +} + +impl ApplyRequestHeader for RequestInsertExpression { + fn apply_request_headers( + &self, + ctx: &RequestExpressionContext, + output_headers: &mut HeaderMap, + ) -> Result<(), HeaderRuleRuntimeError> { + if is_denied_header(&self.name) { + return Ok(()); + } + + let mut target = VrlTargetValue { + value: ctx.into(), + metadata: VrlValue::Object(BTreeMap::new()), + secrets: VrlSecrets::default(), + }; + + let mut state = VrlState::default(); + let timezone = VrlTimeZone::default(); + let mut ctx = VrlContext::new(&mut target, &mut state, &timezone); + let value = self.expression.resolve(&mut ctx).map_err(|err| { + HeaderRuleRuntimeError::new_expression_evaluation(self.name.to_string(), Box::new(err)) + })?; + + if let Some(header_value) = vrl_value_to_header_value(value) { + if is_never_join_header(&self.name) { + output_headers.append(self.name.clone(), header_value); + } else { + output_headers.insert(self.name.clone(), header_value); + } + } + + Ok(()) } } impl ApplyRequestHeader for RequestRemoveNamed { fn apply_request_headers( &self, - _client_headers: &NtexHeaderMap, + _ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { for header_name in &self.names { if is_denied_header(header_name) { continue; } output_headers.remove(header_name); } + + Ok(()) } } impl ApplyRequestHeader for RequestRemoveRegex { fn apply_request_headers( &self, - _client_headers: &NtexHeaderMap, + _ctx: &RequestExpressionContext, output_headers: &mut HeaderMap, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { let mut headers_to_remove = Vec::new(); for header_name in output_headers.keys() { if is_denied_header(header_name) { @@ -169,5 +237,7 @@ impl ApplyRequestHeader for RequestRemoveRegex { for header_name in headers_to_remove.iter() { output_headers.remove(header_name); } + + Ok(()) } } diff --git a/lib/executor/src/headers/response.rs b/lib/executor/src/headers/response.rs index 5ee528ca..1de5ccdf 100644 --- a/lib/executor/src/headers/response.rs +++ b/lib/executor/src/headers/response.rs @@ -1,64 +1,88 @@ -use std::iter::once; - -use crate::headers::{ - plan::{ - HeaderAggregationStrategy, HeaderRulesPlan, ResponseHeaderAggregator, ResponseHeaderRule, - ResponseInsertStatic, ResponsePropagateNamed, ResponsePropagateRegex, ResponseRemoveNamed, - ResponseRemoveRegex, +use std::{collections::BTreeMap, iter::once}; + +use crate::{ + execution::plan::ClientRequestDetails, + headers::{ + errors::HeaderRuleRuntimeError, + expression::vrl_value_to_header_value, + plan::{ + HeaderAggregationStrategy, HeaderRulesPlan, ResponseHeaderAggregator, + ResponseHeaderRule, ResponseInsertExpression, ResponseInsertStatic, + ResponsePropagateNamed, ResponsePropagateRegex, ResponseRemoveNamed, + ResponseRemoveRegex, + }, + sanitizer::is_denied_header, }, - sanitizer::is_denied_header, }; use super::sanitizer::is_never_join_header; -use http::{HeaderMap, HeaderName, HeaderValue}; +use http::{header::InvalidHeaderValue, HeaderMap, HeaderName, HeaderValue}; +use vrl::{ + compiler::TargetValue as VrlTargetValue, + core::Value as VrlValue, + prelude::{state::RuntimeState as VrlState, Context as VrlContext, TimeZone as VrlTimeZone}, + value::Secrets as VrlSecrets, +}; pub fn apply_subgraph_response_headers( header_rule_plan: &HeaderRulesPlan, subgraph_name: &str, subgraph_headers: &HeaderMap, + client_request_details: &ClientRequestDetails, accumulator: &mut ResponseHeaderAggregator, -) { +) -> Result<(), HeaderRuleRuntimeError> { let global_actions = &header_rule_plan.response.global; let subgraph_actions = header_rule_plan.response.by_subgraph.get(subgraph_name); + let ctx = ResponseExpressionContext { + subgraph_name, + subgraph_headers, + client_request: client_request_details, + }; + for action in global_actions .iter() .chain(subgraph_actions.into_iter().flatten()) { - action.apply_response_headers(subgraph_headers, accumulator); + action.apply_response_headers(&ctx, accumulator)?; } + + Ok(()) +} + +pub struct ResponseExpressionContext<'a> { + pub subgraph_name: &'a str, + pub client_request: &'a ClientRequestDetails<'a>, + pub subgraph_headers: &'a HeaderMap, } trait ApplyResponseHeader { fn apply_response_headers( &self, - input_headers: &HeaderMap, + ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ); + ) -> Result<(), HeaderRuleRuntimeError>; } impl ApplyResponseHeader for ResponseHeaderRule { fn apply_response_headers( &self, - input_headers: &HeaderMap, + ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { match self { ResponseHeaderRule::PropagateNamed(data) => { - data.apply_response_headers(input_headers, accumulator) + data.apply_response_headers(ctx, accumulator) } ResponseHeaderRule::PropagateRegex(data) => { - data.apply_response_headers(input_headers, accumulator) + data.apply_response_headers(ctx, accumulator) } - ResponseHeaderRule::InsertStatic(data) => { - data.apply_response_headers(input_headers, accumulator) - } - ResponseHeaderRule::RemoveNamed(data) => { - data.apply_response_headers(input_headers, accumulator) - } - ResponseHeaderRule::RemoveRegex(data) => { - data.apply_response_headers(input_headers, accumulator) + ResponseHeaderRule::InsertStatic(data) => data.apply_response_headers(ctx, accumulator), + ResponseHeaderRule::InsertExpression(data) => { + data.apply_response_headers(ctx, accumulator) } + ResponseHeaderRule::RemoveNamed(data) => data.apply_response_headers(ctx, accumulator), + ResponseHeaderRule::RemoveRegex(data) => data.apply_response_headers(ctx, accumulator), } } } @@ -66,9 +90,9 @@ impl ApplyResponseHeader for ResponseHeaderRule { impl ApplyResponseHeader for ResponsePropagateNamed { fn apply_response_headers( &self, - input_headers: &HeaderMap, + ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { let mut matched = false; for header_name in &self.names { @@ -76,7 +100,7 @@ impl ApplyResponseHeader for ResponsePropagateNamed { continue; } - if let Some(header_value) = input_headers.get(header_name) { + if let Some(header_value) = ctx.subgraph_headers.get(header_name) { matched = true; write_agg( accumulator, @@ -92,22 +116,24 @@ impl ApplyResponseHeader for ResponsePropagateNamed { let destination_name = self.rename.as_ref().unwrap_or(first_name); if is_denied_header(destination_name) { - return; + return Ok(()); } write_agg(accumulator, destination_name, default_value, self.strategy); } } + + Ok(()) } } impl ApplyResponseHeader for ResponsePropagateRegex { fn apply_response_headers( &self, - input_headers: &HeaderMap, + ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { - for (header_name, header_value) in input_headers { + ) -> Result<(), HeaderRuleRuntimeError> { + for (header_name, header_value) in ctx.subgraph_headers { if is_denied_header(header_name) { continue; } @@ -132,50 +158,93 @@ impl ApplyResponseHeader for ResponsePropagateRegex { write_agg(accumulator, header_name, header_value, self.strategy); } + + Ok(()) } } impl ApplyResponseHeader for ResponseInsertStatic { fn apply_response_headers( &self, - _input_headers: &HeaderMap, + _ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { if is_denied_header(&self.name) { - return; + return Ok(()); } let strategy = if is_never_join_header(&self.name) { HeaderAggregationStrategy::Append } else { - HeaderAggregationStrategy::Last + self.strategy }; write_agg(accumulator, &self.name, &self.value, strategy); + + Ok(()) + } +} + +impl ApplyResponseHeader for ResponseInsertExpression { + fn apply_response_headers( + &self, + ctx: &ResponseExpressionContext, + accumulator: &mut ResponseHeaderAggregator, + ) -> Result<(), HeaderRuleRuntimeError> { + if is_denied_header(&self.name) { + return Ok(()); + } + + let mut target = VrlTargetValue { + value: ctx.into(), + metadata: VrlValue::Object(BTreeMap::new()), + secrets: VrlSecrets::default(), + }; + + let mut state = VrlState::default(); + let timezone = VrlTimeZone::default(); + let mut ctx = VrlContext::new(&mut target, &mut state, &timezone); + let value = self.expression.resolve(&mut ctx).map_err(|err| { + HeaderRuleRuntimeError::ExpressionEvaluation(self.name.to_string(), Box::new(err)) + })?; + + if let Some(header_value) = vrl_value_to_header_value(value) { + let strategy = if is_never_join_header(&self.name) { + HeaderAggregationStrategy::Append + } else { + self.strategy + }; + + write_agg(accumulator, &self.name, &header_value, strategy); + } + + Ok(()) } } impl ApplyResponseHeader for ResponseRemoveNamed { fn apply_response_headers( &self, - _input_headers: &HeaderMap, + _ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { for header_name in &self.names { if is_denied_header(header_name) { continue; } accumulator.entries.remove(header_name); } + + Ok(()) } } impl ApplyResponseHeader for ResponseRemoveRegex { fn apply_response_headers( &self, - _input_headers: &HeaderMap, + _ctx: &ResponseExpressionContext, accumulator: &mut ResponseHeaderAggregator, - ) { + ) -> Result<(), HeaderRuleRuntimeError> { accumulator.entries.retain(|name, _| { if is_denied_header(name) { // Denied headers (hop-by–hop) are never inserted in the first place @@ -185,6 +254,8 @@ impl ApplyResponseHeader for ResponseRemoveRegex { !self.regex.is_match(name.as_str().as_bytes()) }); + + Ok(()) } } @@ -226,7 +297,10 @@ fn write_agg( } /// Modify the outgoing client response headers based on the aggregated headers from subgraphs. -pub fn modify_client_response_headers(agg: ResponseHeaderAggregator, out: &mut HeaderMap) { +pub fn modify_client_response_headers( + agg: ResponseHeaderAggregator, + out: &mut HeaderMap, +) -> Result<(), HeaderRuleRuntimeError> { for (name, (agg_strategy, mut values)) in agg.entries { if values.is_empty() { continue; @@ -246,14 +320,17 @@ pub fn modify_client_response_headers(agg: ResponseHeaderAggregator, out: &mut H } if matches!(agg_strategy, HeaderAggregationStrategy::Append) { - let joined = join_with_comma(&values); + let joined = join_with_comma(&values) + .map_err(|_| HeaderRuleRuntimeError::BadHeaderValue(name.to_string()))?; out.insert(name, joined); } } + + Ok(()) } #[inline] -fn join_with_comma(values: &[HeaderValue]) -> HeaderValue { +fn join_with_comma(values: &[HeaderValue]) -> Result { // Compute capacity: sum of lengths + ", ".len() * (n-1) let mut cap = 0usize; @@ -272,5 +349,5 @@ fn join_with_comma(values: &[HeaderValue]) -> HeaderValue { } buf.extend_from_slice(value.as_bytes()); } - HeaderValue::from_bytes(&buf).unwrap_or_else(|_| HeaderValue::from_static("")) + HeaderValue::from_bytes(&buf) } diff --git a/lib/router-config/src/headers.rs b/lib/router-config/src/headers.rs index 1ecaef48..ff3bc574 100644 --- a/lib/router-config/src/headers.rs +++ b/lib/router-config/src/headers.rs @@ -117,7 +117,7 @@ pub enum RequestHeaderRule { /// - For **normal** headers: replaces any existing value. /// - For **never-join** headers (e.g. `set-cookie`): **appends** another /// occurrence (multiple lines), never comma-joins. - Insert(InsertRule), + Insert(RequestInsertRule), } /// Response-header rules (applied before sending back to the client). @@ -141,7 +141,7 @@ pub enum ResponseHeaderRule { /// Add or overwrite a header in the response to the client. /// /// For never-join headers, appends another occurrence (multiple lines). - Insert(InsertRule), + Insert(ResponseInsertRule), } /// Remove headers matched by the specification. @@ -167,7 +167,7 @@ pub struct RemoveRule { /// # If another Set-Cookie exists, this creates another header line (never joined) /// ``` #[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] -pub struct InsertRule { +pub struct RequestInsertRule { /// Header name to insert or overwrite (case-insensitive). pub name: HeaderName, /// Where the value comes from (currently static only). @@ -175,13 +175,58 @@ pub struct InsertRule { pub source: InsertSource, } +/// Insert a header with a static value. +/// +/// ### Examples +/// ```yaml +/// - insert: +/// name: x-env +/// value: prod +/// ``` +/// +/// ```yaml +/// - insert: +/// name: set-cookie +/// value: "a=1; Path=/" +/// # If another Set-Cookie exists, this creates another header line (never joined) +/// ``` +#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] +pub struct ResponseInsertRule { + /// Header name to insert or overwrite (case-insensitive). + pub name: HeaderName, + /// Where the value comes from (currently static only). + #[serde(flatten)] + pub source: InsertSource, + /// How to merge values across multiple subgraph responses. + /// Default: `Last` (overwrite). + #[serde(default)] + pub algorithm: Option, +} + /// Source for an inserted header value. #[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] #[serde(untagged)] pub enum InsertSource { /// Static value provided in the config. Value { value: String }, - // Expression { expression: String }, + /// A dynamic value computed by a VRL expression. + /// + /// This allows you to generate header values based on the incoming request, + /// subgraph name, and (for response rules) subgraph response headers. + /// The expression has access to a context object with `.request`, `.subgraph`, + /// and `.response` fields. + /// + /// For more information on the available functions and syntax, see the + /// [VRL documentation](https://vrl.dev/). + /// + /// ### Example + /// ```yaml + /// # Insert a header with a value derived from another header. + /// - insert: + /// name: x-auth-scheme + /// expression: 'split(.request.headers.authorization, " ")[0] ?? "none"' + /// ``` + Expression { expression: String }, } /// Helper to allow `one` or `many` values for ergonomics (OR semantics).