diff --git a/.gitignore b/.gitignore index 7916b98..098915a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ target/ node_modules/ .env test/cypress/screenshots + +**/Cargo.lock diff --git a/backend/index.js b/backend/index.js index 91330a6..6eef265 100644 --- a/backend/index.js +++ b/backend/index.js @@ -60,19 +60,20 @@ app.post("/test-endpoint", (req, res) => { }); app.post("/init-tunnel", (req, res) => { - console.log("Received request:", req.body); // Log the entire request body to the console as well + console.log("/init-tunnel Received request:", req.body); // Log the entire request body to the console as well if (!req.body) { return res.status(400).json({ error: "Invalid request payload" }); } - res.status(200).json({ data: "Tunnel established succesfully" }); + res.status(200).send(); }); app.post("/proxy", (req, res) => { - console.log("Received request:", req.body); // Log the entire request body to the console as well + console.log("/proxy Received request:", req.body); // Log the entire request body to the console as well if (!req.body) { return res.status(400).json({ error: "Invalid request payload" }); } - res.status(200).json({ data: "Tunnel established succesfully" }); + + res.set('be_response_header', 'added in BE').status(200).json({ be_response_body: "body added in Backend" }); }); app.use(expressWinston.errorLogger({ diff --git a/forward-proxy/Cargo.lock b/forward-proxy/Cargo.lock deleted file mode 100644 index e45e699..0000000 --- a/forward-proxy/Cargo.lock +++ /dev/null @@ -1,3406 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.3", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" -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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.59.0", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "aws-lc-rs" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.9.1", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.101", - "which", -] - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "brotli" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "cc" -version = "1.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive", - "clap_lex", - "indexmap 1.9.3", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "daemonize" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfdaacb3c887a54d41bdf48d3af8873b3f5566469f8ba21b92057509f116e" -dependencies = [ - "libc", -] - -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - -[[package]] -name = "deranged" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", -] - -[[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]] -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.101", -] - -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_filter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "flate2" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" -dependencies = [ - "crc32fast", - "libz-ng-sys", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -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 = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" -dependencies = [ - "equivalent", - "hashbrown 0.15.4", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jiff" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.172" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.0", -] - -[[package]] -name = "libz-ng-sys" -version = "1.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7118c2c2a3c7b6edc279a8b19507672b9c4d716f95e671172dfa4e23f9fd824" -dependencies = [ - "cmake", - "libc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "lru" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8cc7106155f10bdf99a6f379688f543ad6596a415375b36a59a054ceda1198" -dependencies = [ - "hashbrown 0.15.4", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[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.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - -[[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 = "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-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-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[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 = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pingora" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c9fc7098dc3e7d09d2d1647921005be9301cf68536826195dc5369e05124bd" -dependencies = [ - "pingora-core", - "pingora-http", - "pingora-timeout", -] - -[[package]] -name = "pingora-cache" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ee62f28526d8d484621e77f8d6a1807f1bd07558a06ab5a204b4834d6be056" -dependencies = [ - "ahash", - "async-trait", - "blake2", - "bytes", - "hex", - "http 1.3.1", - "httparse", - "httpdate", - "indexmap 1.9.3", - "log", - "lru", - "once_cell", - "parking_lot", - "pingora-core", - "pingora-error", - "pingora-header-serde", - "pingora-http", - "pingora-lru", - "pingora-timeout", - "regex", - "rmp", - "rmp-serde", - "rustracing", - "rustracing_jaeger", - "serde", - "strum", - "tokio", -] - -[[package]] -name = "pingora-core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d123320b69bd06e897fc16bd1dde962a7b488c4d2ae825683fbca0198fad8669" -dependencies = [ - "ahash", - "async-trait", - "brotli", - "bytes", - "chrono", - "clap", - "daemonize", - "flate2", - "futures", - "h2 0.4.10", - "http 1.3.1", - "httparse", - "httpdate", - "libc", - "log", - "lru", - "nix", - "once_cell", - "openssl-probe", - "parking_lot", - "percent-encoding", - "pingora-error", - "pingora-http", - "pingora-pool", - "pingora-runtime", - "pingora-timeout", - "prometheus", - "rand 0.8.5", - "regex", - "serde", - "serde_yaml", - "sfv", - "socket2", - "strum", - "strum_macros", - "thread_local", - "tokio", - "tokio-test", - "unicase", - "windows-sys 0.59.0", - "zstd", -] - -[[package]] -name = "pingora-error" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389511530152c535a554f592ae4a9691b1246cff20eb4564f2a34fc921195c0" - -[[package]] -name = "pingora-header-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb3f62d852da015e76ced56e93e6d52941679a9825281c90f2897841129e59d" -dependencies = [ - "bytes", - "http 1.3.1", - "httparse", - "pingora-error", - "pingora-http", - "thread_local", - "zstd", - "zstd-safe", -] - -[[package]] -name = "pingora-http" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70202f126056f366549afc804741e12dd9f419cfc79a0063ab15653007a0f4c6" -dependencies = [ - "bytes", - "http 1.3.1", - "pingora-error", -] - -[[package]] -name = "pingora-lru" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb50f65f06c4b81ccb3edcceaa54bb9439608506b0b3b8c048798169a64aad8e" -dependencies = [ - "arrayvec", - "hashbrown 0.15.4", - "parking_lot", - "rand 0.9.1", -] - -[[package]] -name = "pingora-pool" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bacdd5dbdec690d468856d988b170c8bb4ab62e0edefc0f432ba5e326489f421" -dependencies = [ - "crossbeam-queue", - "log", - "lru", - "parking_lot", - "pingora-timeout", - "thread_local", - "tokio", -] - -[[package]] -name = "pingora-proxy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5031783d6743bd31e4de7d7c7a19e9eecf369174c3cbd8a57eb52bc6bf882d92" -dependencies = [ - "async-trait", - "bytes", - "clap", - "futures", - "h2 0.4.10", - "http 1.3.1", - "log", - "once_cell", - "pingora-cache", - "pingora-core", - "pingora-error", - "pingora-http", - "pingora-timeout", - "regex", - "tokio", -] - -[[package]] -name = "pingora-runtime" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a7c445ca224630961045684201e3cf8da9af0b01f286ed54ff8b2403aaabff" -dependencies = [ - "once_cell", - "rand 0.8.5", - "thread_local", - "tokio", -] - -[[package]] -name = "pingora-timeout" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685bb8808cc1919c63a06ab14fdac9b84a4887ced49259a5c0adc8bfb2ffe558" -dependencies = [ - "once_cell", - "parking_lot", - "pin-project-lite", - "thread_local", - "tokio", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" -dependencies = [ - "zerovec", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" -dependencies = [ - "proc-macro2", - "syn 2.0.101", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prometheus" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot", - "protobuf", - "thiserror 1.0.69", -] - -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - -[[package]] -name = "proxy" -version = "0.1.0" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "clap", - "dotenv", - "env_logger", - "jsonwebtoken", - "log", - "pingora", - "pingora-core", - "pingora-error", - "pingora-http", - "pingora-proxy", - "reqwest", - "serde", - "serde_json", - "serde_yaml", - "simplelog", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "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]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "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]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "redox_syscall" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[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 = "rmp" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - -[[package]] -name = "rust_decimal" -version = "1.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" -dependencies = [ - "arrayvec", - "num-traits", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.23.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustracing" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44822b10c095e574869de2b891e40c724fef42cadaea040d1cd3bdbb13d36a5" -dependencies = [ - "backtrace", - "crossbeam-channel", - "rand 0.8.5", - "trackable 0.2.24", -] - -[[package]] -name = "rustracing_jaeger" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6c2fe9411ef5f43ac773f0e84ad735804c55719346a7aad52de2d9162db97c8" -dependencies = [ - "crossbeam-channel", - "hostname", - "percent-encoding", - "rand 0.8.5", - "rustracing", - "thrift_codec", - "trackable 0.2.24", -] - -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.1", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sfv" -version = "0.9.4" -source = "git+https://github.com/undef1nd/sfv.git?tag=v0.9.4#e6499d8ce11271dd0a4c1f72445775a58b835a56" -dependencies = [ - "data-encoding", - "indexmap 2.9.0", - "rust_decimal", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" -dependencies = [ - "libc", -] - -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.12", - "time", -] - -[[package]] -name = "simplelog" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85d04ae642154220ef00ee82c36fb07853c10a4f2a0ca6719f9991211d2eb959" -dependencies = [ - "chrono", - "log", - "termcolor", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.101", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[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.101", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.7", - "windows-sys 0.59.0", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "thrift_codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb61fb3d0a0af14949f3a6949b2639112e13226647112824f4d081533f9b1a8" -dependencies = [ - "byteorder", - "trackable 0.2.24", -] - -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-test" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" -dependencies = [ - "async-stream", - "bytes", - "futures-core", - "tokio", - "tokio-stream", -] - -[[package]] -name = "tokio-util" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", -] - -[[package]] -name = "trackable" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98abb9e7300b9ac902cc04920945a874c1973e08c310627cc4458c04b70dd32" -dependencies = [ - "trackable 1.3.0", - "trackable_derive", -] - -[[package]] -name = "trackable" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15bd114abb99ef8cee977e517c8f37aee63f184f2d08e3e6ceca092373369ae" -dependencies = [ - "trackable_derive", -] - -[[package]] -name = "trackable_derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[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 = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.101", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "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]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[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 = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[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.101", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[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.101", - "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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" -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.101", -] - -[[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.15+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/forward-proxy/Cargo.toml b/forward-proxy/Cargo.toml index 52736db..6c1f409 100644 --- a/forward-proxy/Cargo.toml +++ b/forward-proxy/Cargo.toml @@ -4,26 +4,23 @@ version = "0.1.0" edition = "2024" [dependencies] -async-trait="0.1" +async-trait = "0.1" bytes = "1.10.1" clap = { version = "3.2.25", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" -serde_yaml = "0.8.26" -env_logger = "0.11.7" log = "0.4.27" chrono = "0.4.40" reqwest = { version = "0.11", features = ["json"] } -tokio-rustls = "0.26.2" -tokio = "1.44.2" +tokio = { version = "1.44.2", features = ["rt-multi-thread", "macros"] } simplelog = "0.10" -pingora-core = "0.4.0" -pingora-proxy = "0.4.0" -pingora-http = "0.4.0" -pingora = "0.4.0" +pingora = { version = "0.4.0", features = ["lb"] } jsonwebtoken = "9.3.1" dotenv = "0.15.0" -pingora-error = "0.4.0" +futures = "0.3.31" +pingora-router = { path = "../pingora-router" } +once_cell = "1.21.3" +utils = { path = "../utils" } [patch.crates-io] sfv = { git = "https://github.com/undef1nd/sfv.git", tag = "v0.9.4" } diff --git a/forward-proxy/src/handler/consts.rs b/forward-proxy/src/handler/consts.rs new file mode 100644 index 0000000..f20766c --- /dev/null +++ b/forward-proxy/src/handler/consts.rs @@ -0,0 +1,36 @@ +use once_cell::sync::Lazy; + +// can be replaced by constants, will see +pub enum ForwardHeaderKeys { + FpHeaderRequestKey, + FpHeaderResponseKey, +} + +impl ForwardHeaderKeys { + pub fn as_str(&self) -> &'static str { + match self { + ForwardHeaderKeys::FpHeaderRequestKey => "fp_request_header", + ForwardHeaderKeys::FpHeaderResponseKey => "fp_response_header" + } + } + + pub fn placeholder_value(&self) -> &'static str { + match self { + ForwardHeaderKeys::FpHeaderRequestKey => "added in ForwardProxy", + ForwardHeaderKeys::FpHeaderResponseKey => "added in ForwardProxy" + } + } +} + +const LAYER8_URL: &str = "http://127.0.0.1:5001"; +const RP_URL: &str = "http://127.0.0.1:6194"; + +pub static RP_INIT_ENCRYPTED_TUNNEL_PATH: Lazy = Lazy::new(|| format!("{}/init-tunnel", RP_URL)); +pub static RP_PROXY_PATH: Lazy = Lazy::new(|| format!("{}/proxy", RP_URL)); +pub static LAYER8_GET_CERTIFICATE_PATH: Lazy = Lazy::new(|| format!("{}/sp-pub-key?backend_url=", LAYER8_URL)); + +pub const NTOR_SERVER_ID: &str = "ReverseProxyServer"; +pub const NTOR_STATIC_PUBLIC_KEY: [u8; 32] = [ + 131, 210, 36, 101, 39, 191, 61, 165, 29, 112, 94, 149, 120, 202, 189, 170, + 151, 62, 247, 71, 208, 255, 144, 173, 52, 223, 239, 221, 153, 225, 40, 10 +]; \ No newline at end of file diff --git a/forward-proxy/src/handler/helpers.rs b/forward-proxy/src/handler/helpers.rs new file mode 100644 index 0000000..1df5dd9 --- /dev/null +++ b/forward-proxy/src/handler/helpers.rs @@ -0,0 +1,28 @@ +use serde::Serialize; +use chrono::Utc; +use jsonwebtoken::{encode, EncodingKey, Header}; + +// Get SECRET_KEY from environment variable +pub fn get_secret_key() -> String { + std::env::var("JWT_SECRET_KEY").expect("JWT_SECRET_KEY must be set") +} + +#[derive(Serialize)] +struct Claims { + exp: usize, +} + +pub fn generate_standard_token(secret_key: &str) -> pingora::Result> { + let now = Utc::now(); + let claims = Claims { + exp: (now + chrono::Duration::days(1)).timestamp() as usize, + }; + + let token = encode( + &Header::new(jsonwebtoken::Algorithm::HS256), + &claims, + &EncodingKey::from_secret(secret_key.as_bytes()), + )?; + + Ok(token) +} diff --git a/forward-proxy/src/handler/mod.rs b/forward-proxy/src/handler/mod.rs new file mode 100644 index 0000000..1189785 --- /dev/null +++ b/forward-proxy/src/handler/mod.rs @@ -0,0 +1,383 @@ +use log::{debug, error, info}; +use pingora::http::StatusCode; +use reqwest::{Client, Response}; +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use pingora_router::handler::{APIHandlerResponse, DefaultHandlerTrait, RequestBodyTrait}; +use crate::handler::types::response::{ErrorResponse, FpHealthcheckError, FpHealthcheckSuccess, InitTunnelResponseFromRP, InitTunnelResponseToINT, ProxyResponse}; +use pingora_router::handler::ResponseBodyTrait; +use reqwest::header::HeaderMap; +use crate::handler::consts::ForwardHeaderKeys::{FpHeaderRequestKey, FpHeaderResponseKey}; +use crate::handler::consts::{LAYER8_GET_CERTIFICATE_PATH, NTOR_SERVER_ID, NTOR_STATIC_PUBLIC_KEY, RP_INIT_ENCRYPTED_TUNNEL_PATH, RP_PROXY_PATH}; +use crate::handler::types::request::{InitTunnelRequest, ProxyRequest}; +use utils; + +pub mod types; +mod helpers; +mod consts; + +pub struct ForwardHandler { + // add later +} + +impl DefaultHandlerTrait for ForwardHandler {} + +struct NTorServerCertificate { + server_id: String, + public_key: Vec, +} + +impl ForwardHandler { + async fn get_public_key( + &self, + backend_url: String, + ctx: &mut Layer8Context + ) -> Result + { + let secret_key = helpers::get_secret_key(); + let token = self::helpers::generate_standard_token(&secret_key).unwrap(); + let client = Client::new(); + + return match client + .get(format!("{}{}", LAYER8_GET_CERTIFICATE_PATH.as_str(), backend_url)) + .header("Authorization", format!("Bearer {}", token)) + .send() + .await + { + Ok(res) => { + if !res.status().is_success() { + let response_body = ErrorResponse { + error: format!("Failed to get public key from layer8, status code: {}", res.status().as_u16()), + }; + info!("Sending error response: {:?}", response_body); + + ctx.insert_response_header("Connection", "close"); // Ensure connection closes??? + + Err(APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body: Some(response_body.to_bytes()), + }) + } else { + // todo extract public key from response + Ok(NTorServerCertificate { + server_id: "".to_string(), + public_key: vec![], + }) + } + } + Err(e) => { + let response_body = ErrorResponse { + error: format!("Failed to connect to layer8: {}", e) + }; + + Err(APIHandlerResponse { + status: StatusCode::INTERNAL_SERVER_ERROR, + body: Some(response_body.to_bytes()), + }) + } + }; + } + + /// Add response headers to `ctx` to respond to Interceptor: + /// - *Copy* ReverseProxy's response header in `headers` + /// - *Add* custom ForwardProxy's response headers `custom_header` + fn create_response_headers( + headers: HeaderMap, + ctx: &mut Layer8Context, + custom_header: &str + ) { + for (key, val) in headers.iter() { + if let (k, Ok(v)) = (key.to_string(), val.to_str()) { + ctx.insert_response_header(k.as_str(), v); + } + } + + ctx.insert_response_header( + FpHeaderResponseKey.as_str(), + custom_header + ) + } + + /// Create request header to send/forward to ReverseProxy: + /// - *Copy* origin request headers from Interceptor `ctx` + /// - *Add* custom ForwardProxy's request headers `custom_header` + /// - *Set* universal Content-Type and Content-Length + fn create_forward_request_headers( + ctx: &mut Layer8Context, + custom_header: &str, + content_length: usize + ) -> HeaderMap { + // copy all origin header to new request + let origin_headers = ctx.get_request_header().clone(); + let mut reqwest_header = ::utils::to_reqwest_header(origin_headers); + + // add forward proxy header `fp_request_header` + reqwest_header.insert( + FpHeaderRequestKey.as_str(), + custom_header.parse().unwrap(), + ); + + reqwest_header.insert("Content-Length", content_length.to_string().parse().unwrap()); + reqwest_header.insert("Content-Type", "application/json".parse().unwrap()); + + reqwest_header + } + + /// forward manipulated `init-encrypted-tunnel` request to ReverseProxy and handle success response + async fn init_tunnel_forward_to_rp( + ctx: &mut Layer8Context, + headers: HeaderMap, + body: Vec, + ntor_server_certificate: NTorServerCertificate + ) -> APIHandlerResponse + { + let body_string = utils::bytes_to_string(&body); + let log_meta = format!("[FORWARD {}]", RP_INIT_ENCRYPTED_TUNNEL_PATH.as_str()); + info!("{log_meta} request headers to RP: {:?}", headers); + info!("{log_meta} request body to RP: {:?}", body_string); + + let client = Client::new(); + let response = client.post(RP_INIT_ENCRYPTED_TUNNEL_PATH.as_str()) + .headers(headers) + .body(body_string) + .send() + .await; + + match response { + Ok(res) if res.status().is_success() => { + let headers = res.headers().clone(); + let rp_response_body = res.bytes().await.unwrap_or_default(); + info!("{log_meta} response headers from RP: {:?}", headers); + info!("{log_meta} response body from RP: {}", utils::bytes_to_string(&rp_response_body.to_vec())); + + return match utils::bytes_to_json::(rp_response_body.to_vec()) { + Err(e) => { + error!("Error parsing RP response: {:?}", e); + APIHandlerResponse { + status: StatusCode::INTERNAL_SERVER_ERROR, + body: None, + } + } + Ok(res_from_rp) => { + // forward ReverseProxy's headers + ForwardHandler::create_response_headers(headers, ctx, FpHeaderResponseKey.placeholder_value()); + + let res_to_int = InitTunnelResponseToINT { + ephemeral_public_key: res_from_rp.public_key, + t_b_hash: res_from_rp.t_b_hash, + session_id: res_from_rp.session_id, + static_public_key: ntor_server_certificate.public_key, + server_id: ntor_server_certificate.server_id, + }; + + APIHandlerResponse { + status: StatusCode::OK, + body: Some(res_to_int.to_bytes()), + } + } + }; + } + _ => {} + }; + + ForwardHandler::handle_failed_forward_response(log_meta, response).await + } + + /// handle failed forward requests (to ReverseProxy) + async fn handle_failed_forward_response( + log_meta: String, + response: Result + ) -> APIHandlerResponse { + match response { + Ok(res) => { + // Handle 4xx/5xx errors + let status = res.status(); + error!("{log_meta} RP Response: {:?}", res); + + let error_body = match res.content_length() { + None => "internal-server-error".to_string(), + Some(_) => { + res.text().await.unwrap_or_else(|_e| "".to_string()) + } + }; + + let response_bytes = ErrorResponse { + error: error_body + }.to_bytes(); + + APIHandlerResponse { + status: StatusCode::try_from(status.as_u16()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR), + body: Some(response_bytes), + } + } + Err(e) => { + error!("Failed to forward request to RP: {}", e); + + let response_body_bytes = ErrorResponse { + error: e.to_string(), + }.to_bytes(); + + APIHandlerResponse { + status: StatusCode::INTERNAL_SERVER_ERROR, + body: Some(response_body_bytes), + } + } + } + } + + pub async fn handle_init_encrypted_tunnel(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + // validate request body + let received_body = match ForwardHandler::parse_request_body::< + InitTunnelRequest, + ErrorResponse + >(&ctx.get_request_body()) + { + Ok(res) => res.to_bytes(), + Err(err) => { + let body = match err { + None => None, + Some(e) => Some(e.to_bytes()) + }; + + return APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body, + }; + } + }; + + // get public key to initialize encrypted tunnel + let backend_url = match ctx.param("backend_url") { + Some(url) => url.clone(), + None => "".to_string() + }; + + //todo handle result_certificate + let _result_certificate = self.get_public_key(backend_url.to_string(), ctx).await; + // println!("public_key: {:?}", result_public_key); + let ntor_server_certificate = NTorServerCertificate { // hardcoded for now + server_id: NTOR_SERVER_ID.to_string(), + public_key: NTOR_STATIC_PUBLIC_KEY.to_vec(), + }; + + // copy origin headers and add ForwardProxy header + let new_headers = ForwardHandler::create_forward_request_headers( + ctx, + FpHeaderRequestKey.placeholder_value(), + received_body.len() + ); + + // forward origin request body + ForwardHandler::init_tunnel_forward_to_rp( + ctx, + new_headers, + received_body, + ntor_server_certificate + ).await + } + + /// forward manipulated `proxy` request to ReverseProxy and handle success response + async fn proxy_forward_to_rp( + ctx: &mut Layer8Context, + headers: HeaderMap, + body: Vec, + ) -> APIHandlerResponse + { + let body_string = ::utils::bytes_to_string(&body); + let log_meta = format!("[FORWARD {}]", RP_PROXY_PATH.as_str()); + debug!("{log_meta} request headers to RP: {:?}", headers); + debug!("{log_meta} request body to RP: {}", body_string); + + let client = Client::new(); + let response = client + .post(RP_PROXY_PATH.as_str()) + .headers(headers) + .body(body_string) + .send() + .await; + + match response { + Ok(res) if res.status().is_success() => { + let headers = res.headers().clone(); + let rp_response_bytes = res.bytes().await.unwrap_or_default(); + debug!("{log_meta} response headers from RP: {:?}", headers); + debug!("{log_meta} response body from RP: {}", utils::bytes_to_string(&rp_response_bytes.to_vec())); + + // validate reverse proxy's response body format, is it necessary? + match ::utils::bytes_to_json::(rp_response_bytes.to_vec()) { + Err(err) => { + error!("Reverse Proxy's response mismatch: {:}", err); + return APIHandlerResponse { + status: StatusCode::INTERNAL_SERVER_ERROR, + body: None, + }; + } + Ok(_) => {} + } + + // forward ReverseProxy's headers + ForwardHandler::create_response_headers(headers, ctx, FpHeaderResponseKey.placeholder_value()); + + return APIHandlerResponse { + status: StatusCode::OK, + body: Some(rp_response_bytes.to_vec()), // forward ReverseProxy's response + }; + } + _ => {} + }; + + ForwardHandler::handle_failed_forward_response(log_meta, response).await + } + + pub async fn handle_proxy(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + // validate request body + let received_body = match ForwardHandler:: + parse_request_body::(&ctx.get_request_body()) + { + Ok(body) => body.to_bytes(), + Err(err) => { + let body = match err { + None => None, + Some(body) => Some(body.to_bytes()) + }; + + return APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body, + }; + } + }; + + let new_headers = ForwardHandler::create_forward_request_headers( + ctx, FpHeaderRequestKey.placeholder_value(), received_body.len()); + + // send new request to ReverseProxy + ForwardHandler::proxy_forward_to_rp(ctx, new_headers, received_body).await + } + + pub async fn handle_healthcheck(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + let error = ctx.param("error").unwrap(); + + if error == "true" { + let response_bytes = FpHealthcheckError { + fp_healthcheck_error: "this is placeholder for a custom error".to_string() + }.to_bytes(); + + ctx.insert_response_header("x-fp-healthcheck-error", "response-header-error"); + return APIHandlerResponse { + status: StatusCode::IM_A_TEAPOT, + body: Some(response_bytes), + }; + } + + let response_bytes = FpHealthcheckSuccess { + fp_healthcheck_success: "this is placeholder for a custom body".to_string(), + }.to_bytes(); + + ctx.insert_response_header("x-fp-healthcheck-success", "response-header-success"); + + return APIHandlerResponse { + status: StatusCode::OK, + body: Some(response_bytes), + }; + } +} \ No newline at end of file diff --git a/forward-proxy/src/handler/types/mod.rs b/forward-proxy/src/handler/types/mod.rs new file mode 100644 index 0000000..0ec9b86 --- /dev/null +++ b/forward-proxy/src/handler/types/mod.rs @@ -0,0 +1,2 @@ +pub mod response; +pub mod request; diff --git a/forward-proxy/src/handler/types/request.rs b/forward-proxy/src/handler/types/request.rs new file mode 100644 index 0000000..a0977f7 --- /dev/null +++ b/forward-proxy/src/handler/types/request.rs @@ -0,0 +1,17 @@ +use serde::{Deserialize, Serialize}; +use pingora_router::handler::RequestBodyTrait; + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitTunnelRequest { + pub public_key: Vec, +} + +impl RequestBodyTrait for InitTunnelRequest {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyRequest { + pub int_request_body: String, + pub spa_request_body: String, +} + +impl RequestBodyTrait for ProxyRequest {} \ No newline at end of file diff --git a/forward-proxy/src/handler/types/response.rs b/forward-proxy/src/handler/types/response.rs new file mode 100644 index 0000000..d879571 --- /dev/null +++ b/forward-proxy/src/handler/types/response.rs @@ -0,0 +1,58 @@ +use serde::{Deserialize, Serialize}; +use pingora_router::handler::ResponseBodyTrait; +use serde_json::Error; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ErrorResponse { + pub(crate) error: String, +} + +impl ResponseBodyTrait for ErrorResponse { + fn from_json_err(err: Error) -> Option { + Some(ErrorResponse { + error: err.to_string() + }) + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitTunnelResponseFromRP { // this struct should match ReverseProxy's Response + pub public_key: Vec, + pub t_b_hash: Vec, + pub session_id: String, +} + +impl ResponseBodyTrait for InitTunnelResponseFromRP {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitTunnelResponseToINT { // this struct should match Interceptor's expected Response + pub ephemeral_public_key: Vec, + pub t_b_hash: Vec, + pub session_id: String, + pub static_public_key: Vec, + pub server_id: String +} + +impl ResponseBodyTrait for InitTunnelResponseToINT {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyResponse { + pub be_response_body: String, + pub rp_response_body: String, +} + +impl ResponseBodyTrait for ProxyResponse {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct FpHealthcheckSuccess { + pub(crate) fp_healthcheck_success: String, +} + +impl ResponseBodyTrait for FpHealthcheckSuccess {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct FpHealthcheckError { + pub(crate) fp_healthcheck_error: String, +} + +impl ResponseBodyTrait for FpHealthcheckError {} diff --git a/forward-proxy/src/main.rs b/forward-proxy/src/main.rs index d008955..2dcafbc 100644 --- a/forward-proxy/src/main.rs +++ b/forward-proxy/src/main.rs @@ -1,419 +1,50 @@ -use async_trait::async_trait; -use chrono::Utc; -use jsonwebtoken::{EncodingKey, Header, encode}; -use log::{error, info}; -use pingora_core::prelude::*; -use pingora_error::Result; -use pingora_proxy::{ProxyHttp, Session}; -use reqwest::Client; -use serde::{Deserialize, Serialize}; -use simplelog::{ConfigBuilder, LevelFilter, WriteLogger}; -use std::fs; - -const LAYER8_URL: &str = "http://127.0.0.1:5001"; -const RP_URL: &str = "http://127.0.0.1:6193"; -struct ForwardProxy; - -// Get SECRET_KEY from environment variable -fn get_secret_key() -> String { - std::env::var("JWT_SECRET_KEY").expect("JWT_SECRET_KEY must be set") -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ResponseBody { - data: String, -} - -#[derive(Serialize)] -struct Claims { - exp: usize, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpRequestBodyInit { - fp_request_body_init: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpResponseBodyInit { - fp_response_body_init: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpRequestBodyProxied { - fp_request_body_proxied: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpResponseBodyProxied { - fp_response_body_proxied: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpHealthcheckSuccess { - fp_healthcheck_success: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpHealthcheckError { - fp_healthcheck_error: String, -} - -#[async_trait] -impl ProxyHttp for ForwardProxy { - type CTX = (); - - fn new_ctx(&self) -> Self::CTX {} - - async fn upstream_peer( - &self, - _session: &mut Session, - _ctx: &mut Self::CTX, - ) -> Result> { - Ok(Box::from(HttpPeer::new( - String::from("127.0.0.1:6193"), - false, - String::from(""), - ))) - } - - async fn request_filter(&self, session: &mut Session, _ctx: &mut Self::CTX) -> Result - where - Self::CTX: Send + Sync, - { - let request_url = session.req_header().uri.to_string(); - let mut body = Vec::new(); - loop { - match session.read_request_body().await? { - Some(chunk) => body.extend_from_slice(&chunk), - None => break, - } - } - - let body_string = String::from_utf8_lossy(&body).to_string(); - - if request_url.contains("init-tunnel") { - let query_params = session.req_header().uri.query(); - let params: Vec<&str> = query_params.unwrap().split("=").collect(); - let backend_url = params.get(1).unwrap(); - let secret_key = get_secret_key(); - let token = generate_standard_token(&secret_key).unwrap(); - let client = Client::new(); - - let res = match client - .get(format!( - "{}{}?backend_url={}", - LAYER8_URL, "/sp-pub-key", backend_url - )) - .header("Authorization", format!("Bearer {}", token)) - .send() - .await - { - Ok(res) => res, - Err(e) => { - let response_body = serde_json::json!({ - "error": format!("Failed to connect to layer8: {}", e) - }); - - let mut header = pingora_http::ResponseHeader::build(500, None)?; - header.insert_header("Content-Type", "application/json")?; - - // Single response with headers and body - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body( - Some(bytes::Bytes::from(response_body.to_string())), - true, - ) - .await?; - return Ok(true); - } - }; - - if !res.status().is_success() { - let response_body = serde_json::json!({ - "error": format!("Failed to get public key from layer8, status code: {}", res.status().as_u16()) - }); - info!("Sending error response: {}", response_body); - - let mut header = pingora_http::ResponseHeader::build( - res.status().as_u16().try_into().unwrap_or(400), - None, - )?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("Connection", "close")?; // Ensure connection closes - header.insert_header("Content-Length", response_body.to_string().len())?; - // Single response with headers and body - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body(Some(bytes::Bytes::from(response_body.to_string())), true) - .await?; - return Ok(true); - } +mod proxy; +mod handler; - let client = Client::new(); - let response = client - .post(format!("{}/init-tunnel", RP_URL)) - .header( - "x-fp-request-header-init", - "request-header-forward-proxy-init", - ) - .header("Content-Type", "application/json") - .body(body_string.clone()) - .send() - .await; - - match response { - Ok(res) if res.status().is_success() => { - let response_body = res.text().await.unwrap_or_default(); - let mut header = pingora_http::ResponseHeader::build(200, None)?; - header.insert_header( - "x-fp-response-header-init", - "response-header-forward-proxy-init", - )?; - header.insert_header("Content-Type", "application/json")?; - // header.insert_header("Content-Length", response_body.to_string().len())?; - header.insert_header("Content-Length", 2048)?; - - let response_json = FpResponseBodyInit { - fp_response_body_init: response_body.clone(), - }; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body( - Some(bytes::Bytes::from( - serde_json::to_string(&response_json).unwrap(), - )), - true, - ) - .await?; - return Ok(true); - } - Ok(res) => { - // Handle 4xx/5xx errors - let status = res.status(); - let error_body = res.text().await.unwrap_or_default(); - - let mut header = pingora_http::ResponseHeader::build(status.as_u16(), None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("Content-Length", error_body.to_string().len())?; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body(Some(bytes::Bytes::from(error_body)), true) - .await?; - return Ok(true); - } - Err(e) => { - error!("Failed to forward request to RP: {}", e); - let mut header = pingora_http::ResponseHeader::build(500, None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("Content-Length", e.to_string().len())?; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body( - Some(bytes::Bytes::from( - serde_json::json!({ - "error": format!("Failed to forward request: {}", e) - }) - .to_string(), - )), - true, - ) - .await?; - return Ok(true); - } - } - } else if request_url.contains("proxy") { - // Handle proxy endpoint - let client = Client::new(); - // let request_body = FpRequestBodyProxied { - // fp_request_body_proxied: body_string.clone(), - // }; - - let response = client - .post(format!("{}/proxy", RP_URL)) - .header( - "x-fp-request-header-proxied", - "request-header-forward-proxied", - ) - // .json(&request_body) - .body(body_string.clone()) - .send() - .await; - - match response { - Ok(res) if res.status().is_success() => { - let headers = res.headers().clone(); - let response_body = res.text().await.unwrap_or_default(); - - let mut header = pingora_http::ResponseHeader::build(200, None)?; - header.insert_header( - "x-fp-response-header-proxied", - "response-header-forward-proxied", - )?; - - if let Some(rp_header) = headers.get("x-rp-response-header-proxied") { - header.insert_header( - "x-rp-response-header-proxied", - rp_header.to_str().unwrap_or(""), - )?; - } - - header.insert_header("Content-Type", "application/json")?; - // header.insert_header("Content-Length", response_body.to_string().len())?; - header.insert_header("Content-Length", 2048)?; - - let response_json = FpResponseBodyProxied { - fp_response_body_proxied: response_body.clone(), - }; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body( - Some(bytes::Bytes::from( - serde_json::to_string(&response_json).unwrap(), - )), - true, - ) - .await?; - return Ok(true); - } - Ok(res) => { - // Handle 4xx/5xx errors - let status = res.status(); - let error_body = res.text().await.unwrap_or_default(); - - let mut header = pingora_http::ResponseHeader::build(status.as_u16(), None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("Content-Length", error_body.to_string().len())?; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body(Some(bytes::Bytes::from(error_body)), true) - .await?; - return Ok(true); - } - Err(e) => { - error!("Failed to proxy request: {}", e); - let mut header = pingora_http::ResponseHeader::build(500, None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("Content-Length", e.to_string().len())?; - - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body( - Some(bytes::Bytes::from( - serde_json::json!({ - "error": format!("Failed to proxy request: {}", e) - }) - .to_string(), - )), - true, - ) - .await?; - return Ok(true); - } - } - } else if request_url.contains("healthcheck") { - let query_params = session.req_header().uri.query(); - let params: Vec<&str> = query_params.unwrap().split("=").collect(); - let error = params.get(1).unwrap(); - if *error == "true" { - let mut header = pingora_http::ResponseHeader::build(418, None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("x-fp-healthcheck-error", "response-header-error")?; - let response_body = serde_json::json!({ - "fp_healthcheck_error": "this is placeholder for a custom error" - }); - header.insert_header("Content-Length", response_body.to_string().len())?; - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body(Some(bytes::Bytes::from(response_body.to_string())), true) - .await?; - return Ok(true); - } - let mut header = pingora_http::ResponseHeader::build(200, None)?; - header.insert_header("Content-Type", "application/json")?; - header.insert_header("x-fp-healthcheck-success", "response-header-success")?; - let response_body = serde_json::json!({ - "fp_healthcheck_success": "this is placeholder for a custom body" - }); - header.insert_header("Content-Length", response_body.to_string().len())?; - session - .write_response_header(Box::new(header), false) - .await?; - session - .write_response_body(Some(bytes::Bytes::from(response_body.to_string())), true) - .await?; - return Ok(true); - } - - Ok(false) - } - - async fn response_filter( - &self, - _session: &mut Session, - upstream_response: &mut pingora_http::ResponseHeader, - _ctx: &mut Self::CTX, - ) -> Result<()> { - upstream_response.insert_header("Access-Control-Allow-Origin", "*")?; - upstream_response.insert_header("Access-Control-Allow-Methods", "GET, POST")?; - upstream_response.insert_header("Access-Control-Allow-Headers", "Content-Type")?; - Ok(()) - } -} - -fn generate_standard_token(secret_key: &str) -> Result> { - let now = Utc::now(); - let claims = Claims { - exp: (now + chrono::Duration::days(1)).timestamp() as usize, - }; - - let token = encode( - &Header::new(jsonwebtoken::Algorithm::HS256), - &claims, - &EncodingKey::from_secret(secret_key.as_bytes()), - )?; - - Ok(token) -} +use pingora::prelude::*; +use simplelog::{ConfigBuilder, LevelFilter, WriteLogger}; +use std::sync::Arc; +use futures::FutureExt; +use log::info; +use proxy::ForwardProxy; +use crate::handler::ForwardHandler; +use pingora_router::handler::{APIHandler}; +use pingora_router::router::Router; fn main() { // Load environment variables from .env file dotenv::dotenv().ok(); - // Initialize logger - let log_file = fs::File::create("log.txt").expect("Failed to create log file"); let config = ConfigBuilder::new().set_time_to_local(true).build(); - WriteLogger::init(LevelFilter::Debug, config, log_file).expect("Failed to initialize logger"); + // Initialize logger + // let log_file = fs::File::create("log.txt").expect("Failed to create log file"); + // WriteLogger::init(LevelFilter::Debug, config, log_file).expect("Failed to initialize logger"); + WriteLogger::init(LevelFilter::Debug, config, std::io::stdout()).expect("Failed to initialize logger"); info!("Starting server..."); let mut server = Server::new(None).unwrap(); server.bootstrap(); - let mut proxy = pingora_proxy::http_proxy_service(&server.configuration, ForwardProxy); + let fp_handler = Arc::new(ForwardHandler{}); + let mut router: Router> = Router::new(fp_handler.clone()); + + let handle_init_tunnel: APIHandler> = Box::new(|h, ctx| { + async move { h.handle_init_encrypted_tunnel(ctx).await }.boxed() + }); + + let handle_proxy: APIHandler> = Box::new(|h, ctx| { + async move { h.handle_proxy(ctx).await }.boxed() + }); + + let handle_healthcheck: APIHandler> = Box::new(|h, ctx| { + async move { h.handle_healthcheck(ctx).await }.boxed() + }); + + router.post("/init-tunnel?backend_url={}".to_string(), Box::new([handle_init_tunnel])); + router.post("/proxy".to_string(), Box::new([handle_proxy])); + router.get("/healthcheck?error={}".to_string(), Box::new([handle_healthcheck])); + + let mut proxy = http_proxy_service(&server.configuration, ForwardProxy::new(router)); proxy.add_tcp("0.0.0.0:6191"); diff --git a/forward-proxy/src/old.rs b/forward-proxy/src/old.rs deleted file mode 100644 index 356804e..0000000 --- a/forward-proxy/src/old.rs +++ /dev/null @@ -1,351 +0,0 @@ - -use async_trait::async_trait; -use bytes::Bytes; -use chrono::Utc; -use jsonwebtoken::{EncodingKey, Header, encode}; -use log::info; -use pingora_core::prelude::*; -use pingora_error::{ErrorType, Result}; -use pingora_proxy::{ProxyHttp, Session}; -use reqwest::Client; -use serde::{Deserialize, Serialize}; -use simplelog::{ConfigBuilder, LevelFilter, WriteLogger}; -use std::collections::HashMap; -use std::fs; -use tokio::time::Duration; - -const LAYER8_URL: &str = "http://127.0.0.1:5001"; -const RP_URL: &str = "http://127.0.0.1:6193"; -const RP_PORT: u16 = 6193; - - -struct ForwardProxy; - -fn get_secret_key() -> String { - std::env::var("JWT_SECRET_KEY").expect("JWT_SECRET_KEY must be set") -} - -#[derive(Serialize, Deserialize, Debug)] -struct ResponseBody { - data: String, -} - -#[derive(Serialize)] -struct Claims { - exp: usize, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpRequestBodyInit { - fp_request_body_init: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpResponseBodyInit { - fp_response_body_init: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpRequestBodyProxied { - fp_request_body_proxied: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpResponseBodyProxied { - fp_response_body_proxied: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpHealthcheckSuccess { - fp_healthcheck_success: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct FpHealthcheckError { - fp_healthcheck_error: String, -} - -#[async_trait] -impl ProxyHttp for ForwardProxy { - type CTX = (); - - fn new_ctx(&self) -> Self::CTX {} - - async fn upstream_peer( - &self, - _session: &mut Session, - _ctx: &mut Self::CTX, - ) -> Result> { - Ok(Box::from(HttpPeer::new( - String::from("127.0.0.1:6193"), - false, - String::from(""), - ))) - } - - async fn request_filter(&self, session: &mut Session, _ctx: &mut Self::CTX) -> Result { - let path = session.req_header().uri.path(); - - // Handle /init-tunnel endpoint - if path == "/init-tunnel" { - let query_params = session.req_header().uri.query(); - let params: Vec<&str> = query_params.unwrap().split("=").collect(); - let backend_url = params.get(1).unwrap(); - let secret_key = get_secret_key(); - let token = generate_standard_token(&secret_key).unwrap(); - let client = Client::builder().timeout(Duration::from_secs(2)).build().unwrap(); - - let res = client - .get(format!( - "{}{}?backend_url={}", - LAYER8_URL, "/sp-pub-key", backend_url - )) - .header("Authorization", format!("Bearer {}", token)) - .send() - .await - .unwrap(); - - if res.status().as_u16() != 200 { - return Err(pingora_core::Error::explain( - ErrorType::ConnectProxyFailure, - format!( - "Failed to get public key from layer8, status code: {}", - res.status().as_u16() - ), - )); - } - - // Copy the body - let mut old_request_body = Vec::new(); - while let Some(chunk) = session.read_request_body().await? { - old_request_body.extend_from_slice(&chunk); - } - let body_str = String::from_utf8_lossy(&old_request_body).to_string(); - - // Build new request - let new_body = FpRequestBodyInit { - fp_request_body_init: body_str, - }; - - let client = Client::new(); - let res = client - .post(format!("{}/init-tunnel", RP_URL)) - .header( - "x-fp-request-header-init", - "request-header-forward-proxy-init", - ) - .json(&new_body) - .send() - .await - .unwrap(); - - if !res.status().is_success() { - return Err(pingora_core::Error::explain( - ErrorType::ConnectProxyFailure, - format!("RP returned error status: {}", res.status().as_u16()), - )); - } - - // Get response body from RP - let response_body = res.text().await.unwrap(); - - // Modify response to client - let mut response = pingora_http::ResponseHeader::build(200, None)?; - response.insert_header( - "x-fp-response-header-init", - "response-header-forward-proxy-init", - )?; - session - .write_response_header(Box::new(response), true) - .await?; - - let response_body_json = FpResponseBodyInit { - fp_response_body_init: response_body, - }; - let response_body_json_str = serde_json::to_string(&response_body_json).unwrap(); - let response_body_json_bytes = - Bytes::copy_from_slice(response_body_json_str.as_bytes()); - session - .write_response_body(Some(response_body_json_bytes), true) - .await?; - session.finish_body().await?; - - return Ok(true); - - } - - // Handle /proxy endpoint - if path == "/proxy" { - // Copy the body - let old_request_body = session.read_request_body().await?.unwrap(); - let body_str = String::from_utf8_lossy(&old_request_body).to_string(); - - // Build new request - let new_body = FpRequestBodyProxied { - fp_request_body_proxied: body_str, - }; - - let client = Client::new(); - let res = client - .post(format!("{}/proxy", RP_URL)) - .header( - "x-fp-request-header-proxied", - "request-header-forward-proxied", - ) - .json(&new_body) - .send() - .await - .unwrap(); - - if !res.status().is_success() { - return Err(pingora_core::Error::explain( - ErrorType::ConnectProxyFailure, - format!("RP returned error status: {}", res.status().as_u16()), - )); - } - - // Get response headers and body from RP - let response_headers = res.headers().clone(); - let response_body = res.text().await.unwrap(); - - // Modify response to client - let mut response = pingora_http::ResponseHeader::build(200, None)?; - response.insert_header( - "x-fp-response-header-proxied", - "response-header-forward-proxied", - )?; - - if let Some(rp_header) = response_headers.get("x-rp-response-header-proxied") { - response - .insert_header("x-rp-response-header-proxied", rp_header.to_str().unwrap())?; - } - - session - .write_response_header(Box::new(response), false) - .await?; - - let response_body_json = FpResponseBodyProxied { - fp_response_body_proxied: response_body, - }; - let response_body_json_str = serde_json::to_string(&response_body_json).unwrap(); - let response_body_json_bytes = - Bytes::copy_from_slice(response_body_json_str.as_bytes()); - session - .write_response_body(Some(response_body_json_bytes), true) - .await?; - - return Ok(true); - } - - // Handle /healthcheck endpoint - - if path == "/healthcheck" { - let query_params: HashMap<_, _> = session - .req_header() - .uri - .query() - .map(|q| { - q.split('&') - .filter_map(|p| { - let mut kv = p.splitn(2, '='); - match (kv.next(), kv.next()) { - (Some(k), Some(v)) => Some((k.to_string(), v.to_string())), - _ => None, - } - }) - .collect() - }) - .unwrap_or_default(); - - let error_param = query_params - .get("error") - .map(|s| s.as_str()) - .unwrap_or("false"); - - if error_param == "true" { - let mut response = pingora_http::ResponseHeader::build(418, None)?; - response.insert_header("x-fp-healthcheck-error", "response-header-error")?; - session - .write_response_header(Box::new(response), false) - .await?; - - let response_body = FpHealthcheckError { - fp_healthcheck_error: "this is placeholder for a custom error".to_string(), - }; - let response_body_json_str = serde_json::to_string(&response_body).unwrap(); - let response_body_json_bytes = - Bytes::copy_from_slice(response_body_json_str.as_bytes()); - session - .write_response_body(Some(response_body_json_bytes), true) - .await?; - } else { - let mut response = pingora_http::ResponseHeader::build(200, None)?; - response.insert_header("x-fp-healthcheck-success", "response-header-success")?; - session - .write_response_header(Box::new(response), false) - .await?; - - let response_body = FpHealthcheckSuccess { - fp_healthcheck_success: "this is placeholder for a custom body".to_string(), - }; - let response_body_json_str = serde_json::to_string(&response_body).unwrap(); - let response_body_json_bytes = - Bytes::copy_from_slice(response_body_json_str.as_bytes()); - session - .write_response_body(Some(response_body_json_bytes), true) - .await?; - } - - return Ok(true); - } - - Ok(false) - } - - async fn response_filter( - &self, - _session: &mut Session, - upstream_response: &mut pingora_http::ResponseHeader, - _ctx: &mut Self::CTX, - ) -> Result<()> { - upstream_response.insert_header("Access-Control-Allow-Origin", "*")?; - upstream_response.insert_header("Access-Control-Allow-Methods", "GET, POST")?; - upstream_response.insert_header("Access-Control-Allow-Headers", "Content-Type")?; - Ok(()) - } -} - -fn generate_standard_token(secret_key: &str) -> Result> { - let now = Utc::now(); - let claims = Claims { - exp: (now + chrono::Duration::days(1)).timestamp() as usize, - }; - - let token = encode( - &Header::new(jsonwebtoken::Algorithm::HS256), - &claims, - &EncodingKey::from_secret(secret_key.as_bytes()), - )?; - - Ok(token) -} - -fn main() { - dotenv::dotenv().ok(); - let log_file = fs::File::create("log.txt").expect("Failed to create log file"); - let config = ConfigBuilder::new().set_time_to_local(true).build(); - WriteLogger::init(LevelFilter::Debug, config, log_file).expect("Failed to initialize logger"); - - info!("Starting server..."); - - let mut server = Server::new(None).unwrap(); - server.bootstrap(); - - let mut proxy = pingora_proxy::http_proxy_service(&server.configuration, ForwardProxy); - - proxy.add_tcp("0.0.0.0:6191"); - - server.add_service(proxy); - - server.run_forever(); -} diff --git a/forward-proxy/src/proxy.rs b/forward-proxy/src/proxy.rs new file mode 100644 index 0000000..b8a028f --- /dev/null +++ b/forward-proxy/src/proxy.rs @@ -0,0 +1,94 @@ +use async_trait::async_trait; +use bytes::Bytes; +use log::{info}; +use pingora::prelude::{HttpPeer, ProxyHttp, Session}; +use pingora::http::{ResponseHeader, StatusCode}; +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use pingora_router::router::Router; + +pub struct ForwardProxy { + router: Router, +} + +impl ForwardProxy { + pub fn new(router: Router) -> Self { + ForwardProxy { + router + } + } +} + +#[async_trait] +impl ProxyHttp for ForwardProxy { + type CTX = Layer8Context; + + fn new_ctx(&self) -> Self::CTX { + Layer8Context::default() + } + + async fn upstream_peer( + &self, + _session: &mut Session, + _ctx: &mut Self::CTX, + ) -> pingora::Result> { + Ok(Box::from(HttpPeer::new( + String::from("127.0.0.1:6193"), + false, + String::from(""), + ))) + } + + async fn request_filter(&self, session: &mut Session, ctx: &mut Self::CTX) -> pingora::Result + where + Self::CTX: Send + Sync, + { + // create Context + ctx.update(session).await?; + let request_summary = format!("{} {}", session.req_header().method, session.req_header().uri.to_string()); + println!(); + info!("[REQUEST {}] {:?}", request_summary, ctx.request); + info!("[REQUEST {}] Decoded body: {}", request_summary, String::from_utf8_lossy(&*ctx.get_request_body())); + println!(); + + let handler_response = self.router.call_handler(ctx).await; + if handler_response.status == StatusCode::NOT_FOUND && handler_response.body == None { + return Ok(false) + } + + // set headers + let mut header = ResponseHeader::build(handler_response.status, None)?; + let response_header = ctx.get_response_header().clone(); + for (key, val) in response_header.iter() { + header.insert_header(key.clone(), val.clone()).unwrap(); + }; + + let mut response_bytes = vec![]; + if let Some(body_bytes) = handler_response.body { + header.insert_header("Content-length", &body_bytes.len().to_string()).unwrap(); + response_bytes = body_bytes; + }; + + session.write_response_header_ref(&header).await?; + + println!(); + info!("[RESPONSE {}] Header: {:?}", request_summary, header.headers); + info!("[RESPONSE {}] Body: {}", request_summary, String::from_utf8_lossy(&*response_bytes)); + println!(); + + // Write the response body to the session after setting headers + session.write_response_body(Some(Bytes::from(response_bytes)), true).await?; + Ok(true) + } + + async fn response_filter( + &self, + _session: &mut Session, + upstream_response: &mut ResponseHeader, + _ctx: &mut Self::CTX, + ) -> pingora::Result<()> { + upstream_response.insert_header("Access-Control-Allow-Origin", "*")?; + upstream_response.insert_header("Access-Control-Allow-Methods", "GET, POST")?; + upstream_response.insert_header("Access-Control-Allow-Headers", "Content-Type")?; + Ok(()) + } +} diff --git a/pingora-router/Cargo.toml b/pingora-router/Cargo.toml new file mode 100644 index 0000000..8464408 --- /dev/null +++ b/pingora-router/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "pingora-router" +version = "0.1.0" +edition = "2024" + +[dependencies] +#pingora = { git = "https://github.com/dtpthao/pingora.git", tag = "0.4.1", features = [ "lb" ] } +log = "0.4.27" +futures = "0.3.31" +pingora = { version = "0.4.0", features = ["lb"] } +serde = "1.0.219" +serde_json = "1.0.140" + +[patch.crates-io] +sfv = { git = "https://github.com/undef1nd/sfv.git", tag = "v0.9.4" } \ No newline at end of file diff --git a/pingora-router/src/ctx.rs b/pingora-router/src/ctx.rs new file mode 100644 index 0000000..b3e622c --- /dev/null +++ b/pingora-router/src/ctx.rs @@ -0,0 +1,197 @@ +use std::collections::HashMap; +use pingora::http::{Method, RequestHeader}; +use pingora::proxy::Session; +use crate::utils::get_request_body; + +/* + * Each type in this crate serves a specific purpose and may be updated as requirements evolve. + */ + +/// `Layer8ContextRequestSummary` is expected to contain all request's metadata +#[derive(Debug, Clone, Default)] +pub struct Layer8ContextRequestSummary { + pub method: Method, + pub path: String, + pub params: HashMap, +} + +impl Layer8ContextRequestSummary { + pub(crate) fn from(session: &Session) -> Self { + let method = session.req_header().method.clone(); + let path = session.req_header().uri.path().to_string(); + let query = session.req_header().uri.query(); + + let mut params = HashMap::new(); + if let Some(query) = query { + for pair in query.split('&') { + let mut iter = pair.splitn(2, '='); + if let (Some(key), Some(value)) = (iter.next(), iter.next()) { + params.insert(key.to_string(), value.to_string()); + } + } + } + + Layer8ContextRequestSummary { + method, + path, + params, + } + } +} + +/// `Layer8ContextRequest` is expected to contain all relevant request information +/// needed for processing and handler access +#[derive(Debug, Clone, Default)] +pub struct Layer8ContextRequest { + summary: Layer8ContextRequestSummary, + header: Layer8Header, + body: Vec, +} + +/// `Layer8ContextResponse` is expected to store data to be returned to the client and +/// shared across handlers during request processing +#[derive(Debug, Clone, Default)] +pub struct Layer8ContextResponse { + header: Layer8Header, + body: Vec, +} + +/// `Layer8Context` is the main context object passed to handlers during request processing. +/// +/// It encapsulates: +/// - `request`: All relevant request information (method, path, headers, body, params). +/// - `response`: Data to be returned to the client and shared across handlers (headers, body). +/// - `memory`: Arbitrary key-value data for sharing state between handlers during processing. +/// +/// This struct is designed to provide a unified interface for accessing and modifying +/// request and response data, as well as sharing state across middleware and handlers. +/// All fields are private and should be accessed or modified only through dedicated `get` and `set` methods. +#[derive(Debug, Clone, Default)] +pub struct Layer8Context { + /// `request`: contains all relevant request information needed for processing and handler access + pub request: Layer8ContextRequest, + /// `response`: stores data to be returned to the client and shared across handlers + /// during request processing + pub response: Layer8ContextResponse, + /// `memory`: stores arbitrary key-value data that needs to be shared across handlers + /// during request processing. + /// Accessed via `get(&self, key: &str)` and `set(&mut self, key: String, value: String)` methods + memory: HashMap, +} + +impl Layer8Context { + pub async fn update(&mut self, session: &mut Session) -> pingora::Result { + self.request.summary = Layer8ContextRequestSummary::from(session); + + match get_request_body(session).await { + Ok(body) => self.request.body = body, + Err(err) => return Err(err) + }; + + self.set_request_header(session.req_header().clone()); + + // take anything as needed later + + Ok(true) + } + +} + +impl Layer8ContextTrait for Layer8Context { + fn method(&self) -> Method { + self.request.summary.method.clone() + } + fn path(&self) -> String { + self.request.summary.path.clone() + } + + fn params(&self) -> &HashMap { + &self.request.summary.params + } + + fn param(&self, key: &str) -> Option<&String> { + self.request.summary.params.get(key) + } + + fn set_request_header(&mut self, header: RequestHeader) { + for (key, val) in header.headers.iter() { + self.request.header.insert(key.to_string(), val.to_str().unwrap_or("").to_string()); + }; + } + + fn get_request_header(&self) -> &Layer8Header { + &self.request.header + } + + fn insert_response_header(&mut self, key: &str, val: &str) { + self.response.header.insert(key.to_lowercase().to_string(), val.to_string()); + } + + fn remove_response_header(&mut self, key: &str) -> Option { + self.response.header.remove(key) + } + + fn get_response_header(&self) -> &Layer8Header { + &self.response.header + } + + fn set_request_body(&mut self, body: Vec) { + self.request.body = body + } + + fn get_request_body(&self) -> Vec { + self.request.body.clone() + } + + fn set_response_body(&mut self, body: Vec) { + self.response.body = body + } + + fn get_response_body(&self) -> Vec { + self.response.body.clone() + } + + fn get(&self, key: &str) -> Option<&String> { + self.memory.get(key) + } + + fn set(&mut self, key: String, value: String) { + self.memory.insert(key, value); + } + + fn set_request_summary(&mut self, summary: Layer8ContextRequestSummary) { + self.request.summary = summary + } +} + +/// This trait appears to be redundant and could potentially be removed, +/// as it is only implemented for `Layer8Context` and not used elsewhere. +/// Considering... +pub trait Layer8ContextTrait { + fn method(&self) -> Method; + fn path(&self) -> String; + fn params(&self) -> &HashMap; + fn param(&self, key: &str) -> Option<&String>; + fn set_request_header(&mut self, header: RequestHeader); + fn get_request_header(&self) -> &Layer8Header; + fn insert_response_header(&mut self, key: &str, val: &str); + fn remove_response_header(&mut self, key: &str) -> Option; + fn get_response_header(&self) -> &Layer8Header; + fn set_request_body(&mut self, body: Vec); + fn get_request_body(&self) -> Vec; + fn set_response_body(&mut self, body: Vec); + fn get_response_body(&self) -> Vec; + fn get(&self, key: &str) -> Option<&String>; + fn set(&mut self, key: String, value: String); + fn set_request_summary(&mut self, summary: Layer8ContextRequestSummary); +} + +/// `Layer8Header` is a type alias for a map of HTTP header key-value pairs used +/// throughout the proxy context. +/// +/// - Keys and values are both `String`. +/// - Only string-representable header values are currently supported. +/// - This may need to be updated in the future to support non-string header values +/// (e.g., binary or multi-valued headers). +/// - Used for both request and response headers in `Layer8Context`. +pub type Layer8Header = HashMap; diff --git a/pingora-router/src/handler.rs b/pingora-router/src/handler.rs new file mode 100644 index 0000000..e2f3413 --- /dev/null +++ b/pingora-router/src/handler.rs @@ -0,0 +1,117 @@ +use std::fmt::Debug; +use pingora::http::StatusCode; +use crate::ctx::Layer8Context; +use futures::future::BoxFuture; +use serde::de::Deserialize; +use serde::ser::Serialize; + +/* + * Each type in this crate has a specific purpose and may be updated as requirements evolve. + */ + +/// `APIHandler` is a type alias for an asynchronous handler function used in the proxy's routing system. +/// +/// - It represents a boxed function that takes a reference to a handler object (`T`) +/// and a mutable reference to a `Layer8Context`, returning a boxed future that resolves to an `APIHandlerResponse`. +/// - The handler function must be `Send` and `Sync` to support concurrent execution. +/// - This abstraction allows for flexible, composable, and type-safe API endpoint handlers. +/// +/// # Type Parameters +/// - `T`: The handler type, typically containing shared state or logic for processing requests. +/// +/// # Example +/// ```rust +/// use std::sync::Arc; +/// use futures::FutureExt; +/// use pingora::http::StatusCode; +/// use pingora_router::ctx::Layer8Context; +/// use pingora_router::handler::{APIHandler, APIHandlerResponse}; +/// +/// struct MyHandler; +/// +/// impl MyHandler { +/// async fn handle(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { +/// // Example logic +/// APIHandlerResponse::new(StatusCode::OK, Some(b"Hello, world!".to_vec())) +/// } +/// } +/// +/// ... +/// let handler: APIHandler> = Box::new(|h, ctx| { +/// async move { h.handle(ctx).await }.boxed() +/// }); +/// ``` +pub type APIHandler = Box Fn(&'a T, &'a mut Layer8Context) -> BoxFuture<'a, APIHandlerResponse> + Send + Sync>; + +/// `APIHandlerResponse` contains information returned by handlers and can be +/// shared across handlers during request processing. +#[derive(Debug, Default)] +pub struct APIHandlerResponse { + pub status: StatusCode, + pub body: Option>, +} + +impl APIHandlerResponse { + pub fn new(status: StatusCode, body: Option>) -> Self { + APIHandlerResponse { status, body } + } +} + +/// `ResponseBodyTrait` provides a default method to serialize the response body to bytes. +/// +/// *Implementation* for response body types is **optional** and provided mainly for +/// *convenience* at this stage. +/// +/// But it *can be extended* to specify requirements as needed later. +pub trait ResponseBodyTrait: Serialize + for<'de> Deserialize<'de> + Debug { + fn to_bytes(&self) -> Vec { + serde_json::to_vec(self).unwrap() + } + + fn from_bytes(bytes: Vec) -> Result, serde_json::Error> { + serde_json::from_slice(&bytes) + } + + /// Override this method to handle error serialization if your handler implements + /// the `DefaultHandler` trait. + fn from_json_err(_err: serde_json::Error) -> Option {None} +} + +/// `RequestBodyTrait` provides a default method to deserialize the request body bytes +/// to json format. +/// +/// *Implementation* for request body types is **optional** and provided mainly for +/// *convenience* at this stage. +/// +/// But it *can be extended* to specify requirements as needed later. +pub trait RequestBodyTrait: Serialize + for<'de> Deserialize<'de> + Debug { + fn to_bytes(&self) -> Vec { + serde_json::to_vec(self).unwrap() + } + + fn from_bytes(bytes: Vec) -> Result, serde_json::Error> { + serde_json::from_slice(&bytes) + } +} + +/// `DefaultHandlerTrait` provides default request body parsing. +/// Can be extended to specify requirements for integration with the router or to provide +/// additional default methods in the future. +/// +/// *Implementation* for your handler is **optional** and provided mainly for +/// *convenience* at this stage. +/// +/// This trait defines a generic method `parse_request_body` that attempts to deserialize a +/// request body of type `T: impl RequestBodyTrait` from a byte vector. +/// If deserialization succeeds, it returns the parsed body, no error, and a 200 OK status. +/// If deserialization fails, it returns no body, an error response of type `E: impl +/// ResponseBodyTrait` (constructed from the JSON error), and a 400 Bad Request status. +pub trait DefaultHandlerTrait { + fn parse_request_body(data: &Vec) -> Result> + { + match T::from_bytes(data.clone()) { + Ok(body) => Ok(*body), + Err(e) => Err(E::from_json_err(e)) + } + } +} \ No newline at end of file diff --git a/pingora-router/src/lib.rs b/pingora-router/src/lib.rs new file mode 100644 index 0000000..7b98195 --- /dev/null +++ b/pingora-router/src/lib.rs @@ -0,0 +1,4 @@ +pub mod ctx; +pub mod handler; +mod utils; +pub mod router; diff --git a/pingora-router/src/router.rs b/pingora-router/src/router.rs new file mode 100644 index 0000000..36a99fb --- /dev/null +++ b/pingora-router/src/router.rs @@ -0,0 +1,126 @@ +use std::collections::HashMap; +use pingora::http::{Method, StatusCode}; +use crate::ctx::{Layer8Context, Layer8ContextTrait}; +use crate::handler::{APIHandler, APIHandlerResponse}; + +/// `Router` is a generic struct that manages HTTP route registration and handler dispatching. +/// +/// # Type Parameters +/// - `T`: The type of the main handler object, typically shared across all route handlers. +/// +/// # Fields +/// - `handler`: The main handler instance shared with all route handlers. +/// - `_groups`: Reserved for future use (e.g., route grouping or middleware). +/// - `posts`, `gets`, `puts`, `deletes`: Maps of HTTP method and path to arrays of handler functions. +/// +/// # Usage +/// Register handlers for specific HTTP methods and paths using the `post`, `get`, `put`, and `delete` methods. +/// Call `call_handler` to dispatch a request to the appropriate handler(s) based on method and path. +/// +/// # Example +/// ```rust +/// let mut router = Router::new(handler); +/// router.post("/example".to_string(), Box::new([example_handler])); +/// ``` +pub struct Router { + handler: T, + _groups: Vec, // placeholder for later use + posts: HashMap]>>, + gets: HashMap]>>, + puts: HashMap]>>, + deletes: HashMap]>>, +} + +impl Router { + pub fn new(handler: T) -> Self { + Router { + handler, + _groups: Vec::new(), + posts: HashMap::new(), + gets: HashMap::new(), + puts: HashMap::new(), + deletes: HashMap::new(), + } + } + + /// Checks if the router contains a handler for the given HTTP method and path. + /// + /// # Arguments + /// + /// * `method` - The HTTP method to check (e.g., GET, POST). + /// * `path` - The request path to check. + /// + /// # Returns + /// + /// `true` if a handler exists for the specified method and path, or if the method is OPTIONS; + /// otherwise, `false`. + pub fn contains(&self, method: &Method, path: &str) -> bool { + match *method { + Method::POST => self.posts.contains_key(path), + Method::GET => self.gets.contains_key(path), + Method::PUT => self.puts.contains_key(path), + Method::DELETE => self.deletes.contains_key(path), + Method::OPTIONS => true, + _ => false, + } + } + + fn get_handlers(&self, method: &Method, path: &str) -> Option<&Box<[APIHandler]>> { + match *method { + Method::POST => self.posts.get(path), + Method::GET => self.gets.get(path), + Method::PUT => self.puts.get(path), + Method::DELETE => self.deletes.get(path), + _ => return None, + } + } + + pub async fn call_handler(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + let method = ctx.method(); + let path = ctx.path(); + + if method == Method::OPTIONS { + return APIHandlerResponse::new(StatusCode::NO_CONTENT, None); + } + + if let Some(handlers) = self.get_handlers(&method, &path) { + let mut response = APIHandlerResponse::new(StatusCode::OK, None); + for handler in handlers.iter() { + response = handler(&self.handler, ctx).await; + if response.status != StatusCode::OK { + return response; + } + + if response.body != None { + ctx.set_response_body(response.body.clone().unwrap()); + } + } + + response + } else { + return APIHandlerResponse::new(StatusCode::NOT_FOUND, None); + } + } + + fn get_base_path(&self, path: &str) -> String { + path.split('?').next().unwrap_or(path).to_string() + } + + pub fn post(&mut self, path: String, handlers: Box<[APIHandler]>) { + self.posts.insert(self.get_base_path(&path), handlers); + } + + pub fn get(&mut self, path: String, handlers: Box<[APIHandler]>) { + self.gets.insert(self.get_base_path(&path), handlers); + } + + pub fn put(&mut self, path: String, handlers: Box<[APIHandler]>) { + self.puts.insert(self.get_base_path(&path), handlers); + } + + pub fn delete(&mut self, path: String, handlers: Box<[APIHandler]>) { + self.deletes.insert(self.get_base_path(&path), handlers); + } +} + + diff --git a/pingora-router/src/utils.rs b/pingora-router/src/utils.rs new file mode 100644 index 0000000..7c2ced0 --- /dev/null +++ b/pingora-router/src/utils.rs @@ -0,0 +1,21 @@ +use log::error; +use pingora::prelude::Session; + +pub(crate) async fn get_request_body(session: &mut Session) -> pingora::Result> { + let mut body = Vec::new(); + loop { + match session.read_request_body().await { + Ok(option) => { + match option { + Some(chunk) => body.extend_from_slice(&chunk), + None => break, + } + } + Err(err) => { + error!("ERROR: {err}"); + return Err(err); + } + } + } + Ok(body) +} \ No newline at end of file diff --git a/reverse-proxy/Cargo.lock b/reverse-proxy/Cargo.lock deleted file mode 100644 index 3f8ec62..0000000 --- a/reverse-proxy/Cargo.lock +++ /dev/null @@ -1,3284 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.3", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" -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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.59.0", -] - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "aws-lc-rs" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.9.1", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.101", - "which", -] - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "brotli" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "cc" -version = "1.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive", - "clap_lex", - "indexmap 1.9.3", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "daemonize" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfdaacb3c887a54d41bdf48d3af8873b3f5566469f8ba21b92057509f116e" -dependencies = [ - "libc", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "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]] -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.101", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_filter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "flate2" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" -dependencies = [ - "crc32fast", - "libz-ng-sys", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -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 = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" -dependencies = [ - "equivalent", - "hashbrown 0.15.4", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jiff" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.172" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.0", -] - -[[package]] -name = "libz-ng-sys" -version = "1.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7118c2c2a3c7b6edc279a8b19507672b9c4d716f95e671172dfa4e23f9fd824" -dependencies = [ - "cmake", - "libc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "lru" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8cc7106155f10bdf99a6f379688f543ad6596a415375b36a59a054ceda1198" -dependencies = [ - "hashbrown 0.15.4", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[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.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - -[[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 = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[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 = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pingora" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "pingora-core", - "pingora-http", - "pingora-load-balancing", - "pingora-proxy", - "pingora-timeout", -] - -[[package]] -name = "pingora-cache" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "ahash", - "async-trait", - "blake2", - "bytes", - "hex", - "http 1.3.1", - "httparse", - "httpdate", - "indexmap 1.9.3", - "log", - "lru", - "once_cell", - "parking_lot", - "pingora-core", - "pingora-error", - "pingora-header-serde", - "pingora-http", - "pingora-lru", - "pingora-timeout", - "regex", - "rmp", - "rmp-serde", - "rustracing", - "rustracing_jaeger", - "serde", - "strum", - "tokio", -] - -[[package]] -name = "pingora-core" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "ahash", - "async-trait", - "brotli", - "bytes", - "chrono", - "clap", - "daemonize", - "flate2", - "futures", - "h2 0.4.10", - "http 1.3.1", - "httparse", - "httpdate", - "libc", - "log", - "lru", - "nix", - "once_cell", - "openssl-probe", - "parking_lot", - "percent-encoding", - "pingora-error", - "pingora-http", - "pingora-pool", - "pingora-runtime", - "pingora-timeout", - "prometheus", - "rand 0.8.5", - "regex", - "serde", - "serde_yaml", - "sfv", - "socket2", - "strum", - "strum_macros", - "thread_local", - "tokio", - "tokio-test", - "unicase", - "windows-sys 0.59.0", - "zstd", -] - -[[package]] -name = "pingora-error" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" - -[[package]] -name = "pingora-header-serde" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "bytes", - "http 1.3.1", - "httparse", - "pingora-error", - "pingora-http", - "thread_local", - "zstd", - "zstd-safe", -] - -[[package]] -name = "pingora-http" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "bytes", - "http 1.3.1", - "pingora-error", -] - -[[package]] -name = "pingora-ketama" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "crc32fast", -] - -[[package]] -name = "pingora-load-balancing" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "arc-swap", - "async-trait", - "derivative", - "fnv", - "futures", - "http 1.3.1", - "log", - "pingora-core", - "pingora-error", - "pingora-http", - "pingora-ketama", - "pingora-runtime", - "rand 0.9.1", - "tokio", -] - -[[package]] -name = "pingora-lru" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "arrayvec", - "hashbrown 0.15.4", - "parking_lot", - "rand 0.9.1", -] - -[[package]] -name = "pingora-pool" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "crossbeam-queue", - "log", - "lru", - "parking_lot", - "pingora-timeout", - "thread_local", - "tokio", -] - -[[package]] -name = "pingora-proxy" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "async-trait", - "bytes", - "clap", - "futures", - "h2 0.4.10", - "http 1.3.1", - "log", - "once_cell", - "pingora-cache", - "pingora-core", - "pingora-error", - "pingora-http", - "pingora-timeout", - "regex", - "tokio", -] - -[[package]] -name = "pingora-runtime" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "once_cell", - "rand 0.8.5", - "thread_local", - "tokio", -] - -[[package]] -name = "pingora-timeout" -version = "0.4.0" -source = "git+https://github.com/dtpthao/pingora.git?tag=0.4.1#de892369f6d873eb160d0d88a2a4cf5c724771c7" -dependencies = [ - "once_cell", - "parking_lot", - "pin-project-lite", - "thread_local", - "tokio", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" -dependencies = [ - "zerovec", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" -dependencies = [ - "proc-macro2", - "syn 2.0.101", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prometheus" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot", - "protobuf", - "thiserror", -] - -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - -[[package]] -name = "proxy" -version = "0.1.0" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "clap", - "env_logger", - "log", - "pingora", - "reqwest", - "serde", - "serde_json", - "serde_yaml", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "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]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "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]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "redox_syscall" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[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 = "rmp" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - -[[package]] -name = "rust_decimal" -version = "1.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" -dependencies = [ - "arrayvec", - "num-traits", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.23.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustracing" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44822b10c095e574869de2b891e40c724fef42cadaea040d1cd3bdbb13d36a5" -dependencies = [ - "backtrace", - "crossbeam-channel", - "rand 0.8.5", - "trackable 0.2.24", -] - -[[package]] -name = "rustracing_jaeger" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6c2fe9411ef5f43ac773f0e84ad735804c55719346a7aad52de2d9162db97c8" -dependencies = [ - "crossbeam-channel", - "hostname", - "percent-encoding", - "rand 0.8.5", - "rustracing", - "thrift_codec", - "trackable 0.2.24", -] - -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.1", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sfv" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa1f336066b758b7c9df34ed049c0e693a426afe2b27ff7d5b14f410ab1a132" -dependencies = [ - "base64 0.22.1", - "indexmap 2.9.0", - "rust_decimal", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.101", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[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.101", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.7", - "windows-sys 0.59.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 = "textwrap" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "thrift_codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb61fb3d0a0af14949f3a6949b2639112e13226647112824f4d081533f9b1a8" -dependencies = [ - "byteorder", - "trackable 0.2.24", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-test" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" -dependencies = [ - "async-stream", - "bytes", - "futures-core", - "tokio", - "tokio-stream", -] - -[[package]] -name = "tokio-util" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", -] - -[[package]] -name = "trackable" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98abb9e7300b9ac902cc04920945a874c1973e08c310627cc4458c04b70dd32" -dependencies = [ - "trackable 1.3.0", - "trackable_derive", -] - -[[package]] -name = "trackable" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15bd114abb99ef8cee977e517c8f37aee63f184f2d08e3e6ceca092373369ae" -dependencies = [ - "trackable_derive", -] - -[[package]] -name = "trackable_derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[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 = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.101", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "windows-interface" -version = "0.59.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "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]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[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 = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[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.101", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.101", -] - -[[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.101", - "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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" -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.101", -] - -[[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.15+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/reverse-proxy/Cargo.toml b/reverse-proxy/Cargo.toml index 951bc0a..adf470a 100644 --- a/reverse-proxy/Cargo.toml +++ b/reverse-proxy/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] async-trait="0.1" -pingora = { git = "https://github.com/dtpthao/pingora.git", tag = "0.4.1", features = [ "lb" ] } bytes = "1.10.1" clap = { version = "3.2.25", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] } @@ -17,3 +16,15 @@ chrono = "0.4.40" reqwest = { version = "0.11", features = ["json"] } tokio-rustls = "0.26.2" tokio = "1.44.2" +pingora-router = { path = "../pingora-router" } +pingora = { version = "0.4.0", features = ["lb"] } +futures = "0.3.31" +ntor = { git = "https://github.com/globe-and-citizen/ntor.git", tag = "0.1.0"} +#ntor = { path = "../../../ntor" } +config = "0.15.11" +toml = "0.8.23" +uuid = { version = "1.16.0", features = ["v4"] } +utils = { path = "../utils" } + +[patch.crates-io] +sfv = { git = "https://github.com/undef1nd/sfv.git", tag = "v0.9.4" } diff --git a/reverse-proxy/config.toml b/reverse-proxy/config.toml new file mode 100644 index 0000000..c7dbdd7 --- /dev/null +++ b/reverse-proxy/config.toml @@ -0,0 +1,16 @@ +[upstream] +host="localhost" +port=0 + +[server] +local_address="127.0.0.1:6194" +public_address="0.0.0.0:6193" + +[log] +level="DEBUG" +path="console" + +[handler] +#jwt_secret="this is 32-byte wgp's jwt secret" +ntor_server_id="ReverseProxyServer" +ntor_static_secret="this is 32-byte nTorStaticSecret" diff --git a/reverse-proxy/src/config.rs b/reverse-proxy/src/config.rs new file mode 100644 index 0000000..9b1a0a8 --- /dev/null +++ b/reverse-proxy/src/config.rs @@ -0,0 +1,66 @@ +use std::fs; +use serde::Deserialize; +use toml; + +#[derive(Debug, Deserialize)] +pub struct Config { + pub upstream: UpstreamConfig, + pub log: LogConfig, + pub server: ServerConfig, + pub handler: HandlerConfig +} + +impl Config { + /// panic if unable to validate. + /// assuming after this validation, all configs are valid + pub fn validate(&self) { + // todo + } +} + +impl Config { + pub fn from_file(path: &str) -> Self { + let content = fs::read_to_string(path).expect("Failed to read configuration file"); + toml::from_str(&content).expect("Failed to parse configuration file") + } +} + +#[derive(Debug, Deserialize)] +pub(super) struct UpstreamConfig { + pub host: String, + pub port: u16, +} + +#[derive(Debug, Deserialize)] +pub(super) struct LogConfig { + pub path: String, + pub level: String, +} + +impl LogConfig { + pub fn to_level_filter(&self) -> log::LevelFilter { + match self.level.to_uppercase().as_str() { + "INFO" => log::LevelFilter::Info, + "DEBUG" => log::LevelFilter::Debug, + "WARNING" => log::LevelFilter::Warn, + "ERROR" => log::LevelFilter::Error, + "TRACE" => log::LevelFilter::Trace, + "OFF" => log::LevelFilter::Off, + _ => log::max_level() + } + } +} + +#[derive(Debug, Deserialize)] +pub(super) struct ServerConfig { + pub local_address: String, + pub public_address: String +} + +#[derive(Debug, Deserialize)] +pub(super) struct HandlerConfig { + pub ntor_server_id: String, + pub ntor_static_secret: String, +} + + diff --git a/reverse-proxy/src/handler/common/consts.rs b/reverse-proxy/src/handler/common/consts.rs new file mode 100644 index 0000000..ff3a476 --- /dev/null +++ b/reverse-proxy/src/handler/common/consts.rs @@ -0,0 +1,37 @@ +use clap::__macro_refs::once_cell::sync::Lazy; + +// can be replaced by constants, will see +pub enum HeaderKeys { + RpHeaderRequestKey, + RpHeaderResponseKey, + SpaHeaderRequestKey, + IntHeaderRequestKey, + FpHeaderRequestKey, + BeHeaderResponseKey +} + +impl HeaderKeys { + pub fn as_str(&self) -> &'static str { + match self { + HeaderKeys::RpHeaderRequestKey => "rp_request_header", + HeaderKeys::RpHeaderResponseKey => "rp_response_header", + HeaderKeys::SpaHeaderRequestKey => "spa_request_header", + HeaderKeys::BeHeaderResponseKey => "be_response_header", + HeaderKeys::FpHeaderRequestKey => "fp_request_header", + HeaderKeys::IntHeaderRequestKey => "int_request_header" + } + } + + pub fn placeholder_value(&self) -> &'static str { + match self { + HeaderKeys::RpHeaderRequestKey => "added in ReverseProxy", + HeaderKeys::RpHeaderResponseKey => "added in ReverseProxy", + _ => "" + } + } +} + +// fixme BE path should be taken from configuration +const BACKEND_URL: &str = "http://localhost:3000"; +pub static INIT_TUNNEL_TO_BACKEND_PATH: Lazy = Lazy::new(|| format!("{}/init-tunnel", BACKEND_URL)); +pub static PROXY_TO_BACKEND_PATH: Lazy = Lazy::new(|| format!("{}/proxy", BACKEND_URL)); diff --git a/reverse-proxy/src/handler/common/handler.rs b/reverse-proxy/src/handler/common/handler.rs new file mode 100644 index 0000000..6fd4f18 --- /dev/null +++ b/reverse-proxy/src/handler/common/handler.rs @@ -0,0 +1,60 @@ +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use reqwest::header::HeaderMap; +use crate::handler::common::consts::HeaderKeys::{FpHeaderRequestKey, IntHeaderRequestKey, RpHeaderRequestKey, RpHeaderResponseKey}; +use utils::{to_reqwest_header}; + +/// Struct containing only associated methods (no instance methods or fields). +/// The contents are quite drafting, but the idea is to handle common operations +pub struct CommonHandler {} + +impl CommonHandler { + /// Add response headers to `ctx` to respond to FP: + /// - *Copy* Backend's response header in `headers` - *update* `Content-Length` + /// - *Add* custom ReverseProxy's response headers `custom_header` + pub fn create_response_headers( + headers: HeaderMap, + ctx: &mut Layer8Context, + custom_header: &str, + content_length: usize, + ) { + for (key, val) in headers.iter() { + if let (k, Ok(v)) = (key.to_string(), val.to_str()) { + ctx.insert_response_header(k.as_str(), v); + } + } + + ctx.insert_response_header( + RpHeaderResponseKey.as_str(), + custom_header, + ); + + ctx.insert_response_header("Content-Length", &*content_length.to_string()) + } + + /// Create request header to send/forward to BE: + /// - *Copy* origin request headers from ForwardProxy `ctx` + /// - *Add* custom ReverseProxy's request headers `custom_header` + /// - *Set* universal Content-Type and Content-Length + pub fn create_forward_request_headers( + ctx: &mut Layer8Context, + custom_header: &str, + content_length: usize, + ) -> HeaderMap { + // copy all origin header to new request + let origin_headers = ctx.get_request_header().clone(); + let mut reqwest_header = to_reqwest_header(origin_headers); + + // add forward proxy header `fp_request_header` + reqwest_header.insert( + RpHeaderRequestKey.as_str(), + custom_header.parse().unwrap(), + ); + + reqwest_header.insert("Content-Length", content_length.to_string().parse().unwrap()); + reqwest_header.insert("Content-Type", "application/json".parse().unwrap()); + reqwest_header.remove(IntHeaderRequestKey.as_str()); + reqwest_header.remove(FpHeaderRequestKey.as_str()); + + reqwest_header + } +} \ No newline at end of file diff --git a/reverse-proxy/src/handler/common/mod.rs b/reverse-proxy/src/handler/common/mod.rs new file mode 100644 index 0000000..a6ef363 --- /dev/null +++ b/reverse-proxy/src/handler/common/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod consts; +pub mod types; +pub mod handler; diff --git a/reverse-proxy/src/handler/common/types.rs b/reverse-proxy/src/handler/common/types.rs new file mode 100644 index 0000000..93b7cd4 --- /dev/null +++ b/reverse-proxy/src/handler/common/types.rs @@ -0,0 +1,17 @@ +use std::fmt::Debug; +use serde::{Deserialize, Serialize}; +use pingora_router::handler::ResponseBodyTrait; +use serde_json::Error; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ErrorResponse { + pub error: String +} + +impl ResponseBodyTrait for ErrorResponse { + fn from_json_err(err: Error) -> Option { + Some(ErrorResponse { + error: err.to_string() + }) + } +} \ No newline at end of file diff --git a/reverse-proxy/src/handler/init_tunnel/handler.rs b/reverse-proxy/src/handler/init_tunnel/handler.rs new file mode 100644 index 0000000..2732dcb --- /dev/null +++ b/reverse-proxy/src/handler/init_tunnel/handler.rs @@ -0,0 +1,63 @@ +use log::{error, info}; +use pingora::http::StatusCode; +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use pingora_router::handler::{APIHandlerResponse, DefaultHandlerTrait, ResponseBodyTrait}; +use reqwest::Client; +use crate::handler::common::consts::INIT_TUNNEL_TO_BACKEND_PATH; +use crate::handler::common::types::ErrorResponse; +use crate::handler::init_tunnel::{InitEncryptedTunnelRequest, InitTunnelRequestToBackend}; + +/// Struct containing only associated methods (no instance methods or fields) +pub(crate) struct InitTunnelHandler {} + +impl DefaultHandlerTrait for InitTunnelHandler {} + +impl InitTunnelHandler { + pub(crate) async fn validate_request_body(ctx: &mut Layer8Context) + -> Result + { + return match InitTunnelHandler::parse_request_body::< + InitEncryptedTunnelRequest, + ErrorResponse + >(&ctx.get_request_body()) + { + Ok(res) => Ok(res), + Err(err) => { + let body = match err { + None => None, + Some(err_response) => Some(err_response.to_bytes()) + }; + + InitTunnelHandler::send_result_to_be(false).await; + + Err(APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body, + }) + } + }; + } + + pub(crate) async fn send_result_to_be(result: bool) { + let body = InitTunnelRequestToBackend { + success: result, + }; + let log_meta = format!("[FORWARD {}]", INIT_TUNNEL_TO_BACKEND_PATH.as_str()); + info!("{log_meta} request to BE body: {:?}", body); + + let client = Client::new(); + match client.post(INIT_TUNNEL_TO_BACKEND_PATH.as_str()) + .header("Content-Type", "application/json") + .json(&body) + .send() + .await + { + Ok(res) => { + info!("{log_meta} Response sending init-tunnel result to BE: {:?}", res) + } + Err(err) => { + error!("{log_meta} Error sending init-tunnel result to BE: {:?}", err) + } + } + } +} diff --git a/reverse-proxy/src/handler/init_tunnel/mod.rs b/reverse-proxy/src/handler/init_tunnel/mod.rs new file mode 100644 index 0000000..29a1717 --- /dev/null +++ b/reverse-proxy/src/handler/init_tunnel/mod.rs @@ -0,0 +1,27 @@ +pub(crate) mod handler; + +use serde::{Deserialize, Serialize}; +use pingora_router::handler::{RequestBodyTrait, ResponseBodyTrait}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitEncryptedTunnelRequest { + pub public_key: Vec, +} + +impl RequestBodyTrait for InitEncryptedTunnelRequest {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitTunnelRequestToBackend { + pub success: bool, +} + +impl RequestBodyTrait for InitTunnelRequestToBackend {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InitEncryptedTunnelResponse { + pub public_key: Vec, + pub t_b_hash: Vec, + pub session_id: String +} + +impl ResponseBodyTrait for InitEncryptedTunnelResponse {} diff --git a/reverse-proxy/src/handler/mod.rs b/reverse-proxy/src/handler/mod.rs new file mode 100644 index 0000000..26b2c9b --- /dev/null +++ b/reverse-proxy/src/handler/mod.rs @@ -0,0 +1,114 @@ +use std::collections::HashMap; +use std::sync::{Mutex, MutexGuard}; +use log::debug; +use ntor::common::{InitSessionMessage, NTorParty}; +use ntor::server::NTorServer; +use pingora::http::StatusCode; +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use pingora_router::handler::{APIHandlerResponse, RequestBodyTrait, ResponseBodyTrait}; +use crate::handler::common::consts::HeaderKeys::{RpHeaderRequestKey, RpHeaderResponseKey}; +use init_tunnel::handler::InitTunnelHandler; +use proxy::handler::ProxyHandler; +use init_tunnel::InitEncryptedTunnelResponse; +use proxy::ProxyRequestToBackend; +use utils::{new_uuid, string_to_array32}; +use crate::config::HandlerConfig; +use crate::handler::common::handler::CommonHandler; + +mod common; +mod init_tunnel; +mod proxy; + +thread_local! { + static TEMPORARY_MEMORY: Mutex>> = Mutex::new(HashMap::new()); +} + +pub struct ReverseHandler { + config: HandlerConfig, + ntor_static_secret: [u8; 32], +} + +impl ReverseHandler { + pub fn new(config: HandlerConfig) -> Self { + let ntor_secret = string_to_array32(config.ntor_static_secret.clone()).unwrap(); + + ReverseHandler { + config, + ntor_static_secret: ntor_secret, + } + } + + pub async fn handle_init_tunnel(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + // validate request body + let request_body = match InitTunnelHandler::validate_request_body(ctx).await { + Ok(res) => res, + Err(res) => return res + }; + debug!("[REQUEST /init-tunnel] Parsed body: {:?}", request_body); + + // todo I think there are prettier ways to use nTor since we are free to modify the nTor crate, but I'm lazy + let mut ntor_server = NTorServer::new_with_secret( + self.config.ntor_server_id.clone(), + self.ntor_static_secret, + ); + + if request_body.public_key.len() != 32 { + return APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body: Some("Invalid public key length".as_bytes().to_vec()), + }; + } + + // Client initializes session with the server + let init_session_msg = InitSessionMessage::from(request_body.public_key); + + let init_session_response = ntor_server.accept_init_session_request(&init_session_msg); + + let ntor_session_id = new_uuid(); + + let response = InitEncryptedTunnelResponse { + public_key: init_session_response.public_key(), + t_b_hash: init_session_response.t_b_hash(), + session_id: ntor_session_id.clone(), + }; + + // set ReverseProxy's response header + ctx.insert_response_header( + RpHeaderResponseKey.as_str(), + RpHeaderResponseKey.placeholder_value() + ); + + InitTunnelHandler::send_result_to_be(true).await; + + TEMPORARY_MEMORY.with(|memory| { + let mut guard: MutexGuard>> = memory.lock().unwrap(); + guard.insert(ntor_session_id, ntor_server.get_shared_secret().unwrap()); + }); + + APIHandlerResponse { + status: StatusCode::OK, + body: Some(response.to_bytes()), + } + } + + pub async fn handle_proxy_request(&self, ctx: &mut Layer8Context) -> APIHandlerResponse { + // validate request body + let request_body = match ProxyHandler::validate_request_body(ctx).await { + Ok(res) => res, + Err(res) => return res, + }; + + let new_body = ProxyRequestToBackend { + spa_request_body: request_body.spa_request_body, + }; + + // todo validate request headers + let new_header = CommonHandler::create_forward_request_headers( + ctx, + RpHeaderRequestKey.placeholder_value(), + new_body.to_bytes().len(), + ); + + ProxyHandler::proxy_request_to_backend(ctx, new_header, new_body).await + } +} \ No newline at end of file diff --git a/reverse-proxy/src/handler/proxy/handler.rs b/reverse-proxy/src/handler/proxy/handler.rs new file mode 100644 index 0000000..21d332a --- /dev/null +++ b/reverse-proxy/src/handler/proxy/handler.rs @@ -0,0 +1,134 @@ +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use reqwest::header::HeaderMap; +use pingora_router::handler::{APIHandlerResponse, DefaultHandlerTrait, RequestBodyTrait, ResponseBodyTrait}; +use log::{error, info}; +use reqwest::Client; +use pingora::http::StatusCode; +use crate::handler::common::consts::HeaderKeys::RpHeaderResponseKey; +use crate::handler::common::consts::PROXY_TO_BACKEND_PATH; +use crate::handler::common::handler::CommonHandler; +use crate::handler::common::types::ErrorResponse; +use crate::handler::proxy::{ProxyRequestToBackend, ProxyResponse, ProxyResponseFromBackend}; + +/// Struct containing only associated methods (no instance methods or fields) +pub struct ProxyHandler {} + +impl DefaultHandlerTrait for ProxyHandler {} + +impl ProxyHandler { + pub(crate) async fn validate_request_body(ctx: &mut Layer8Context) + -> Result + { + match ProxyHandler::parse_request_body::< + ProxyRequestToBackend, + ErrorResponse + >(&ctx.get_request_body()) { + Ok(res) => Ok(res), + Err(err) => { + let body = match err { + None => None, + Some(err_response) => { + error!("Error parsing request body: {}", err_response.error); + Some(err_response.to_bytes()) + } + }; + Err(APIHandlerResponse { + status: StatusCode::BAD_REQUEST, + body, + }) + } + } + } + + /// - get spa_request_body from received request body + /// - send spa body to backend with ReverseProxy header + pub(crate) async fn proxy_request_to_backend( + ctx: &mut Layer8Context, + headers: HeaderMap, + body: ProxyRequestToBackend, + ) -> APIHandlerResponse + { + let new_body_string = String::from_utf8_lossy(&body.to_bytes()).to_string(); + + let log_meta = format!("[FORWARD {}]", PROXY_TO_BACKEND_PATH.as_str()); + info!("{log_meta} request to BE headers: {:?}", headers); + info!("{log_meta} request to BE body: {}", new_body_string); + + let client = Client::new(); + let response = client.post(PROXY_TO_BACKEND_PATH.as_str()) + .header("Content-Type", "application/json") + .headers(headers) + .body(new_body_string) + .send() + .await; + + match response { + Ok(reqw_response) if reqw_response.status().is_success() => { + let headers = reqw_response.headers().clone(); + info!("{log_meta} response from BE headers: {:?}", reqw_response.headers()); + return match reqw_response.json::().await { + Ok(res) => { + info!("{log_meta} response from BE body: {:?}", res); + // create new response body from backend's response + let proxy_response = ProxyResponse { + be_response_body: res.be_response_body, + rp_response_body: "body added in ReverseProxy".to_string(), + }.to_bytes(); + + CommonHandler::create_response_headers( + headers, + ctx, + RpHeaderResponseKey.placeholder_value(), + proxy_response.len(), + ); + + APIHandlerResponse { + status: StatusCode::OK, + body: Some(proxy_response), + } + } + Err(err) => { + error!("Parsing backend body error: {:?}", err); + APIHandlerResponse { + status: StatusCode::INTERNAL_SERVER_ERROR, + body: None, + } + } + }; + } + Ok(res) => { + // Handle 4xx/5xx errors + let status = res.status(); + error!("{log_meta} BE Response: {:?}", res); + + let error_body = match res.content_length() { + None => "internal-server-error".to_string(), + Some(_) => { + res.text().await.unwrap_or_else(|_e| "".to_string()) + } + }; + + let response_bytes = ErrorResponse { + error: error_body + }.to_bytes(); + + APIHandlerResponse { + status: StatusCode::try_from(status.as_u16()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR), + body: Some(response_bytes), + } + } + Err(err) => { + error!("{log_meta} Error: {:?}", err); + let status = err.status().unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR); + let err_body = ErrorResponse { + error: format!("Backend error: {}", status), + }; + + APIHandlerResponse { + status: StatusCode::BAD_GATEWAY, + body: Some(err_body.to_bytes()), + } + } + } + } +} diff --git a/reverse-proxy/src/handler/proxy/mod.rs b/reverse-proxy/src/handler/proxy/mod.rs new file mode 100644 index 0000000..46b4a9b --- /dev/null +++ b/reverse-proxy/src/handler/proxy/mod.rs @@ -0,0 +1,34 @@ +pub(crate) mod handler; + +use pingora_router::handler::{RequestBodyTrait, ResponseBodyTrait}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyRequest { + pub int_request_body: String, + pub spa_request_body: String +} + +impl RequestBodyTrait for ProxyRequest {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyRequestToBackend { + pub spa_request_body: String +} + +impl RequestBodyTrait for ProxyRequestToBackend {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyResponseFromBackend { + pub be_response_body: String +} + +impl ResponseBodyTrait for ProxyResponseFromBackend {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProxyResponse { + pub be_response_body: String, + pub rp_response_body: String +} + +impl ResponseBodyTrait for ProxyResponse {} diff --git a/reverse-proxy/src/main.rs b/reverse-proxy/src/main.rs index c12f995..e6bf1c9 100644 --- a/reverse-proxy/src/main.rs +++ b/reverse-proxy/src/main.rs @@ -1,288 +1,38 @@ -use async_trait::async_trait; -use bytes::Bytes; +mod handler; +mod proxy; + +use std::env; use clap::Parser; -use serde::{Deserialize, Serialize}; use std::net::ToSocketAddrs; -use pingora::Result; -use pingora::http::{Method, ResponseHeader, StatusCode}; -use pingora::proxy::{ProxyHttp, Session}; +use pingora::prelude::{http_proxy_service}; use pingora::server::Server; use pingora::server::configuration::Opt; -use pingora::upstreams::peer::HttpPeer; use chrono::Local; use env_logger; use log::*; -use reqwest::Client; -use std::collections::HashMap; -use std::fs::OpenOptions; use std::io::Write; - -const UPSTREAM_HOST: &str = "localhost"; -const UPSTREAM_IP: &str = "0.0.0.0"; -const BACKEND_PORT: u16 = 3000; - -#[derive(Serialize, Deserialize, Debug)] -pub struct RequestBody { - data: String, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ResponseBody { - rp_response_body_init_proxied: Option, - rp_request_body_proxied: Option, - fp_request_body_proxied: Option, - error: Option, -} - -pub struct ReverseProxy { - addr: std::net::SocketAddr, -} - -impl ReverseProxy { - fn get_method(session: &Session) -> String { - let request_summary = session.request_summary(); - let tmp: Vec<&str> = request_summary.split(" ").collect(); - let method: &str = tmp.get(0).unwrap(); - method.to_string() - } - - async fn handle_init_tunnel(session: &mut Session) -> Result> { - let response = ResponseBody { - rp_response_body_init_proxied: Some("response body init, reverse proxy".to_string()), - rp_request_body_proxied: None, - fp_request_body_proxied: None, - error: None, - }; - Ok(Some(response)) - } - - async fn handle_proxy_request(session: &mut Session) -> Result> { - // read request body - let mut body = Vec::new(); - loop { - match session.read_request_body().await? { - Some(chunk) => body.extend_from_slice(&chunk), - None => break, - } - } - - // convert to json - match serde_json::de::from_slice::(&body) { - Ok(request_body) => { - debug!("Request body: {:?}", request_body.data); - let request_url = session.req_header().uri.path().to_string(); - debug!( - "Creating a new request to http://localhost:{}{}", - BACKEND_PORT, request_url - ); - - let client = Client::new(); - let mut map = HashMap::new(); - map.insert("fp_request_body_proxied", request_body.data); - - let res = client - .post(format!("http://localhost:{}{}", BACKEND_PORT, request_url)) - .header("x-fp-request-header-proxied", "request-header-forward-proxied") - .header("x-rp-request-header-proxied", "request-header-reverse-proxy") - .json(&map) - .send() - .await; - - match res { - Ok(response) => { - debug!( - "POST {}, Host: localhost:{}, response code: {}", - request_url, - BACKEND_PORT, - response.status() - ); - - let mut response_body: ResponseBody = response.json().await.unwrap(); - response_body.rp_request_body_proxied = Some("data copied by reverse proxy".to_string()); - Ok(Some(response_body)) - } - Err(err) => { - error!("Error forwarding request to backend: {}", err); - let status = err.status().unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR); - Ok(Some(ResponseBody { - rp_response_body_init_proxied: None, - rp_request_body_proxied: None, - fp_request_body_proxied: None, - error: Some(format!("Backend error: {}", status)), - })) - } - } - } - Err(err) => { - error!("Error parsing request body: {}", err); - Ok(Some(ResponseBody { - rp_response_body_init_proxied: None, - rp_request_body_proxied: None, - fp_request_body_proxied: None, - error: Some("Invalid request body".to_string()), - })) - } - } - } - - async fn set_headers( - response_status: StatusCode, - body_bytes: &Vec, - session: &mut Session, - is_init_tunnel: bool, - ) -> Result<()> { - let mut header = ResponseHeader::build(response_status, None)?; - header - .append_header("Content-Length", body_bytes.len().to_string()) - .unwrap(); - - // Common headers - header - .append_header("Access-Control-Allow-Origin", "*") - .unwrap(); - header - .append_header("Access-Control-Allow-Methods", "POST, OPTIONS") - .unwrap(); - header - .append_header("Access-Control-Allow-Headers", "Content-Type") - .unwrap(); - header - .append_header("Access-Control-Max-Age", "86400") - .unwrap(); - - // Endpoint-specific headers - if is_init_tunnel { - header - .append_header("x-rp-response-header-init", "response-header-init-reverse-proxy") - .unwrap(); - } else { - header - .append_header("x-rp-response-header-added", "response-header-forward-proxied") - .unwrap(); - } - - session.write_response_header_ref(&header).await - } -} - -#[async_trait] -impl ProxyHttp for ReverseProxy { - type CTX = (); - - fn new_ctx(&self) -> Self::CTX {} - - async fn upstream_peer( - &self, - _session: &mut Session, - _ctx: &mut Self::CTX, - ) -> Result> { - let peer: Box = - Box::new(HttpPeer::new(self.addr, false, UPSTREAM_HOST.to_owned())); - Ok(peer) - } - - async fn request_filter(&self, session: &mut Session, _ctx: &mut Self::CTX) -> Result - where - Self::CTX: Send + Sync, - { - let mut response_body = ResponseBody { - rp_response_body_init_proxied: None, - rp_request_body_proxied: None, - fp_request_body_proxied: None, - error: None, - }; - let mut response_status = StatusCode::OK; - let mut is_init_tunnel = false; - - // get request method - let method = ReverseProxy::get_method(session); - let path = session.req_header().uri.path(); - - // Handle different endpoints - if path == "/init-tunnel" { - if method == Method::POST.to_string() { - match ReverseProxy::handle_init_tunnel(session).await? { - Some(res) => { - response_body = res; - is_init_tunnel = true; - } - None => { - response_status = StatusCode::BAD_REQUEST; - } - } - } else if method == Method::OPTIONS.to_string() { - response_status = StatusCode::NO_CONTENT; - } else { - response_status = StatusCode::METHOD_NOT_ALLOWED; - } - } else if path == "/proxy" { - if method == Method::POST.to_string() { - match ReverseProxy::handle_proxy_request(session).await? { - Some(res) => { - response_body = res; - } - None => { - response_status = StatusCode::BAD_REQUEST; - } - } - } else if method == Method::OPTIONS.to_string() { - response_status = StatusCode::NO_CONTENT; - } else { - response_status = StatusCode::METHOD_NOT_ALLOWED; - } - } else { - response_status = StatusCode::NOT_FOUND; - response_body.error = Some("Endpoint not found".to_string()); - } - - // Handle error responses - if response_body.error.is_some() { - response_status = match response_body.error.as_ref().unwrap().contains("Backend error") { - true => StatusCode::BAD_GATEWAY, - false => StatusCode::BAD_REQUEST, - }; - } - - // convert json response to vec - let response_body_bytes = serde_json::ser::to_vec(&response_body).unwrap(); - ReverseProxy::set_headers(response_status, &response_body_bytes, session, is_init_tunnel).await?; - session - .write_response_body(Some(Bytes::from(response_body_bytes)), true) - .await?; - - Ok(true) - } - - async fn logging( - &self, - session: &mut Session, - _e: Option<&pingora::Error>, - ctx: &mut Self::CTX, - ) { - let response_code = session - .response_written() - .map_or(0, |resp| resp.status.as_u16()); - // access log - info!( - "{} response code: {response_code}", - self.request_summary(session, ctx) - ); - } -} +use std::sync::Arc; +use pingora_router::handler::{APIHandler}; +use pingora_router::router::Router; +use proxy::{BACKEND_PORT, ReverseProxy, UPSTREAM_IP}; +use crate::handler::ReverseHandler; +use futures::FutureExt; +mod config; fn main() { - let file = OpenOptions::new() - .append(true) - .create(true) - .open("log.txt") - .expect("Can't create file!"); - - let target = Box::new(file); - + // let file = OpenOptions::new() + // .append(true) + // .create(true) + // .open("log.txt") + // .expect("Can't create file!"); + // + // let target = Box::new(file); + + let target = env_logger::Target::Stdout; env_logger::Builder::new() - .target(env_logger::Target::Pipe(target)) + .target(target) .filter(None, LevelFilter::Debug) .format(|buf, record| { writeln!( @@ -301,15 +51,33 @@ fn main() { let mut my_server = Server::new(Some(opt)).unwrap(); my_server.bootstrap(); - let mut my_proxy = pingora::proxy::http_proxy_service( + let handle_init_tunnel: APIHandler> = Box::new(|h, ctx| { + async move { h.handle_init_tunnel(ctx).await }.boxed() + }); + + let handle_proxy: APIHandler> = Box::new(|h, ctx| { + async move { h.handle_proxy_request(ctx).await }.boxed() + }); + + let config_path = env::var("CONFIG_PATH").unwrap_or_else(|_| "config.toml".to_string()); + let backbone_config = config::Config::from_file(&config_path); + backbone_config.validate(); + println!("{:?}", backbone_config); + + let rp_handler = Arc::new(ReverseHandler::new(backbone_config.handler)); + let mut router: Router> = Router::new(rp_handler.clone()); + router.post("/init-tunnel".to_string(), Box::new([handle_init_tunnel])); + router.post("/proxy".to_string(), Box::new([handle_proxy])); + + let upstream_addr = (UPSTREAM_IP.to_owned(), BACKEND_PORT) + .to_socket_addrs() + .unwrap() + .next() + .unwrap(); + + let mut my_proxy = http_proxy_service( &my_server.configuration, - ReverseProxy { - addr: (UPSTREAM_IP.to_owned(), BACKEND_PORT) - .to_socket_addrs() - .unwrap() - .next() - .unwrap(), - }, + ReverseProxy::new(upstream_addr, router), ); // Listen on both endpoints diff --git a/reverse-proxy/src/proxy.rs b/reverse-proxy/src/proxy.rs new file mode 100644 index 0000000..6aa3609 --- /dev/null +++ b/reverse-proxy/src/proxy.rs @@ -0,0 +1,125 @@ +use pingora::prelude::{HttpPeer, ProxyHttp}; +use pingora::proxy::Session; +use pingora::http::{ResponseHeader, StatusCode}; +use log::{info}; +use async_trait::async_trait; +use bytes::Bytes; +use pingora_router::ctx::{Layer8Context, Layer8ContextTrait}; +use pingora_router::router::Router; + +const UPSTREAM_HOST: &str = "localhost"; +pub const UPSTREAM_IP: &str = "0.0.0.0"; +pub const BACKEND_PORT: u16 = 3000; + +pub struct ReverseProxy { + addr: std::net::SocketAddr, + router: Router +} + +impl ReverseProxy { + + pub fn new(addr: std::net::SocketAddr, router: Router) -> Self { + ReverseProxy { + addr, + router + } + } + + async fn set_headers( + session: &mut Session, + ctx: &mut Layer8Context, + response_status: StatusCode + ) -> pingora::Result<()> { + let mut header = ResponseHeader::build(response_status, None)?; + + let response_header = ctx.get_response_header().clone(); + for (key, val) in response_header.iter() { + header.insert_header(key.clone(), val.clone()).unwrap(); + }; + + // Common headers + header.insert_header("Content-Type", "application/json").unwrap(); + header + .insert_header("Access-Control-Allow-Origin", "*") + .unwrap(); + header + .insert_header("Access-Control-Allow-Methods", "*") + .unwrap(); + header + .insert_header("Access-Control-Allow-Headers", "*") + .unwrap(); + header + .insert_header("Access-Control-Max-Age", "86400") + .unwrap(); + + println!(); + info!("[RESPONSE {} {}] Header: {:?}", session.req_header().method, + session.req_header().uri.to_string(), header.headers); + session.write_response_header_ref(&header).await + } +} + +#[async_trait] +impl ProxyHttp for ReverseProxy { + type CTX = Layer8Context; + + fn new_ctx(&self) -> Self::CTX { + Layer8Context::default() + } + + async fn upstream_peer( + &self, + _session: &mut Session, + _ctx: &mut Self::CTX, + ) -> pingora::Result> { + let peer: Box = + Box::new(HttpPeer::new(self.addr, false, UPSTREAM_HOST.to_owned())); + Ok(peer) + } + + async fn request_filter(&self, session: &mut Session, ctx: &mut Self::CTX) -> pingora::Result + where + Self::CTX: Send + Sync, + { + // create Context + ctx.update(session).await?; + let request_summary = format!("{} {}", session.req_header().method, session.req_header().uri.to_string()); + println!(); + info!("[REQUEST {}] {:?}", request_summary, ctx.request); + info!("[REQUEST {}] Decoded body: {}", request_summary, String::from_utf8_lossy(&*ctx.get_request_body())); + println!(); + + let handler_response = self.router.call_handler(ctx).await; + + let mut response_bytes = vec![]; + if let Some(body_bytes) = handler_response.body { + ctx.insert_response_header("Content-length", &body_bytes.len().to_string()); + response_bytes = body_bytes; + }; + ReverseProxy::::set_headers(session, ctx, handler_response.status).await?; + + info!("[RESPONSE {}] Body: {}", request_summary, String::from_utf8_lossy(&*response_bytes)); + println!(); + + // Write the response body to the session after setting headers + session.write_response_body(Some(Bytes::from(response_bytes)), true).await?; + + Ok(true) + } + + async fn logging( + &self, + session: &mut Session, + _e: Option<&pingora::Error>, + ctx: &mut Self::CTX, + ) { + let response_code = session + .response_written() + .map_or(0, |resp| resp.status.as_u16()); + // access log + info!( + "{} response code: {response_code}", + self.request_summary(session, ctx) + ); + } +} diff --git a/utils/Cargo.toml b/utils/Cargo.toml new file mode 100644 index 0000000..67305cf --- /dev/null +++ b/utils/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2024" + +[dependencies] +reqwest = { version = "0.11", features = ["json"] } +uuid = { version = "1.16.0", features = ["v4"] } +serde_json = "1.0.140" +serde = { version = "1.0.219", features = ["derive"] } diff --git a/utils/src/lib.rs b/utils/src/lib.rs new file mode 100644 index 0000000..1708586 --- /dev/null +++ b/utils/src/lib.rs @@ -0,0 +1,46 @@ +use std::collections::HashMap; +use reqwest::header::HeaderMap; +use uuid::Uuid; + +use serde::{Deserialize, Serialize}; + +pub fn to_reqwest_header(map: HashMap) -> HeaderMap { + let mut header_map = HeaderMap::new(); + for (k, v) in map { + if let Ok(header_name) = reqwest::header::HeaderName::try_from(k.as_str()) { + if let Ok(header_value) = reqwest::header::HeaderValue::from_str(&v) { + header_map.insert(header_name, header_value); + } + } + } + header_map +} + +pub fn new_uuid() -> String { + Uuid::new_v4().to_string() +} + +pub fn vec_to_json(vec: Vec) -> String { + serde_json::to_string(&vec).unwrap() +} + +pub fn json_to_vec(json: &str) -> Vec { + serde_json::from_str(json).unwrap() +} + +pub fn string_to_array32(s: String) -> Option<[u8; 32]> { + let bytes = s.into_bytes(); + if bytes.len() == 32 { + Some(bytes.try_into().unwrap()) + } else { + None + } +} + +pub fn bytes_to_json Deserialize<'de>>(bytes: Vec) -> Result { + serde_json::from_slice::(&bytes) +} + +pub fn bytes_to_string(bytes: &Vec) -> String { + String::from_utf8_lossy(bytes).to_string() +}