diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b5c8238..0969b84 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -18,13 +18,13 @@ jobs: features: "" image: ubuntu-latest - tag: metrics-amd64 - features: expose-metrics + features: metrics image: ubuntu-latest - tag: armv8 features: "" image: ubuntu-24.04-arm - tag: metrics-armv8 - features: expose-metrics + features: metrics image: ubuntu-24.04-arm runs-on: ${{ matrix.image }} diff --git a/Cargo.lock b/Cargo.lock index 0f9ba33..70cba0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # 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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "ahash" version = "0.8.12" @@ -31,18 +16,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -63,9 +48,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.13.3" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" +checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d" dependencies = [ "aws-lc-sys", "zeroize", @@ -73,9 +58,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.30.0" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" +checksum = "107a4e9d9cab9963e04e84bb8dee0e25f2a987f9a8bad5ed054abd439caa8f8c" dependencies = [ "bindgen", "cc", @@ -84,21 +69,6 @@ dependencies = [ "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.22.1" @@ -107,16 +77,14 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.69.5" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ "bitflags", "cexpr", "clang-sys", "itertools", - "lazy_static", - "lazycell", "log", "prettyplease", "proc-macro2", @@ -125,14 +93,13 @@ dependencies = [ "rustc-hash", "shlex", "syn", - "which", ] [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bumpalo" @@ -148,10 +115,11 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.31" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -168,9 +136,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clang-sys" @@ -290,14 +258,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "errno" -version = "0.3.13" +name = "find-msvc-tools" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "fnv" @@ -313,9 +277,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -372,20 +336,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "getrandom" version = "0.2.16" @@ -394,38 +344,32 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] -[[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" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -448,13 +392,19 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "heck" version = "0.5.0" @@ -479,7 +429,7 @@ dependencies = [ "once_cell", "rand", "ring", - "thiserror 2.0.12", + "thiserror", "tinyvec", "tokio", "tracing", @@ -500,20 +450,11 @@ dependencies = [ "parking_lot", "rand", "smallvec", - "thiserror 2.0.12", + "thiserror", "tokio", "tracing", ] -[[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 = "http" version = "1.3.1" @@ -562,13 +503,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -576,6 +518,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -611,9 +554,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "bytes", "futures-channel", @@ -632,9 +575,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -645,9 +588,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -658,11 +601,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -673,42 +615,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" 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" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -718,9 +656,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -739,23 +677,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", -] - -[[package]] -name = "io-uring" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" -dependencies = [ - "bitflags", - "cfg-if", - "libc", + "hashbrown 0.16.0", ] [[package]] @@ -766,9 +693,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -781,19 +708,19 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -805,83 +732,48 @@ 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.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "matchers" -version = "0.2.0" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "metrics" @@ -904,7 +796,7 @@ dependencies = [ "metrics", "metrics-util", "quanta", - "thiserror 2.0.12", + "thiserror", ] [[package]] @@ -916,7 +808,7 @@ dependencies = [ "aho-corasick", "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "indexmap", "metrics", "ordered-float", @@ -933,42 +825,32 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "moka" -version = "0.12.10" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", + "equivalent", "parking_lot", "portable-atomic", "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] @@ -993,11 +875,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1009,15 +891,6 @@ 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" @@ -1039,9 +912,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1049,22 +922,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" @@ -1086,9 +959,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -1104,9 +977,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.36" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", @@ -1114,9 +987,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -1131,16 +1004,16 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "web-sys", "winapi", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -1187,7 +1060,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -1201,27 +1074,27 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.5.0" +version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ "bitflags", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -1231,9 +1104,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -1242,9 +1115,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "ring" @@ -1260,17 +1133,11 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" @@ -1281,24 +1148,11 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "aws-lc-rs", "once_cell", @@ -1310,18 +1164,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "aws-lc-rs", "ring", @@ -1331,15 +1185,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "scoped-tls" -version = "1.0.1" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scopeguard" @@ -1349,24 +1197,34 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1417,19 +1275,19 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "subtle" @@ -1439,9 +1297,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -1467,38 +1325,18 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[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" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -1516,9 +1354,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -1526,9 +1364,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -1541,28 +1379,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -1571,9 +1406,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -1648,14 +1483,10 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ - "matchers", "nu-ansi-term", - "once_cell", - "regex-automata", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", ] @@ -1671,14 +1502,12 @@ name = "twilight-http-proxy" version = "0.1.0" dependencies = [ "dashmap", - "futures-util", "http", "http-body-util", "hyper", "hyper-hickory", "hyper-rustls", "hyper-util", - "lazy_static", "metrics", "metrics-exporter-prometheus", "metrics-util", @@ -1692,18 +1521,19 @@ dependencies = [ [[package]] name = "twilight-http-ratelimiting" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a36945d949920d6bb6aef30547e06ea645eefaa5575a14f56da608bf09d07ec8" +source = "git+https://github.com/twilight-rs/twilight.git?branch=next#5a0502631310e3f4a336450a1f413cab2627f824" dependencies = [ + "hashbrown 0.16.0", "tokio", + "tokio-util", "tracing", ] [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "untrusted" @@ -1713,13 +1543,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -1730,11 +1561,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "wasm-bindgen", ] @@ -1767,45 +1598,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" 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", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1813,31 +1631,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -1845,25 +1663,13 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" dependencies = [ "rustls-pki-types", ] -[[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", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1886,107 +1692,11 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-link", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core", -] - -[[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-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core", - "windows-link", - "windows-threading", -] - -[[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", -] - -[[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", -] - [[package]] name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core", - "windows-link", -] - -[[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" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -1999,20 +1709,20 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.60.2" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-targets 0.53.3", + "windows-link", ] [[package]] @@ -2033,28 +1743,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -dependencies = [ - "windows-link", - "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-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -2065,9 +1766,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -2077,9 +1778,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -2089,9 +1790,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -2101,9 +1802,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -2113,9 +1814,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -2125,9 +1826,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -2137,9 +1838,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -2149,32 +1850,28 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -2182,9 +1879,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -2194,18 +1891,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", @@ -2235,15 +1932,15 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -2252,9 +1949,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbb9122ea75b11bf96e7492afb723e8a7fbe12c67417aa95e7e3d18144d37cd" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -2263,9 +1960,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 4d55185..7512d63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,11 @@ [package] authors = ["Twilight Contributors"] -edition = "2018" +edition = "2024" name = "twilight-http-proxy" version = "0.1.0" [dependencies] dashmap = "6" -futures-util = { version = "0.3", default-features = false } http = "1" http-body-util = "0.1" hyper = { version = "1", default-features = false } @@ -16,20 +15,18 @@ hyper-util = { version = "0.1", default-features = false, features = ["tokio", " tokio = { version = "1.43", features = ["rt-multi-thread", "macros", "signal"] } tokio-util = { version = "0.7.8", default-features = false, features = ["time"] } tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } -twilight-http-ratelimiting = { version = "0.16.0" } +tracing-subscriber = "0.3" +twilight-http-ratelimiting = { git = "https://github.com/twilight-rs/twilight.git", branch = "next" } -# Only used by the `expose-metrics` feature. metrics = { version = "0.24", optional = true } metrics-exporter-prometheus = { version = "0.17", default-features = false, optional = true } metrics-util = { version = "0.20", optional = true } -lazy_static = { version = "1.4", optional = true } [dev-dependencies] tokio = { version = "1.43", features = ["test-util"] } [features] -expose-metrics = ["metrics", "metrics-exporter-prometheus", "metrics-util", "lazy_static"] +metrics = ["dep:metrics", "dep:metrics-exporter-prometheus", "dep:metrics-util"] [profile.release] codegen-units = 1 diff --git a/README.md b/README.md index 92df530..8e4abb4 100644 --- a/README.md +++ b/README.md @@ -115,11 +115,10 @@ setting `DISABLE_HTTP2` to any value when running the proxy. ## Prometheus metrics -The HTTP proxy can expose prometheus metrics when compiled with the -`expose-metrics` feature. These metrics are then available on the `/metrics` -endpoint. -You can set the metrics key used for the histogram data by setting the -`METRIC_KEY` environment variable. +The HTTP proxy can expose prometheus metrics when compiled with the `metrics` +feature. These metrics are then available on the `/metrics` endpoint. You can +set the metrics key used for the histogram data by setting the `METRIC_KEY` +environment variable. The exported histogram includes timing percentiles, response status codes, request path and request method. Calls to the metrics endpoint itself are not @@ -131,10 +130,8 @@ If processing an incoming request fails, the proxy will respond with a 5xx status code and a helpful error message in the response body. Currently, these status codes include: -- `500` if the proxy generates an invalid URI or the ratelimiter fails - internally -- `501` if the client requested an unsupported API path or used an unsupported - HTTP method +- `500` if the proxy encountered an internal error +- `501` if the client requested an unsupported API endpoint - `502` if the request made by the proxy fails [twilight]: https://github.com/twilight-rs/twilight diff --git a/src/error.rs b/src/error.rs index 7183954..e4c7bbc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,47 +1,26 @@ -use http::{uri::InvalidUri, Method, Response}; -use http_body_util::{combinators::BoxBody, BodyExt, Full}; +use http::{Method, Response}; +use http_body_util::{BodyExt, Full, combinators::BoxBody}; use hyper::body::Bytes; use hyper_util::client::legacy::Error as HyperUtilError; use std::{ error::Error, fmt::{Display, Formatter, Result as FmtResult}, }; -use twilight_http_ratelimiting::request::PathParseError; -static ACQUIRING_TICKET_FAILED_MSG: &str = - "http-proxy: Acquiring ticket from the ratelimiter failed"; -static INVALID_URI_MSG: &str = "http-proxy: Failed to create URI for requesting Discord API"; static INVALID_METHOD_MSG: &str = "http-proxy: Unsupported HTTP method in request"; -static INVALID_PATH_MSG: &str = "http-proxy: Failed to parse API path from client request"; static REQUEST_ISSUE_MSG: &str = "http-proxy: Error requesting the Discord API"; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] pub enum RequestError { - AcquiringTicket { - source: Box, - }, - InvalidMethod { - method: Method, - }, - InvalidPath { - source: PathParseError, - }, - InvalidURI { - source: InvalidUri, - }, - RequestIssue { - source: HyperUtilError, - }, + InvalidMethod { method: Method }, + RequestIssue { source: HyperUtilError }, } impl RequestError { pub fn as_response(&self) -> Response> { let (status_code, body_incoming) = match self { - RequestError::AcquiringTicket { .. } => (500, ACQUIRING_TICKET_FAILED_MSG), - RequestError::InvalidURI { .. } => (500, INVALID_URI_MSG), RequestError::InvalidMethod { .. } => (501, INVALID_METHOD_MSG), - RequestError::InvalidPath { .. } => (501, INVALID_PATH_MSG), RequestError::RequestIssue { .. } => (502, REQUEST_ISSUE_MSG), }; @@ -57,22 +36,10 @@ impl RequestError { impl Display for RequestError { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match self { - Self::AcquiringTicket { source } => { - f.write_str("error when acquiring ratelimiting ticket: ")?; - source.fmt(f) - } Self::InvalidMethod { method } => { f.write_str("invalid method: ")?; method.fmt(f) } - Self::InvalidPath { source } => { - f.write_str("invalid path: ")?; - source.fmt(f) - } - Self::InvalidURI { source } => { - f.write_str("generated uri for discord api is invalid: ")?; - source.fmt(f) - } Self::RequestIssue { source } => { f.write_str("error executing request: ")?; source.fmt(f) diff --git a/src/expiring_lru.rs b/src/expiring_lru.rs index 0c51c9e..c97229d 100644 --- a/src/expiring_lru.rs +++ b/src/expiring_lru.rs @@ -1,8 +1,10 @@ -use dashmap::{mapref::one::Ref, DashMap}; -use futures_util::StreamExt; -use std::{borrow::Borrow, hash::Hash, marker::PhantomData, ops::Deref, sync::Arc, time::Duration}; -use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; -use tokio_util::time::{delay_queue::Key, DelayQueue}; +use dashmap::{DashMap, mapref::one::Ref}; +use std::{ + borrow::Borrow, future::poll_fn, hash::Hash, marker::PhantomData, ops::Deref, sync::Arc, + time::Duration, +}; +use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel}; +use tokio_util::time::{DelayQueue, delay_queue::Key}; use tracing::debug; pub struct Entry { @@ -53,7 +55,7 @@ async fn decay_task( loop { tokio::select! { - Some(key) = queue.next(), if !queue.is_empty() => { + Some(key) = poll_fn(|cx| queue.poll_expired(cx)), if !queue.is_empty() => { // An item expired in the queue, remove it from the map debug!("Removing expired entry from ratelimiter decay queue"); map.remove(key.get_ref()); @@ -200,7 +202,7 @@ where #[cfg(test)] mod tests { use super::Builder; - use tokio::time::{sleep, Duration}; + use tokio::time::{Duration, sleep}; #[tokio::test(start_paused = true)] async fn test_lru() { diff --git a/src/main.rs b/src/main.rs index dd2eda4..61560b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,14 +3,12 @@ mod expiring_lru; mod ratelimiter_map; use error::RequestError; -use http::{ - header::{AUTHORIZATION, CONNECTION, HOST, TRANSFER_ENCODING, UPGRADE}, - HeaderValue, Method as HttpMethod, Uri, -}; +use http::{HeaderMap, HeaderValue, Method as HttpMethod, Uri, header}; use http_body_util::combinators::BoxBody; use hyper::{ + Request, Response, body::{Bytes, Incoming}, - service, Request, Response, + service, }; use hyper_hickory::{TokioHickoryHttpConnector, TokioHickoryResolver}; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; @@ -21,59 +19,44 @@ use hyper_util::{ }; use ratelimiter_map::RatelimiterMap; use std::{ - convert::{Infallible, TryFrom}, + convert::Infallible, env, error::Error, - net::{IpAddr, SocketAddr}, + net::{Ipv4Addr, SocketAddr}, pin::pin, str::FromStr, sync::Arc, + time::{Duration, Instant}, }; use tokio::{net::TcpListener, task::JoinSet}; -use tracing::{debug, error, info, trace, warn}; -use tracing_subscriber::EnvFilter; -use twilight_http_ratelimiting::{ - InMemoryRatelimiter, Method, Path, RatelimitHeaders, Ratelimiter, -}; +use tracing::{error, info, trace}; +use twilight_http_ratelimiting::{Endpoint, Method, RateLimitHeaders, RateLimiter}; #[cfg(unix)] -use tokio::signal::unix::{signal, SignalKind}; - -#[cfg(feature = "expose-metrics")] -use std::time::Instant; +use tokio::signal::unix::{SignalKind, signal}; -#[cfg(feature = "expose-metrics")] -use http::header::CONTENT_TYPE; -#[cfg(feature = "expose-metrics")] +#[cfg(feature = "metrics")] use http_body_util::{BodyExt, Full}; -#[cfg(feature = "expose-metrics")] -use lazy_static::lazy_static; -#[cfg(feature = "expose-metrics")] +#[cfg(feature = "metrics")] use metrics::histogram; -#[cfg(feature = "expose-metrics")] +#[cfg(feature = "metrics")] use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle}; -#[cfg(feature = "expose-metrics")] +#[cfg(feature = "metrics")] use metrics_util::MetricKindMask; -#[cfg(feature = "expose-metrics")] -use std::time::Duration; +#[cfg(feature = "metrics")] +use std::{borrow::Cow, sync::LazyLock}; -#[cfg(feature = "expose-metrics")] -lazy_static! { - static ref METRIC_KEY: String = - env::var("METRIC_KEY").unwrap_or_else(|_| "twilight_http_proxy".into()); -} +#[cfg(feature = "metrics")] +static METRIC_KEY: LazyLock> = LazyLock::new(|| { + env::var("METRIC_KEY").map_or(Cow::Borrowed("twilight_http_proxy"), Cow::Owned) +}); #[tokio::main] async fn main() -> Result<(), Box> { - tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), - ) - .init(); + tracing_subscriber::fmt::init(); - let host_raw = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".into()); - let host = IpAddr::from_str(&host_raw)?; - let port = env::var("PORT").unwrap_or_else(|_| "80".into()).parse()?; + let host = parse_env("HOST")?.unwrap_or(Ipv4Addr::UNSPECIFIED); + let port = parse_env("PORT")?.unwrap_or(80); let https_connector = { let mut http_connector = TokioHickoryResolver::default().into_http_connector(); @@ -84,7 +67,7 @@ async fn main() -> Result<(), Box> { .https_only() .enable_http1(); - if env::var("DISABLE_HTTP2").is_ok() { + if env::var_os("DISABLE_HTTP2").is_some() { builder.wrap_connector(http_connector) } else { builder.enable_http2().wrap_connector(http_connector) @@ -92,16 +75,20 @@ async fn main() -> Result<(), Box> { }; let client: Client<_, Incoming> = Client::builder(TokioExecutor::new()).build(https_connector); - let ratelimiter_map = Arc::new(RatelimiterMap::new(env::var("DISCORD_TOKEN")?)); + let ratelimiter_map = Arc::new(RatelimiterMap::new( + env::var("DISCORD_TOKEN")?, + Duration::from_secs(parse_env("CLIENT_DECAY_TIMEOUT")?.unwrap_or(3600)), + parse_env("CLIENT_CACHE_MAX_SIZE")?, + )); let address = SocketAddr::from((host, port)); - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] let handle: Arc; - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] { - let timeout = parse_env("METRIC_TIMEOUT").unwrap_or(300); + let timeout = parse_env("METRIC_TIMEOUT")?.unwrap_or(300); let recorder = PrometheusBuilder::new() .idle_timeout( MetricKindMask::COUNTER | MetricKindMask::HISTOGRAM, @@ -133,7 +120,7 @@ async fn main() -> Result<(), Box> { // Cloning a hyper client is fairly cheap by design let client = client.clone(); - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] let handle = handle.clone(); tasks.spawn(async move { @@ -147,7 +134,7 @@ async fn main() -> Result<(), Box> { let (ratelimiter, token) = ratelimiter_map.get_or_insert(token); let client = client.clone(); - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] { let handle = handle.clone(); @@ -164,7 +151,7 @@ async fn main() -> Result<(), Box> { } } - #[cfg(not(feature = "expose-metrics"))] + #[cfg(not(feature = "metrics"))] { async move { Ok::<_, Infallible>( @@ -193,7 +180,7 @@ async fn main() -> Result<(), Box> { } } - while let Some(_) = tasks.join_next().await {} + while tasks.join_next().await.is_some() {} Ok(()) } @@ -216,229 +203,103 @@ async fn shutdown_signal() { }; } -fn path_name(path: &Path) -> &'static str { - match path { - Path::ApplicationCommand(..) => "Application commands", - Path::ApplicationCommandId(..) => "Application command", - Path::ApplicationGuildCommand(..) => "Application commands in guild", - Path::ApplicationGuildCommandId(..) => "Application command in guild", - Path::ChannelsId(..) => "Channel", - Path::ChannelsIdFollowers(..) => "Channel followers", - Path::ChannelsIdInvites(..) => "Channel invite", - Path::ChannelsIdMessages(..) | Path::ChannelsIdMessagesId(..) => "Channel message", - Path::ChannelsIdMessagesBulkDelete(..) => "Bulk delete message", - Path::ChannelsIdMessagesIdCrosspost(..) => "Crosspost message", - Path::ChannelsIdMessagesIdReactions(..) => "Message reaction", - Path::ChannelsIdMessagesIdReactionsUserIdType(..) => "Message reaction for user", - Path::ChannelsIdMessagesIdThreads(..) => "Threads of a specific message", - Path::ChannelsIdPermissionsOverwriteId(..) => "Channel permission override", - Path::ChannelsIdPins(..) => "Channel pins", - Path::ChannelsIdPinsMessageId(..) => "Specific channel pin", - Path::ChannelsIdRecipients(..) => "Channel recipients", - Path::ChannelsIdThreadMembers(..) => "Thread members", - Path::ChannelsIdThreadMembersId(..) => "Thread member", - Path::ChannelsIdThreads(..) => "Channel threads", - Path::ChannelsIdTyping(..) => "Typing indicator", - Path::ChannelsIdWebhooks(..) | Path::WebhooksId(..) => "Webhook", - Path::Gateway => "Gateway", - Path::GatewayBot => "Gateway bot info", - Path::Guilds => "Guilds", - Path::GuildsId(..) => "Guild", - Path::GuildsIdAuditLogs(..) => "Guild audit logs", - Path::GuildsIdAutoModerationRules(..) => "Guild automoderation rules", - Path::GuildsIdAutoModerationRulesId(..) => "Guild automoderation rule", - Path::GuildsIdBans(..) => "Guild bans", - Path::GuildsIdBansId(..) => "Specific guild ban", - Path::GuildsIdBansUserId(..) => "Guild ban for user", - Path::GuildsIdChannels(..) => "Guild channel", - Path::GuildsIdEmojis(..) => "Guild emoji", - Path::GuildsIdEmojisId(..) => "Specific guild emoji", - Path::GuildsIdIntegrations(..) => "Guild integrations", - Path::GuildsIdIntegrationsId(..) => "Specific guild integration", - Path::GuildsIdIntegrationsIdSync(..) => "Sync guild integration", - Path::GuildsIdInvites(..) => "Guild invites", - Path::GuildsIdMembers(..) => "Guild members", - Path::GuildsIdMembersId(..) => "Specific guild member", - Path::GuildsIdMembersIdRolesId(..) => "Guild member role", - Path::GuildsIdMembersMeNick(..) => "Modify own nickname", - Path::GuildsIdMembersSearch(..) => "Search guild members", - Path::GuildsIdMfa(..) => "Guild MFA setting", - Path::GuildsIdPreview(..) => "Guild preview", - Path::GuildsIdPrune(..) => "Guild prune", - Path::GuildsIdRegions(..) => "Guild region", - Path::GuildsIdRoles(..) => "Guild roles", - Path::GuildsIdRolesId(..) => "Specific guild role", - Path::GuildsIdScheduledEvents(..) => "Scheduled events in guild", - Path::GuildsIdScheduledEventsId(..) => "Scheduled event in guild", - Path::GuildsIdScheduledEventsIdUsers(..) => "Users of a scheduled event", - Path::GuildsIdStickers(..) => "Guild stickers", - Path::GuildsIdTemplates(..) => "Guild templates", - Path::GuildsIdTemplatesCode(..) => "Specific guild template", - Path::GuildsIdThreads(..) => "Guild threads", - Path::GuildsIdVanityUrl(..) => "Guild vanity invite", - Path::GuildsIdVoiceStates(..) => "Guild voice states", - Path::GuildsIdWebhooks(..) => "Guild webhooks", - Path::GuildsIdWelcomeScreen(..) => "Guild welcome screen", - Path::GuildsIdWidget(..) => "Guild widget", - Path::GuildsTemplatesCode(..) => "Specific guild template", - Path::InteractionCallback(..) => "Interaction callback", - Path::InvitesCode => "Invite info", - Path::OauthApplicationsMe => "Current application info", - Path::StageInstances => "Stage instances", - Path::StickerPacks => "Sticker packs", - Path::Stickers => "Stickers", - Path::UsersId => "User info", - Path::UsersIdChannels => "User channels", - Path::UsersIdConnections => "User connections", - Path::UsersIdGuilds => "User in guild", - Path::UsersIdGuildsId => "Guild from user", - Path::UsersIdGuildsIdMember => "Member of a guild", - Path::VoiceRegions => "Voice region list", - Path::WebhooksIdToken(..) => "Webhook", - Path::WebhooksIdTokenMessagesId(..) => "Specific webhook message", - _ => "Unknown path!", - } -} - -fn normalize_path(request_path: &str) -> (&str, &str) { - if let Some(trimmed_path) = request_path.strip_prefix("/api") { - if let Some(maybe_api_version) = trimmed_path.split('/').nth(1) { - if let Some(version_number) = maybe_api_version.strip_prefix('v') { - if version_number.parse::().is_ok() { - let len = "/api/v".len() + version_number.len(); - return (&request_path[..len], &request_path[len..]); - }; - }; - } - - ("/api", trimmed_path) - } else { - ("/api", request_path) - } -} - async fn handle_request( client: Client, Incoming>, - ratelimiter: InMemoryRatelimiter, + ratelimiter: RateLimiter, token: String, mut request: Request, ) -> Result>, RequestError> { trace!("Incoming request: {:?}", request); - let (method, m) = match *request.method() { - HttpMethod::DELETE => (Method::Delete, "DELETE"), - HttpMethod::GET => (Method::Get, "GET"), - HttpMethod::PATCH => (Method::Patch, "PATCH"), - HttpMethod::POST => (Method::Post, "POST"), - HttpMethod::PUT => (Method::Put, "PUT"), + let method = match *request.method() { + HttpMethod::DELETE => Method::Delete, + HttpMethod::GET => Method::Get, + HttpMethod::PATCH => Method::Patch, + HttpMethod::POST => Method::Post, + HttpMethod::PUT => Method::Put, _ => { - error!("Unsupported HTTP method in request, {}", request.method()); return Err(RequestError::InvalidMethod { method: request.into_parts().0.method, }); } }; - let request_path = request.uri().path().to_owned(); - - let (api_path, trimmed_path) = normalize_path(&request_path); - - let path = match Path::try_from((method, trimmed_path)) { - Ok(path) => path, - Err(e) => { - error!( - "Failed to parse path for {:?} {}: {:?}", - method, trimmed_path, e - ); - return Err(RequestError::InvalidPath { source: e }); - } - }; - - let p = path_name(&path); - - let header_sender = match ratelimiter.wait_for_ticket(path).await { - Ok(sender) => sender, - Err(e) => { - error!("Failed to receive ticket for ratelimiting: {:?}", e); - return Err(RequestError::AcquiringTicket { source: e }); - } - }; + let mut segments = request.uri().path().split("/").skip_while(|item| { + matches!(*item, "" | "api") + || item + .strip_prefix("v") + .is_some_and(|s| s.parse::().is_ok()) + }); + let mut path = segments.next().map_or(String::new(), ToOwned::to_owned); + segments.for_each(|s| { + path.push('/'); + path.push_str(s); + }); + let endpoint = Endpoint { method, path }; + + let permit = ratelimiter.acquire(endpoint).await; request.headers_mut().insert( - AUTHORIZATION, + header::AUTHORIZATION, HeaderValue::from_bytes(token.as_bytes()) .expect("strings are guaranteed to be valid utf-8"), ); request .headers_mut() - .insert(HOST, HeaderValue::from_static("discord.com")); + .insert(header::HOST, HeaderValue::from_static("discord.com")); // Remove forbidden HTTP/2 headers // https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.2 - request.headers_mut().remove(CONNECTION); + request.headers_mut().remove(header::CONNECTION); request.headers_mut().remove("keep-alive"); request.headers_mut().remove("proxy-connection"); - request.headers_mut().remove(TRANSFER_ENCODING); - request.headers_mut().remove(UPGRADE); + request.headers_mut().remove(header::TRANSFER_ENCODING); + request.headers_mut().remove(header::UPGRADE); - let mut uri_string = format!("https://discord.com{}{}", api_path, trimmed_path); + let prefix = if request.uri().path().starts_with("/api") { + "" + } else { + "/api" + }; + let mut uri_string = format!("https://discord.com{prefix}{}", request.uri().path()); if let Some(query) = request.uri().query() { uri_string.push('?'); uri_string.push_str(query); } - let uri = match Uri::from_str(&uri_string) { - Ok(uri) => uri, - Err(e) => { - error!("Failed to create URI for requesting Discord API: {:?}", e); - return Err(RequestError::InvalidURI { source: e }); - } - }; + let uri = Uri::from_str(&uri_string).expect("assembled from valid uri"); *request.uri_mut() = uri; - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] let start = Instant::now(); - let resp = match client.request(request).await { - Ok(response) => response, - Err(e) => { - error!("Error when requesting the Discord API: {:?}", e); - return Err(RequestError::RequestIssue { source: e }); - } - }; - - let ratelimit_headers = RatelimitHeaders::from_pairs( - resp.headers() - .into_iter() - .map(|(k, v)| (k.as_str(), v.as_bytes())), - ) - .ok(); - - if header_sender.headers(ratelimit_headers).is_err() { - error!("Error when sending ratelimit headers to ratelimiter"); - }; + let resp = client + .request(request) + .await + .map_err(|source| RequestError::RequestIssue { source })?; - #[cfg(feature = "expose-metrics")] let end = Instant::now(); + let scope = resp + .headers() + .get(RateLimitHeaders::SCOPE) + .map(HeaderValue::as_bytes); + let headers = parse_headers(resp.headers(), scope, end); + permit.complete(headers); + trace!("Response: {:?}", resp); - let status = resp.status(); - #[cfg(feature = "expose-metrics")] + #[cfg(feature = "metrics")] { - let scope = resp - .headers() - .get("X-RateLimit-Scope") - .and_then(|header| header.to_str().ok()) - .unwrap_or("") - .to_string(); - histogram!(METRIC_KEY.as_str(), "method"=>m.to_string(), "route"=>p, "status"=>status.to_string(), "scope" => scope) + let scope = scope + .and_then(|v| String::from_utf8(v.to_owned()).ok()) + .unwrap_or(String::new()); + let route = uri_string.split_off("https://discord.com".len()); + histogram!(METRIC_KEY.as_ref(), "method"=>method.name(), "route"=>route, "status"=>resp.status().to_string(), "scope" => scope) .record(end - start); } - debug!("{} {} ({}): {}", m, p, request_path, status); - let (parts, body) = resp.into_parts(); let boxed_body = BoxBody::new(body); let resp = Response::from_parts(parts, boxed_body); @@ -446,11 +307,11 @@ async fn handle_request( Ok(resp) } -#[cfg(feature = "expose-metrics")] +#[cfg(feature = "metrics")] fn handle_metrics(handle: Arc) -> Response> { Response::builder() .header( - CONTENT_TYPE, + header::CONTENT_TYPE, HeaderValue::from_static("text/plain; version=0.0.4"), ) .body(BoxBody::new( @@ -459,19 +320,76 @@ fn handle_metrics(handle: Arc) -> Response(key: &str) -> Option { - env::var_os(key).and_then(|value| match value.into_string() { - Ok(s) => { - if let Ok(t) = s.parse() { - Some(t) - } else { - warn!("Unable to parse {}, proceeding with defaults", key); - None - } - } - Err(s) => { - warn!("{} is not UTF-8: {:?}", key, s); +fn parse_headers( + headers: &HeaderMap, + scope: Option<&[u8]>, + start: Instant, +) -> Option { + match scope { + Some(b"global") => { + info!("globally rate limited"); + None } - }) + Some(b"shared") => { + let bucket = headers.get(RateLimitHeaders::BUCKET)?.as_bytes().to_vec(); + let retry_after = headers + .get(header::RETRY_AFTER)? + .to_str() + .ok()? + .parse() + .ok()?; + + Some(RateLimitHeaders { + bucket, + limit: 0, + remaining: 0, + reset_at: start + Duration::from_secs(retry_after), + }) + } + Some(b"user") => { + let bucket = headers.get(RateLimitHeaders::BUCKET)?.as_bytes().to_vec(); + let limit = headers + .get(RateLimitHeaders::LIMIT)? + .to_str() + .ok()? + .parse() + .ok()?; + let remaining = headers + .get(RateLimitHeaders::REMAINING)? + .to_str() + .ok()? + .parse() + .ok()?; + let reset_after = headers + .get(RateLimitHeaders::RESET_AFTER)? + .to_str() + .ok()? + .parse() + .ok()?; + + Some(RateLimitHeaders { + bucket, + limit, + remaining, + reset_at: start + Duration::from_secs_f32(reset_after), + }) + } + _ => None, + } +} + +fn parse_env(key: &str) -> Result, Box> +where + T: FromStr, + ::Err: Error + 'static, +{ + match env::var(key) { + Ok(s) => match s.parse() { + Ok(v) => Ok(Some(v)), + Err(e) => Err(e.into()), + }, + Err(env::VarError::NotPresent) => Ok(None), + Err(e @ env::VarError::NotUnicode(_)) => Err(e.into()), + } } diff --git a/src/ratelimiter_map.rs b/src/ratelimiter_map.rs index e54dd5c..7c82f21 100644 --- a/src/ratelimiter_map.rs +++ b/src/ratelimiter_map.rs @@ -1,17 +1,15 @@ use crate::expiring_lru::{Builder, ExpiringLru}; use tokio::time::Duration; -use twilight_http_ratelimiting::InMemoryRatelimiter; - -use crate::parse_env; +use twilight_http_ratelimiting::RateLimiter; pub struct RatelimiterMap { - default: InMemoryRatelimiter, + default: RateLimiter, default_token: String, - inner: ExpiringLru, + inner: ExpiringLru, } impl RatelimiterMap { - pub fn new(mut default_token: String) -> Self { + pub fn new(mut default_token: String, timeout: Duration, max_size: Option) -> Self { let is_bot = default_token.starts_with("Bot "); let is_bearer = default_token.starts_with("Bearer "); @@ -21,17 +19,15 @@ impl RatelimiterMap { default_token.insert_str(0, "Bot "); } - let expiration = Duration::from_secs(parse_env("CLIENT_DECAY_TIMEOUT").unwrap_or(3600)); - - let mut builder = Builder::new().expiration(expiration); + let mut builder = Builder::new().expiration(timeout); - if let Some(max_size) = parse_env("CLIENT_CACHE_MAX_SIZE") { + if let Some(max_size) = max_size { builder = builder.max_size(max_size); } let inner = builder.build(); - let default = InMemoryRatelimiter::new(); + let default = RateLimiter::default(); Self { default, @@ -40,14 +36,14 @@ impl RatelimiterMap { } } - pub fn get_or_insert(&self, token: Option<&str>) -> (InMemoryRatelimiter, String) { + pub fn get_or_insert(&self, token: Option<&str>) -> (RateLimiter, String) { if let Some(token) = token { if token == self.default_token { (self.default.clone(), self.default_token.clone()) } else if let Some(entry) = self.inner.get(token) { (entry.value().clone(), token.to_string()) } else { - let ratelimiter = InMemoryRatelimiter::new(); + let ratelimiter = RateLimiter::default(); self.inner.insert(token.to_string(), ratelimiter.clone());