From 1490f8e5e6a69e7fb2e8eae2a24f4e0241efb67b Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Wed, 4 Jun 2025 14:45:10 +0200 Subject: [PATCH 01/12] TLS certificate generation --- Cargo.lock | 1243 ++++++++++++++++++++++++++++------------ Cargo.toml | 13 + benches/tls.rs | 35 ++ src/lib.rs | 2 + src/mock_server/mod.rs | 2 + src/mock_server/tls.rs | 201 +++++++ 6 files changed, 1142 insertions(+), 354 deletions(-) create mode 100644 benches/tls.rs create mode 100644 src/mock_server/tls.rs diff --git a/Cargo.lock b/Cargo.lock index c6bee63..8fd596f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,14 +9,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] name = "actix-rt" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" dependencies = [ "actix-macros", "futures-core", @@ -24,28 +24,31 @@ dependencies = [ ] [[package]] -name = "addr2line" -version = "0.24.2" +name = "aho-corasick" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ - "gimli", + "memchr", ] [[package]] -name = "adler2" -version = "2.0.1" +name = "anes" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] -name = "aho-corasick" -version = "1.1.3" +name = "anstyle" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "assert-json-diff" @@ -64,7 +67,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote", - "syn 1.0.109", + "syn 1.0.58", ] [[package]] @@ -74,15 +77,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener 2.5.3", + "event-listener 2.5.1", "futures-core", ] [[package]] name = "async-channel" -version = "2.5.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -110,7 +113,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.5.0", + "async-channel 2.3.1", "async-executor", "async-io", "async-lock", @@ -122,9 +125,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock", "cfg-if", @@ -135,16 +138,17 @@ dependencies = [ "polling", "rustix", "slab", - "windows-sys 0.60.2", + "tracing", + "windows-sys 0.59.0", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 5.4.1", + "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] @@ -190,24 +194,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] -name = "backtrace" -version = "0.3.75" +name = "base64" +version = "0.21.7" 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", -] +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" @@ -217,17 +212,23 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "blocking" -version = "1.6.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.5.0", + "async-channel 2.3.1", "async-task", "futures-io", "futures-lite", @@ -236,9 +237,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "bytes" @@ -246,20 +247,78 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" -version = "1.2.34" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "shlex", ] [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "concurrent-queue" @@ -272,9 +331,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", "libc", @@ -282,9 +341,64 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.7" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] [[package]] name = "crossbeam-utils" @@ -292,13 +406,20 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + [[package]] name = "deadpool" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ "deadpool-runtime", + "lazy_static", "num_cpus", "tokio", ] @@ -309,6 +430,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -317,14 +447,20 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] +[[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" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" dependencies = [ "cfg-if", ] @@ -337,25 +473,25 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] name = "event-listener" -version = "2.5.3" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -368,7 +504,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.1", + "event-listener 5.4.0", "pin-project-lite", ] @@ -401,9 +537,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -458,15 +594,17 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.6.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +checksum = "9c1155db57329dca6d018b61e76b1488ce9a2e5e44028cac420a5898f4fcef63" dependencies = [ "fastrand", "futures-core", "futures-io", + "memchr", "parking", "pin-project-lite", + "waker-fn", ] [[package]] @@ -477,7 +615,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] @@ -512,33 +650,15 @@ dependencies = [ [[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.1+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.3" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "gloo-timers" version = "0.3.0" @@ -553,16 +673,35 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +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.3", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http", + "http 1.3.1", "indexmap", "slab", "tokio", @@ -570,17 +709,47 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" + +[[package]] +name = "http" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +dependencies = [ + "bytes", + "fnv", + "itoa 0.4.7", +] [[package]] name = "http" @@ -590,7 +759,17 @@ checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.15", +] + +[[package]] +name = "http-body" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" +dependencies = [ + "bytes", + "http 0.2.3", ] [[package]] @@ -600,7 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.3.1", ] [[package]] @@ -611,8 +790,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "pin-project-lite", ] @@ -628,6 +807,30 @@ 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.3", + "http-body 0.4.0", + "httparse", + "httpdate", + "itoa 1.0.15", + "pin-project-lite", + "socket2 0.5.9", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.7.0" @@ -638,12 +841,12 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2", - "http", - "http-body", + "h2 0.4.10", + "http 1.3.1", + "http-body 1.0.1", "httparse", "httpdate", - "itoa", + "itoa 1.0.15", "pin-project-lite", "pin-utils", "smallvec", @@ -657,13 +860,33 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.3.1", + "hyper 1.7.0", "hyper-util", - "rustls", + "rustls 0.23.27", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.2", + "tower-service", +] + +[[package]] +name = "hyper-server" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2aaf9c44c3bc702a0a3266ab6d1933d9083f2d85ab3701b6d14c9acb048bd4" +dependencies = [ + "arc-swap", + "bytes", + "futures-util", + "http 0.2.3", + "http-body 0.4.0", + "hyper 0.14.32", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile", + "tokio", + "tokio-rustls 0.24.1", "tower-service", ] @@ -675,7 +898,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -685,23 +908,23 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.5.9", "system-configuration", "tokio", "tower-service", @@ -797,9 +1020,9 @@ dependencies = [ [[package]] name = "idna" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", @@ -818,25 +1041,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -853,6 +1065,32 @@ dependencies = [ "serde", ] +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +dependencies = [ + "hermit-abi 0.5.0", + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + [[package]] name = "itoa" version = "1.0.15" @@ -878,11 +1116,17 @@ dependencies = [ "log", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" -version = "0.2.175" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "linux-raw-sys" @@ -898,11 +1142,10 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ - "autocfg", "scopeguard", ] @@ -917,34 +1160,25 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.52.0", ] [[package]] @@ -965,22 +1199,28 @@ dependencies = [ ] [[package]] -name = "num_cpus" -version = "1.17.0" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "hermit-abi", - "libc", + "autocfg", ] [[package]] -name = "object" -version = "0.36.7" +name = "num_cpus" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ - "memchr", + "hermit-abi 0.1.18", + "libc", ] [[package]] @@ -989,13 +1229,19 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "openssl" version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags", + "bitflags 2.9.0", "cfg-if", "foreign-types", "libc", @@ -1012,14 +1258,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" @@ -1035,15 +1281,15 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1051,22 +1297,32 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.11", "smallvec", "windows-targets 0.52.6", ] +[[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.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" @@ -1093,22 +1349,51 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] [[package]] name = "polling" -version = "3.10.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.5.0", "pin-project-lite", "rustix", - "windows-sys 0.60.2", + "tracing", + "windows-sys 0.59.0", ] [[package]] @@ -1120,11 +1405,23 @@ 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.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -1139,18 +1436,94 @@ dependencies = [ ] [[package]] -name = "r-efi" -version = "5.3.0" +name = "rand" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "yasna", +] + +[[package]] +name = "redox_syscall" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570" +dependencies = [ + "bitflags 1.2.1", +] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ - "bitflags", + "bitflags 2.9.0", ] [[package]] @@ -1182,21 +1555,30 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", - "h2", - "http", - "http-body", + "h2 0.4.10", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-rustls", "hyper-tls", "hyper-util", @@ -1230,58 +1612,80 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom", "libc", "untrusted", "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 = "rustix" -version = "1.0.8" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.3", "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" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "zeroize", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -1290,38 +1694,58 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ - "windows-sys 0.59.0", + "lazy_static", + "winapi", ] [[package]] name = "scopeguard" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] [[package]] name = "security-framework" -version = "2.11.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" dependencies = [ - "bitflags", + "bitflags 1.2.1", "core-foundation", "core-foundation-sys", "libc", @@ -1330,9 +1754,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" dependencies = [ "core-foundation-sys", "libc", @@ -1355,17 +1779,16 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" dependencies = [ - "itoa", - "memchr", + "itoa 0.4.7", "ryu", "serde", ] @@ -1377,7 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.15", "ryu", "serde", ] @@ -1390,18 +1813,21 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" dependencies = [ "libc", ] [[package]] name = "slab" -version = "0.4.11" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" @@ -1411,12 +1837,22 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.0" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", ] [[package]] @@ -1433,20 +1869,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "unicode-xid", ] [[package]] name = "syn" -version = "2.0.106" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1470,7 +1906,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] @@ -1479,7 +1915,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags", + "bitflags 2.9.0", "core-foundation", "system-configuration-sys", ] @@ -1496,17 +1932,37 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.21.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix", - "windows-sys 0.60.2", + "cfg-if", + "libc", + "rand", + "redox_syscall 0.2.4", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "time" +version = "0.3.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", ] +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + [[package]] name = "tinystr" version = "0.8.1" @@ -1517,62 +1973,79 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[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", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2", + "socket2 0.6.1", "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", - "syn 2.0.106", + "syn 2.0.100", ] [[package]] name = "tokio-native-tls" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls", + "rustls 0.23.27", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", @@ -1602,11 +2075,11 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags", + "bitflags 2.9.0", "bytes", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -1638,18 +2111,18 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "try-lock" -version = "0.2.5" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "unicode-ident" @@ -1657,6 +2130,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + [[package]] name = "untrusted" version = "0.9.0" @@ -1665,14 +2144,13 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -1689,33 +2167,41 @@ checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" -version = "0.2.15" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" [[package]] -name = "want" -version = "0.3.1" +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ - "try-lock", + "same-file", + "winapi-util", ] [[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +name = "want" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" @@ -1739,19 +2225,18 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" dependencies = [ "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", "web-sys", ] @@ -1774,7 +2259,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1798,19 +2283,56 @@ dependencies = [ "wasm-bindgen", ] +[[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-link" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -1821,7 +2343,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -1830,7 +2352,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -1857,7 +2379,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -1878,19 +2409,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" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 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", + "windows-link 0.2.1", + "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]] @@ -1901,9 +2432,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" @@ -1913,9 +2444,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" @@ -1925,9 +2456,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" @@ -1937,9 +2468,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" @@ -1949,9 +2480,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" @@ -1961,9 +2492,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" @@ -1973,9 +2504,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" @@ -1985,9 +2516,9 @@ 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 = "wiremock" @@ -1996,38 +2527,42 @@ dependencies = [ "actix-rt", "assert-json-diff", "async-std", - "base64", + "base64 0.22.1", + "criterion", "deadpool", "futures", - "http", + "http 1.3.1", "http-body-util", - "hyper", + "hyper 1.7.0", + "hyper-server", "hyper-util", "log", "once_cell", + "rcgen", "regex", "reqwest", + "rustls-pki-types", "serde", "serde_json", "tokio", "url", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - [[package]] name = "writeable" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + [[package]] name = "yoke" version = "0.8.0" @@ -2048,7 +2583,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", "synstructure", ] @@ -2069,7 +2604,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", "synstructure", ] @@ -2092,9 +2627,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -2109,5 +2644,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.100", ] diff --git a/Cargo.toml b/Cargo.toml index 24209da..4a4f9f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,9 +40,22 @@ assert-json-diff = "2.0.2" base64 = "0.22" url = "2.5" +rcgen = { version = "0.13.2", optional = true } +hyper-server = { version = "0.6.0", optional = true } +rustls-pki-types = { version = "1.11.0", optional = true } + [dev-dependencies] async-std = { version = "1.13.2", features = ["attributes", "tokio1"] } reqwest = { version = "0.12.23", features = ["json"] } tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] } actix-rt = "2.10.0" serde = { version = "1", features = ["derive"] } +criterion = "0.5.1" + +[features] +tls = ["rcgen", "hyper-server/tls-rustls", "rustls-pki-types"] +# default = ["tls"] + +[[bench]] +name = "tls" +harness = false diff --git a/benches/tls.rs b/benches/tls.rs new file mode 100644 index 0000000..286f87b --- /dev/null +++ b/benches/tls.rs @@ -0,0 +1,35 @@ +#[cfg(feature = "tls")] +use criterion::{Criterion, criterion_group, criterion_main}; + +#[cfg(feature = "tls")] +use wiremock::tls::MockTlsCertificates; + +#[cfg(feature = "tls")] +// On the good old M1 processor it takes ~77 µs +pub fn tls_mock_tls_certificates_new(c: &mut Criterion) { + c.bench_function("MockTlsCertificates::new", |b| { + b.iter(|| MockTlsCertificates::new()) + }); +} + +#[cfg(feature = "tls")] +// TODO measure with a charger connected +pub fn tls_mock_tls_certificates_client(c: &mut Criterion) { + let mock_tls_certificates = MockTlsCertificates::new(); + c.bench_function("MockTlsCertificates::gen_client", |b| { + b.iter(|| mock_tls_certificates.gen_client("user@myserver.test")) + }); +} + +#[cfg(feature = "tls")] +criterion_group!( + benches, + tls_mock_tls_certificates_new, + tls_mock_tls_certificates_client +); + +#[cfg(feature = "tls")] +criterion_main!(benches); + +#[cfg(not(feature = "tls"))] +fn main() {} diff --git a/src/lib.rs b/src/lib.rs index c0b2efd..803a397 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,6 +158,8 @@ mod verification; pub type ErrorResponse = Box; pub use mock::{Match, Mock, MockBuilder, Times}; +#[cfg(feature = "tls")] +pub use mock_server::tls; pub use mock_server::{MockGuard, MockServer, MockServerBuilder}; pub use request::{BodyPrintLimit, Request}; pub use respond::Respond; diff --git a/src/mock_server/mod.rs b/src/mock_server/mod.rs index a90d108..306beee 100644 --- a/src/mock_server/mod.rs +++ b/src/mock_server/mod.rs @@ -15,6 +15,8 @@ mod builder; mod exposed_server; mod hyper; mod pool; +#[cfg(feature = "tls")] +pub mod tls; pub use bare_server::MockGuard; pub use builder::MockServerBuilder; diff --git a/src/mock_server/tls.rs b/src/mock_server/tls.rs new file mode 100644 index 0000000..0c7babb --- /dev/null +++ b/src/mock_server/tls.rs @@ -0,0 +1,201 @@ +//! Certificate generation. +//! +//! Based on https://github.com/rustls/rustls/blob/main/rustls/examples/internal/test_ca.rs +use std::{ + convert::{TryFrom as _, TryInto as _}, + fmt::Display, + net::IpAddr, + str::FromStr as _, + sync::atomic::{AtomicU64, Ordering}, +}; + +use rcgen::{ + BasicConstraints, Certificate, CertificateParams, DistinguishedName, ExtendedKeyUsagePurpose, + Ia5String, IsCa, KeyPair, KeyUsagePurpose, PKCS_ED25519, SanType, SerialNumber, + SignatureAlgorithm, +}; + +use rustls_pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject}; + +pub const DEFAULT_ALGORITHM: &SignatureAlgorithm = &PKCS_ED25519; + +const ISSUER_KEY_USAGES: &[KeyUsagePurpose; 7] = &[ + KeyUsagePurpose::CrlSign, + KeyUsagePurpose::KeyCertSign, + KeyUsagePurpose::DigitalSignature, + KeyUsagePurpose::ContentCommitment, + KeyUsagePurpose::KeyEncipherment, + KeyUsagePurpose::DataEncipherment, + KeyUsagePurpose::KeyAgreement, +]; + +const ISSUER_EXTENDED_KEY_USAGES: &[ExtendedKeyUsagePurpose; 2] = &[ + ExtendedKeyUsagePurpose::ServerAuth, + ExtendedKeyUsagePurpose::ClientAuth, +]; + +const EE_KEY_USAGES: &[KeyUsagePurpose; 2] = &[ + KeyUsagePurpose::DigitalSignature, + KeyUsagePurpose::ContentCommitment, +]; + +static SERIAL_NUMBER: AtomicU64 = AtomicU64::new(1); + +pub struct MockTlsCertificates { + root_cert: Certificate, + server_cert: Certificate, + server_key: KeyPair, +} + +impl MockTlsCertificates { + /// Creates an instance with "localhost" and "127.0.0.1" as hostnames. + // On the good old M1 processor it takes ~77 µs + pub fn new() -> Self { + Self::with_hostnames(default_hostnames()) + } + + /// Creates an instance with custom hostnames and IPs. + pub fn with_hostnames(hostnames: impl Into>) -> Self { + let (root_cert, root_key) = gen_root_cert(DEFAULT_ALGORITHM); + // We do not bother to have an intermediate certificate because CAs use them for flexibility only. + let (server_cert, server_key) = + gen_server_cert(&root_cert, &root_key, DEFAULT_ALGORITHM, hostnames.into()); + + Self { + root_cert, + server_cert, + server_key, + } + } + + pub fn get_root_cert(&self) -> &Certificate { + &self.root_cert + } + + pub fn server_cert_der(&self) -> CertificateDer { + self.server_cert.der().clone() + } + + pub fn server_private_key_der(&self) -> PrivateKeyDer<'_> { + self.server_key + .serialize_der() + .try_into() + .expect("Failed to deserialize a serialized key") + } + + pub fn gen_client<'s>(&'s self, email: &str) -> (PrivateKeyDer<'s>, CertificateDer) { + let (client_cert, client_key) = gen_client_cert( + &self.server_cert, + &self.server_key, + DEFAULT_ALGORITHM, + email, + ); + let private_key_der = client_key + .serialize_der() + .try_into() + .expect("Failed to deserialize a serialized key"); + let client_cert_der = client_cert.der().clone(); + (private_key_der, client_cert_der) + } +} + +// The methods are not const, so we use a function. +fn default_hostnames() -> Vec { + vec![ + SanType::DnsName(Ia5String::try_from("localhost".to_string()).unwrap()), + SanType::IpAddress(IpAddr::from_str("127.0.0.1").unwrap()), + ] +} + +fn gen_root_cert(alg: &'static SignatureAlgorithm) -> (Certificate, KeyPair) { + let keypair = KeyPair::generate_for(alg).unwrap(); + let serial = SERIAL_NUMBER.fetch_add(1, Ordering::SeqCst); + + let mut params = CertificateParams::default(); + params.distinguished_name = root_common_name(serial); + params.use_authority_key_identifier_extension = true; + params.serial_number = Some(SerialNumber::from_slice(&serial.to_be_bytes()[..])); + + params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); + params.key_usages = ISSUER_KEY_USAGES.to_vec(); + params.extended_key_usages = ISSUER_EXTENDED_KEY_USAGES.to_vec(); + + let cert = params.self_signed(&keypair).unwrap(); + (cert, keypair) +} + +fn gen_server_cert( + signer_cert: &Certificate, + signer_key: &KeyPair, + alg: &'static SignatureAlgorithm, + hostnames: Vec, +) -> (Certificate, KeyPair) { + let keypair = KeyPair::generate_for(alg).unwrap(); + let serial = SERIAL_NUMBER.fetch_add(1, Ordering::SeqCst); + + let mut params = CertificateParams::default(); + params.distinguished_name = server_common_name(serial); + params.use_authority_key_identifier_extension = true; + params.serial_number = Some(SerialNumber::from_slice(&serial.to_be_bytes()[..])); + params.is_ca = IsCa::NoCa; + params.key_usages = EE_KEY_USAGES.to_vec(); + params.subject_alt_names = hostnames; + + let cert = params.signed_by(&keypair, signer_cert, signer_key).unwrap(); + (cert, keypair) +} + +fn gen_client_cert( + signer_cert: &Certificate, + signer_key: &KeyPair, + alg: &'static SignatureAlgorithm, + email: &str, +) -> (Certificate, KeyPair) { + let keypair = KeyPair::generate_for(alg).unwrap(); + let serial = SERIAL_NUMBER.fetch_add(1, Ordering::SeqCst); + + let mut params = CertificateParams::default(); + params.distinguished_name = client_common_name(serial, email); + params.use_authority_key_identifier_extension = true; + params.serial_number = Some(SerialNumber::from_slice(&serial.to_be_bytes()[..])); + params.is_ca = IsCa::NoCa; + params.key_usages = EE_KEY_USAGES.to_vec(); + params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ClientAuth]; + params.subject_alt_names = vec![SanType::Rfc822Name( + Ia5String::try_from(email.to_string()) + .unwrap_or_else(|_| panic!("Invalid email: {}", email)), + )]; + + let cert = params.signed_by(&keypair, signer_cert, signer_key).unwrap(); + (cert, keypair) +} + +fn root_common_name(id: impl Display) -> DistinguishedName { + let mut distinguished_name = DistinguishedName::new(); + distinguished_name.push( + rcgen::DnType::CommonName, + format!("Test-only temporary root CA #{id}"), + ); + + distinguished_name +} + +fn server_common_name(id: impl Display) -> DistinguishedName { + let mut distinguished_name = DistinguishedName::new(); + distinguished_name.push( + rcgen::DnType::CommonName, + format!("Test-only temporary server #{id}"), + ); + + distinguished_name +} + +fn client_common_name(id: impl Display, name: &str) -> DistinguishedName { + let mut distinguished_name = DistinguishedName::new(); + distinguished_name.push( + rcgen::DnType::CommonName, + format!("Test-only temporary client {name} #{id}"), + ); + + distinguished_name +} From add9a5c7455d91d9688e2ae92c4bb2b8b2562fdc Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Sun, 15 Jun 2025 12:51:47 +0200 Subject: [PATCH 02/12] Bare server generalized implementation It gets an additional argument `acceptor` that can represent either ordinary TCP or TLS connection. --- Cargo.toml | 2 +- src/mock_server/bare_server.rs | 26 ++++++++++-- src/mock_server/builder.rs | 50 ++++++++++++++++++++-- src/mock_server/hyper.rs | 76 +++++++++++++++++++++++++++------- src/mock_server/pool.rs | 2 +- src/mock_server/tls.rs | 10 +++-- 6 files changed, 136 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4a4f9f5..2779562 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ futures = "0.3.31" http = "1.3" http-body-util = "0.1" hyper = { version = "1.7", features = ["full"] } +hyper-server = "0.6.0" hyper-util = { version = "0.1", features = [ "tokio", "server", @@ -41,7 +42,6 @@ base64 = "0.22" url = "2.5" rcgen = { version = "0.13.2", optional = true } -hyper-server = { version = "0.6.0", optional = true } rustls-pki-types = { version = "1.11.0", optional = true } [dev-dependencies] diff --git a/src/mock_server/bare_server.rs b/src/mock_server/bare_server.rs index b70bc57..61628ce 100644 --- a/src/mock_server/bare_server.rs +++ b/src/mock_server/bare_server.rs @@ -1,15 +1,17 @@ -use crate::mock_server::hyper::run_server; +use crate::mock_server::hyper::{HyperRequestHandler, run_server}; use crate::mock_set::MockId; use crate::mock_set::MountedMockSet; use crate::request::BodyPrintLimit; use crate::{ErrorResponse, Request, mock::Mock, verification::VerificationOutcome}; use http_body_util::Full; use hyper::body::Bytes; +use hyper_server::accept::Accept; use std::fmt::{Debug, Write}; use std::net::{SocketAddr, TcpListener, TcpStream}; use std::pin::pin; use std::sync::Arc; use std::sync::atomic::AtomicBool; +use tokio::io::{AsyncRead, AsyncWrite}; use tokio::sync::Notify; use tokio::sync::RwLock; @@ -52,11 +54,27 @@ impl MockServerState { impl BareMockServer { /// Start a new instance of a `BareMockServer` listening on the specified /// [`TcpListener`]. - pub(super) async fn start( + pub(super) async fn start( listener: TcpListener, request_recording: RequestRecording, body_print_limit: BodyPrintLimit, - ) -> Self { + acceptor: A, + ) -> Self + where + A: Accept + Send + Clone + 'static, + >::Future: Send, + >::Stream: + Unpin + Send + AsyncWrite + AsyncRead + 'static, + >::Service: + hyper::service::Service, Response = http::Response>> + + Send, + <>::Service as hyper::service::Service< + http::Request, + >>::Error: Send + Sync + Into> + 'static, + <>::Service as hyper::service::Service< + http::Request, + >>::Future: Send + 'static, + { let (shutdown_trigger, shutdown_receiver) = tokio::sync::watch::channel(()); let received_requests = match request_recording { RequestRecording::Enabled => Some(Vec::new()), @@ -73,7 +91,7 @@ impl BareMockServer { let server_state = state.clone(); std::thread::spawn(move || { - let server_future = run_server(listener, server_state, shutdown_receiver); + let server_future = run_server(listener, server_state, shutdown_receiver, acceptor); let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index 4818665..340a04e 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -2,10 +2,12 @@ use crate::MockServer; use crate::mock_server::bare_server::{BareMockServer, RequestRecording}; use crate::mock_server::exposed_server::InnerServer; use crate::request::{BODY_PRINT_LIMIT, BodyPrintLimit}; +#[cfg(feature = "tls")] +use hyper_server::tls_rustls::RustlsConfig; use std::env; use std::net::TcpListener; -/// A builder providing a fluent API to assemble a [`MockServer`] step-by-step. +/// A builder providing a fluent API to assemble a [`MockServer`] step-by-step. /// Use [`MockServer::builder`] to get started. pub struct MockServerBuilder { listener: Option, @@ -100,7 +102,9 @@ impl MockServerBuilder { } /// Finalise the builder to get an instance of a [`BareMockServer`]. - pub(super) async fn build_bare(self) -> BareMockServer { + pub(super) async fn build_bare_http(self) -> BareMockServer { + use hyper_server::accept::DefaultAcceptor; + let listener = if let Some(listener) = self.listener { listener } else { @@ -111,11 +115,49 @@ impl MockServerBuilder { } else { RequestRecording::Disabled }; - BareMockServer::start(listener, recording, self.body_print_limit).await + BareMockServer::start( + listener, + recording, + self.body_print_limit, + DefaultAcceptor::new(), + ) + .await + } + + /// Finalise the builder to get an instance of a [`BareMockServer`]. + #[cfg(feature = "tls")] + pub(super) async fn build_bare_https(self, rustls_config: RustlsConfig) -> BareMockServer { + use hyper_server::tls_rustls::RustlsAcceptor; + + let listener = if let Some(listener) = self.listener { + listener + } else { + TcpListener::bind("127.0.0.1:0").expect("Failed to bind an OS port for a mock server.") + }; + let recording = if self.record_incoming_requests { + RequestRecording::Enabled + } else { + RequestRecording::Disabled + }; + BareMockServer::start( + listener, + recording, + self.body_print_limit, + RustlsAcceptor::new(rustls_config), + ) + .await } /// Finalise the builder and launch the [`MockServer`] instance! pub async fn start(self) -> MockServer { - MockServer::new(InnerServer::Bare(self.build_bare().await)) + MockServer::new(InnerServer::Bare(self.build_bare_http().await)) + } + + /// Finalise the builder and launch the HTTPS [`MockServer`] instance! + #[cfg(feature = "tls")] + pub async fn start_https(self, rustls_config: RustlsConfig) -> MockServer { + MockServer::new(InnerServer::Bare( + self.build_bare_https(rustls_config).await, + )) } } diff --git a/src/mock_server/hyper.rs b/src/mock_server/hyper.rs index c0b3e91..cafc487 100644 --- a/src/mock_server/hyper.rs +++ b/src/mock_server/hyper.rs @@ -1,14 +1,18 @@ use crate::mock_server::bare_server::MockServerState; -use hyper::service::service_fn; +use futures::future::{BoxFuture, FutureExt as _}; +use http_body_util::Full; +use hyper::body::Bytes; +use hyper_server::accept::Accept; use hyper_util::rt::TokioIo; use std::sync::Arc; +use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpListener; use tokio::sync::RwLock; /// Work around a lifetime error where, for some reason, /// `Box` can't be converted to a /// `Box` -struct ErrorLifetimeCast(Box); +pub(super) struct ErrorLifetimeCast(Box); impl From for Box { fn from(value: ErrorLifetimeCast) -> Self { @@ -16,19 +20,18 @@ impl From for Box { } } -/// The actual HTTP server responding to incoming requests according to the specified mocks. -pub(super) async fn run_server( - listener: std::net::TcpListener, +#[derive(Clone)] +pub(super) struct HyperRequestHandler { server_state: Arc>, - mut shutdown_signal: tokio::sync::watch::Receiver<()>, -) { - listener - .set_nonblocking(true) - .expect("Cannot set non-blocking mode on TcpListener"); - let listener = TcpListener::from_std(listener).expect("Cannot upgrade TcpListener"); +} + +impl hyper::service::Service> for HyperRequestHandler { + type Response = hyper::Response>; + type Error = ErrorLifetimeCast; + type Future = BoxFuture<'static, Result>; - let request_handler = move |request| { - let server_state = server_state.clone(); + fn call(&self, request: hyper::Request) -> Self::Future { + let server_state = self.server_state.clone(); async move { let wiremock_request = crate::Request::from_hyper(request).await; let (response, delay) = server_state @@ -52,6 +55,37 @@ pub(super) async fn run_server( Ok::<_, ErrorLifetimeCast>(response) } + .boxed() + } +} + +/// The actual HTTP server responding to incoming requests according to the specified mocks. +pub(super) async fn run_server( + listener: std::net::TcpListener, + server_state: Arc>, + mut shutdown_signal: tokio::sync::watch::Receiver<()>, + acceptor: A, +) where + A: Accept + Send + Clone + 'static, + >::Future: Send, + >::Stream: + Unpin + Send + AsyncWrite + AsyncRead + 'static, + >::Service: + hyper::service::Service, Response = http::Response>> + + Send, + <>::Service + as hyper::service::Service>>::Error: + Send + Sync + Into> + 'static, + <>::Service + as hyper::service::Service>>::Future: Send + 'static, +{ + listener + .set_nonblocking(true) + .expect("Cannot set non-blocking mode on TcpListener"); + let listener = TcpListener::from_std(listener).expect("Cannot upgrade TcpListener"); + + let request_handler = HyperRequestHandler { + server_state: server_state.clone(), }; loop { @@ -67,14 +101,24 @@ pub(super) async fn run_server( break; } }; - let io = TokioIo::new(stream); - let request_handler = request_handler.clone(); let mut shutdown_signal = shutdown_signal.clone(); + let acceptor = acceptor.clone(); tokio::task::spawn(async move { + let accept = acceptor.accept(stream, request_handler).await; + let (stream, request_service) = match accept { + Ok((stream, service)) => (stream, service), + Err(e) => { + log::error!("Failed to accept connection: {}", e); + return; + } + }; + + let io = TokioIo::new(stream); + let http_server = hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new()); - let conn = http_server.serve_connection_with_upgrades(io, service_fn(request_handler)); + let conn = http_server.serve_connection_with_upgrades(io, request_service); tokio::pin!(conn); loop { diff --git a/src/mock_server/pool.rs b/src/mock_server/pool.rs index 1cbf5f2..00de8be 100644 --- a/src/mock_server/pool.rs +++ b/src/mock_server/pool.rs @@ -57,7 +57,7 @@ impl deadpool::managed::Manager for MockServerPoolManager { async fn create(&self) -> Result { // All servers in the pool use the default configuration - Ok(MockServer::builder().build_bare().await) + Ok(MockServer::builder().build_bare_http().await) } async fn recycle( diff --git a/src/mock_server/tls.rs b/src/mock_server/tls.rs index 0c7babb..869a324 100644 --- a/src/mock_server/tls.rs +++ b/src/mock_server/tls.rs @@ -2,10 +2,10 @@ //! //! Based on https://github.com/rustls/rustls/blob/main/rustls/examples/internal/test_ca.rs use std::{ - convert::{TryFrom as _, TryInto as _}, + convert::TryInto, fmt::Display, net::IpAddr, - str::FromStr as _, + str::FromStr, sync::atomic::{AtomicU64, Ordering}, }; @@ -102,7 +102,7 @@ impl MockTlsCertificates { // The methods are not const, so we use a function. fn default_hostnames() -> Vec { vec![ - SanType::DnsName(Ia5String::try_from("localhost".to_string()).unwrap()), + SanType::DnsName(("localhost".to_string()).try_into().unwrap()), SanType::IpAddress(IpAddr::from_str("127.0.0.1").unwrap()), ] } @@ -162,7 +162,9 @@ fn gen_client_cert( params.key_usages = EE_KEY_USAGES.to_vec(); params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ClientAuth]; params.subject_alt_names = vec![SanType::Rfc822Name( - Ia5String::try_from(email.to_string()) + email + .to_string() + .try_into() .unwrap_or_else(|_| panic!("Invalid email: {}", email)), )]; From d281e3f04e96d6fd77b6215097b403cc1a5a7d14 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Thu, 19 Jun 2025 06:42:22 +0200 Subject: [PATCH 03/12] Fix `MockServer::uri()` An HTTPS server's uri start with https protocol. --- src/mock_server/bare_server.rs | 12 ++++++++++-- src/mock_server/builder.rs | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mock_server/bare_server.rs b/src/mock_server/bare_server.rs index 61628ce..b2c54f1 100644 --- a/src/mock_server/bare_server.rs +++ b/src/mock_server/bare_server.rs @@ -24,6 +24,7 @@ use tokio::sync::RwLock; pub(crate) struct BareMockServer { state: Arc>, server_address: SocketAddr, + proto: &'static str, // When `_shutdown_trigger` gets dropped the listening server terminates gracefully. _shutdown_trigger: tokio::sync::watch::Sender<()>, } @@ -58,6 +59,7 @@ impl BareMockServer { listener: TcpListener, request_recording: RequestRecording, body_print_limit: BodyPrintLimit, + proto: &'static str, acceptor: A, ) -> Self where @@ -112,6 +114,7 @@ impl BareMockServer { Self { state, server_address, + proto, _shutdown_trigger: shutdown_trigger, } } @@ -164,7 +167,7 @@ impl BareMockServer { /// Use this method to compose uris when interacting with this instance of `BareMockServer` via /// an HTTP client. pub(crate) fn uri(&self) -> String { - format!("http://{}", self.server_address) + format!("{}://{}", self.proto, self.server_address) } /// Return the socket address of this running instance of `BareMockServer`, e.g. `127.0.0.1:4372`. @@ -191,7 +194,12 @@ impl BareMockServer { impl Debug for BareMockServer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "BareMockServer {{ address: {} }}", self.address()) + write!( + f, + "BareMockServer {{ proto: {}, address: {} }}", + self.proto, + self.address() + ) } } diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index 340a04e..1af913e 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -119,6 +119,7 @@ impl MockServerBuilder { listener, recording, self.body_print_limit, + "http", DefaultAcceptor::new(), ) .await @@ -143,6 +144,7 @@ impl MockServerBuilder { listener, recording, self.body_print_limit, + "https", RustlsAcceptor::new(rustls_config), ) .await From 1144113c737070c80e03de1cc63c75d7aa5f5fb1 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Fri, 20 Jun 2025 10:25:29 +0200 Subject: [PATCH 04/12] First working TLS test example --- Cargo.lock | 129 +++++++++++++++++++++ Cargo.toml | 6 +- benches/{tls.rs => tls_certs.rs} | 4 +- src/lib.rs | 2 +- src/mock_server/mod.rs | 2 +- src/mock_server/{tls.rs => tls_certs.rs} | 34 +++--- tests/fixtures/tls/rootCA.crt | 31 +++++ tests/fixtures/tls/server.crt | 27 +++++ tests/fixtures/tls/server.key | 28 +++++ tests/mocks.rs | 6 +- tests/tls.rs | 137 +++++++++++++++++++++++ 11 files changed, 383 insertions(+), 23 deletions(-) rename benches/{tls.rs => tls_certs.rs} (87%) rename src/mock_server/{tls.rs => tls_certs.rs} (87%) create mode 100644 tests/fixtures/tls/rootCA.crt create mode 100644 tests/fixtures/tls/server.crt create mode 100644 tests/fixtures/tls/server.key create mode 100644 tests/tls.rs diff --git a/Cargo.lock b/Cargo.lock index 8fd596f..00c9134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -268,6 +268,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "ciborium" version = "0.2.2" @@ -655,8 +661,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -868,6 +876,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.2", "tower-service", + "webpki-roots", ] [[package]] @@ -1426,6 +1435,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.27", + "socket2 0.5.9", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.27", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.9", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.40" @@ -1588,6 +1649,8 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.27", "rustls-pki-types", "serde", "serde_json", @@ -1595,6 +1658,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.2", "tower", "tower-http", "tower-service", @@ -1602,6 +1666,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", ] [[package]] @@ -1618,6 +1683,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "1.0.7" @@ -1650,6 +1721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.103.3", "subtle", @@ -1670,6 +1742,9 @@ name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -1944,6 +2019,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[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.100", +] + [[package]] name = "time" version = "0.3.41" @@ -1983,6 +2078,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.48.0" @@ -2283,6 +2393,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 2779562..08f4f30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ rustls-pki-types = { version = "1.11.0", optional = true } [dev-dependencies] async-std = { version = "1.13.2", features = ["attributes", "tokio1"] } -reqwest = { version = "0.12.23", features = ["json"] } +reqwest = { version = "0.12.23", features = ["json", "rustls-tls"] } tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] } actix-rt = "2.10.0" serde = { version = "1", features = ["derive"] } @@ -54,8 +54,8 @@ criterion = "0.5.1" [features] tls = ["rcgen", "hyper-server/tls-rustls", "rustls-pki-types"] -# default = ["tls"] +default = ["tls"] [[bench]] -name = "tls" +name = "tls_certs" harness = false diff --git a/benches/tls.rs b/benches/tls_certs.rs similarity index 87% rename from benches/tls.rs rename to benches/tls_certs.rs index 286f87b..6894390 100644 --- a/benches/tls.rs +++ b/benches/tls_certs.rs @@ -2,7 +2,7 @@ use criterion::{Criterion, criterion_group, criterion_main}; #[cfg(feature = "tls")] -use wiremock::tls::MockTlsCertificates; +use wiremock::tls_certs::MockTlsCertificates; #[cfg(feature = "tls")] // On the good old M1 processor it takes ~77 µs @@ -17,7 +17,7 @@ pub fn tls_mock_tls_certificates_new(c: &mut Criterion) { pub fn tls_mock_tls_certificates_client(c: &mut Criterion) { let mock_tls_certificates = MockTlsCertificates::new(); c.bench_function("MockTlsCertificates::gen_client", |b| { - b.iter(|| mock_tls_certificates.gen_client("user@myserver.test")) + b.iter(|| mock_tls_certificates.gen_client_cert("user@myserver.test")) }); } diff --git a/src/lib.rs b/src/lib.rs index 803a397..abef306 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,7 +159,7 @@ pub type ErrorResponse = Box; pub use mock::{Match, Mock, MockBuilder, Times}; #[cfg(feature = "tls")] -pub use mock_server::tls; +pub use mock_server::tls_certs; pub use mock_server::{MockGuard, MockServer, MockServerBuilder}; pub use request::{BodyPrintLimit, Request}; pub use respond::Respond; diff --git a/src/mock_server/mod.rs b/src/mock_server/mod.rs index 306beee..2c286be 100644 --- a/src/mock_server/mod.rs +++ b/src/mock_server/mod.rs @@ -16,7 +16,7 @@ mod exposed_server; mod hyper; mod pool; #[cfg(feature = "tls")] -pub mod tls; +pub mod tls_certs; pub use bare_server::MockGuard; pub use builder::MockServerBuilder; diff --git a/src/mock_server/tls.rs b/src/mock_server/tls_certs.rs similarity index 87% rename from src/mock_server/tls.rs rename to src/mock_server/tls_certs.rs index 869a324..75dca60 100644 --- a/src/mock_server/tls.rs +++ b/src/mock_server/tls_certs.rs @@ -9,13 +9,13 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; +use hyper_server::tls_rustls::RustlsConfig; use rcgen::{ BasicConstraints, Certificate, CertificateParams, DistinguishedName, ExtendedKeyUsagePurpose, - Ia5String, IsCa, KeyPair, KeyUsagePurpose, PKCS_ED25519, SanType, SerialNumber, - SignatureAlgorithm, + IsCa, KeyPair, KeyUsagePurpose, PKCS_ED25519, SanType, SerialNumber, SignatureAlgorithm, }; -use rustls_pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject}; +use rustls_pki_types::{CertificateDer, PrivateKeyDer}; pub const DEFAULT_ALGORITHM: &SignatureAlgorithm = &PKCS_ED25519; @@ -50,6 +50,7 @@ pub struct MockTlsCertificates { impl MockTlsCertificates { /// Creates an instance with "localhost" and "127.0.0.1" as hostnames. // On the good old M1 processor it takes ~77 µs + #[inline] pub fn new() -> Self { Self::with_hostnames(default_hostnames()) } @@ -68,12 +69,14 @@ impl MockTlsCertificates { } } + #[inline] pub fn get_root_cert(&self) -> &Certificate { &self.root_cert } - pub fn server_cert_der(&self) -> CertificateDer { - self.server_cert.der().clone() + #[inline] + pub fn server_cert_der(&self) -> &CertificateDer<'_> { + self.server_cert.der() } pub fn server_private_key_der(&self) -> PrivateKeyDer<'_> { @@ -83,19 +86,22 @@ impl MockTlsCertificates { .expect("Failed to deserialize a serialized key") } - pub fn gen_client<'s>(&'s self, email: &str) -> (PrivateKeyDer<'s>, CertificateDer) { - let (client_cert, client_key) = gen_client_cert( + #[inline] + pub fn gen_client_cert(&self, email: &str) -> (Certificate, KeyPair) { + gen_client_cert( &self.server_cert, &self.server_key, DEFAULT_ALGORITHM, email, - ); - let private_key_der = client_key - .serialize_der() - .try_into() - .expect("Failed to deserialize a serialized key"); - let client_cert_der = client_cert.der().clone(); - (private_key_der, client_cert_der) + ) + } + + pub async fn get_rustls_config(&self) -> Result { + let server_cert_der = self.server_cert.der().to_vec(); + let root_cert_der = self.get_root_cert().der().to_vec(); + let server_private_key_der = self.server_key.serialize_der(); + + RustlsConfig::from_der(vec![server_cert_der, root_cert_der], server_private_key_der).await } } diff --git a/tests/fixtures/tls/rootCA.crt b/tests/fixtures/tls/rootCA.crt new file mode 100644 index 0000000..077b394 --- /dev/null +++ b/tests/fixtures/tls/rootCA.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUHfigRD1AyensTQ5H9HiNoQZYrXQwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTA2MTkwNjQ3MTdaFw0yODA0 +MDgwNjQ3MTdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCVjCsiEOa+FegZ/zihd/Xth57Qst1amBxNM8k9C3Za +liGj+tduxNEyZrSiCRKfW/CTE0vNVx/TJLF1htS3idgypKVKfT+hGowiaeuoha6z +DZUG1YpdMxSypQJilkJGEQqoI90JRUtEFKaUeACnMEHrcPx2Tp0td2HZFjiC2+5E +YWuOtnzecqDGrxn27OzNYIFj3R0VGFHrzq/TEw67dUgw9brMCYEbsmT3Q8kn4eR+ +Bqxni7hkTxY484M9AR82doh39LUyh1rv8M2bJrDZtCl/nVoNErTs7n3GsO7FiLy6 +nF3SFZVjcqnTvGGTX8j724uMFKps/QdWg5QyXdlDeGC6CrbSQ8vNTLMPqz/vL+io +8iOOrV4HVowvQsrbJvsz2LXQo42AV9jlCpQBkXhsdH6F/l1zAkBXriajp6dxsOjm +5ytucCbLpT0C7EQSAMrhKs7CRz1J+R8VqONZebCDiI80YMYchCohcNOO0VsWe0D6 +C/d14U1RGm0ZhTy7PI4fhsZ2ymDtRTEmTQMKsVKV1P60BBZ+LBwFIQnU02XjiWM3 +EnPMJ6rBcBKAn9dWjiNz09yHfntxten4+akNaMd0+t5b5DUfUnfwAeuCsCxekSC+ +PdyNjdfVrkk/JyOTXn/luim7EZmwa9X+q6rCwBp66rPlR5FsnlOYU23GyMhN+udM +vQIDAQABo1MwUTAdBgNVHQ4EFgQUOaisRzvoDnxrsW4d4KEod7CBaVkwHwYDVR0j +BBgwFoAUOaisRzvoDnxrsW4d4KEod7CBaVkwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAhESQlqrNiCvG54rpvQkd+h0ZNiyP4WF381t+sJev46qL +ckPXLTcylsbkrwD/4paHioh6Ni8Vs2yH99F5fgVe10RKzX6leoC26JduHfvEu6N+ +LKgnchlQZy09ZUsUcwNsxMIFr9/h5y44n44KEJ1muereC8iE6NrsYnEG4z7/YipY +NyuAR1HBJFM/YGJF7jOmNdFzx5c6PuK/0zfKBQfRIjoWCVlnQ1j3bln0S0jul+br +SLga8ncMGHsiM/WOMHIH/OG0bgqsujGFqzB7L7ozLyoYxGUGk8J7kEY64CzAdorx +daurd0qy50qf/Kfa8WyZUd4P7qqNB/enotM35cuc4z5giwmFrUbyMPrjyKdWQ2vs +sezTvPSKDe80SHvkBzlx5fgm4Y7a8MVmQuqh3bPLgF22ivg7N0YYyMAp1WHIsiEi +Vqh/6Akiy2F1pUteSCjSS/KT9xQtN/6ENn+HNo1FCNskeipAkrr8uCFHFgqawaIy +He4J9B+ytLartlMY9JdLl4dmqTCDY48jJZnFxlhoj3xGIgB1V1vnwoujZucWjQGy +i/PqW25LIrz89RXA4mNCqKtq8sgSpqeotA+90TIjkbekgWnqyIYoIWPBplY+AIfc +w5CSRfmI3cXVsvz5CnYvsa1JVMBOFiXKxyqtKumg29U0WWhUT3GCPshnAKac7yY= +-----END CERTIFICATE----- diff --git a/tests/fixtures/tls/server.crt b/tests/fixtures/tls/server.crt new file mode 100644 index 0000000..190efe6 --- /dev/null +++ b/tests/fixtures/tls/server.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEjDCCAnSgAwIBAgIUM5WOxm05GBkIx2USGMxLneKpJYswDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yNTA2MTkwNzE5NTRaGA8yMTI1 +MDUyNjA3MTk1NFowWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJMTI3 +LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApszHQnydLfvs +BJ+hz6w1QzI40OLr3bq2tlOyxGtgFjv9Hv4leg/BxyuadFc3ANnUraiRLmSpbOvQ +LKNLQKbzcldmumjibaRkghB5rkFhiKQZMrubzVu4gKds/Vhh6O7oK0tVyC2g1Bwr +wB2f0DJpMvYTE/UVyRDmb1C3HERcYZq12Gn8HQEcO8TJ1XENZcuCxTKsiKpmjONd +fo+5ytKEItbOmSRRiv8ykNrbjleNcC6RwjZr6D1oVbqyVoipUqlGOBZESQ9tiwrL ++ZMpEYzN8rG/4Eh0n2/pMEWbqfhs3/UVsffoGhN13hZGgrWkfEP1hm5H9PHuYzd6 +OInIGMUd5wIDAQABo14wXDAaBgNVHREEEzARhwR/AAABgglsb2NhbGhvc3QwHQYD +VR0OBBYEFGJ2iciMnRuS77EyRgVDMI2yDRXoMB8GA1UdIwQYMBaAFDmorEc76A58 +a7FuHeChKHewgWlZMA0GCSqGSIb3DQEBCwUAA4ICAQBv2ajzs/1WoHDzjobdr4HZ +8zibAOr432Vv6mUJayphdHfDaptHKUYv0uSM5slVvtMWTv2su81a9EDigdIgakCs +0mrwKTott5ZKWPJWwSBxQob+mRshmJ3XfS8HlP3xxB2KuIXxAqLkZuzZ5Dt/s+Wm +RqgQbzxFgjw29QqVUxRp3S6wItjLAXIOFnNrQS75wvJn2eFY/YCqPpUsXU8CFSCo ++6qpIGnMUlyPFfJWc1axOJzuV+BvjLSacoDzVBE2cQeWbt4g6gg7jjP6SUHTa6E6 +xGbwK7HnxjJH8AfJcS6yehyC0ofnRcDQH2UIvABuIK5ThI/xN8JBQK+BEMa6xtvf +sMh6Nk/BVs4F85yuy2a5V5kJT7rVDQaFbwvvHzoRFqVsmh5yPupv8pCZuFpsTyTI +w0hnyOBc8yMcJBmjY8xgBWPvTuQcjAQgmYbfWIJgsTX4hzTqW2s2Tn38yzTxAWkI +BYs5sXnPPp1H09BaYOi5fDJxrJXoDsEwPOhfZqNrxs/FlmLXAb/XvPYzKkE8hbe9 +/AxsvHChykRF+Ji5orvzhbngwXR84eTOFvwsbDpwThqrhg0awraA6O6FwyRCj1uu +d4GdOyqVlv59w2/GtF0r504E8S9RNja7V9vkWh80A44JssBNYnBTg5i4Apq11fF1 +OAV/eaUEcR7bumTh8X2QDg== +-----END CERTIFICATE----- diff --git a/tests/fixtures/tls/server.key b/tests/fixtures/tls/server.key new file mode 100644 index 0000000..69b9494 --- /dev/null +++ b/tests/fixtures/tls/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmzMdCfJ0t++wE +n6HPrDVDMjjQ4uvdura2U7LEa2AWO/0e/iV6D8HHK5p0VzcA2dStqJEuZKls69As +o0tApvNyV2a6aOJtpGSCEHmuQWGIpBkyu5vNW7iAp2z9WGHo7ugrS1XILaDUHCvA +HZ/QMmky9hMT9RXJEOZvULccRFxhmrXYafwdARw7xMnVcQ1ly4LFMqyIqmaM411+ +j7nK0oQi1s6ZJFGK/zKQ2tuOV41wLpHCNmvoPWhVurJWiKlSqUY4FkRJD22LCsv5 +kykRjM3ysb/gSHSfb+kwRZup+Gzf9RWx9+gaE3XeFkaCtaR8Q/WGbkf08e5jN3o4 +icgYxR3nAgMBAAECggEADckGKCg1CVQ1DltvERhyEnVNHXO+UJtEzHl1tdFgpesb +9qVvItEN5SW6ZHvCGk+RHy+7nUeeelexjcQ1IkkUp6eHivJuJuebkuWaWNzNxcWM +0Oo7wdN0bSrpJrWuPy+3f78rKMR0nUhyvome5/hdRLlHnFz4tEmxnGjhqUlmZSk0 +4ViF2o93y9UvMoZpuOMxqFV/iX158uPpB180uwXFIXDhxHmmWZouJ9zRiISHdVT5 +JE6yc/tFMxOFG2e7UR0mvJ+XYbKoY+XZKVr0xMRIQdwwFQJjvqeEAAmmliFVOwK0 +j8vifi3V2NUnj26f2ym33ucKgfVkSfAcpMhhymMhOQKBgQDekh5BRO3Da8rAHJLa +gqntNUDafpTOUGL+QVwocVgFl5MwTnQn+i3qHbR4WMF5oOc3TtgKszDA5Uap9yv5 ++AwKuiWSRbDffxuwh3r+Ma+7rrnl/RJKGQfGxz+eGnJy9+1TTGLbpXqNycO3jfJx +RLuhMP4qjn6d1fdCa2EkjbXKewKBgQC/2kMCDUe2/wmKDxCycJT2Zd80UYgkmCtt +BuY0782T9ehraxeBp5r80x0e6XzOy13sX88NwN7oxhwUpifzdB1npcjNzoadfdiH +Gr6AP0W2tSE10sXUhHTledmsl1t36bQO+RbWwpFwAwoVXT1dcys7jbfj4R9IU/KI +9Z2rhqsEhQKBgHokG8Bb0FMnC1wEEj8h55jKWa3OO2FBUiIPwkBbex+Of/LJiwsJ +SzsoVAqbQom52ElM1liA36dr6yyI/TQvgIQ+hTHRVvA/s/VbVA69O6A2kcP57piF +RfQ7Edl00AvxrObCi5nYJPo8mFBZ8ItiWclqtoCqNCfv7MIhZW0G65WTAoGBALAD +MILLaEYNidTtqWXsP94m7DZ1rq/UI9MtBzr93t+mNguG/tPmzxyxGwBnOigHEC5y +X+XAU0G/r7eKEREcMHYM9UNL/Ni0wliBQtEqO206lDNrIjCtLQnzVq8vVa2X7afn +AvsZGpFnWHLtTgVUSg+jH1ikCy0yR0s7++GH9ZJ5AoGBAJv2tfqg9xSomwHj59Ws +IwJSZyaNixgevjHRFhwWI1XVwAlaW0cF47whRK5NR9LPIH9ICPnpsbmRAuhVW40r +NeweViAb29KztaJoziqMtT0k97Tc7bq6Bn3FcFqGm3bFNjy6SUW8SH2rrNiwTW/X +f4MbGeR9xfWQ3ZPAaKYPopg4 +-----END PRIVATE KEY----- diff --git a/tests/mocks.rs b/tests/mocks.rs index bbeddb2..72e097a 100644 --- a/tests/mocks.rs +++ b/tests/mocks.rs @@ -378,7 +378,8 @@ async fn debug_prints_mock_server_variants() { pooled_debug_str .find( format!( - "BareMockServer {{ address: {} }}", + "BareMockServer {{ proto: {}, address: {} }}", + "http", pooled_mock_server.address() ) .as_str() @@ -389,7 +390,8 @@ async fn debug_prints_mock_server_variants() { let bare_mock_server = MockServer::builder().start().await; assert_eq!( format!( - "MockServer(Bare(BareMockServer {{ address: {} }}))", + "MockServer(Bare(BareMockServer {{ proto: {}, address: {} }}))", + "http", bare_mock_server.address() ), format!("{:?}", bare_mock_server) diff --git a/tests/tls.rs b/tests/tls.rs new file mode 100644 index 0000000..f5648a3 --- /dev/null +++ b/tests/tls.rs @@ -0,0 +1,137 @@ +#[cfg(feature = "tls")] +mod tlstests { + use hyper_server::tls_rustls::RustlsConfig; + use wiremock::tls_certs::MockTlsCertificates; + + #[async_std::test] + async fn test_tls_basic() { + let certs = MockTlsCertificates::new(); + + let mock_server = wiremock::MockServer::builder() + .start_https( + certs + .get_rustls_config() + .await + .expect("Failed to create RustlsConfig"), + ) + .await; + let uri = mock_server.uri(); + let port = mock_server.address().port(); + + assert_eq!(uri, format!("https://127.0.0.1:{}", port)); + } + + #[async_std::test] + async fn test_tls_invalid() { + let certs = MockTlsCertificates::new(); + + let mock_server = wiremock::MockServer::builder() + .start_https( + certs + .get_rustls_config() + .await + .expect("Failed to create RustlsConfig"), + ) + .await; + let uri = mock_server.uri(); + + let client = reqwest::Client::builder() + .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. + .build() + .expect("Failed to build HTTP client"); + + client + .get(uri.clone()) + .send() + .await + .expect_err("Expected request to fail due to invalid TLS certificate"); + } + + #[async_std::test] + async fn test_tls_anonymous() { + let certs = MockTlsCertificates::new(); + + let mock_server = wiremock::MockServer::builder() + .start_https( + certs + .get_rustls_config() + .await + .expect("Failed to create RustlsConfig"), + ) + .await; + let uri = mock_server.uri(); + + let reqwest_root_certificate = reqwest::Certificate::from_der(certs.get_root_cert().der()) + .expect("Failed to create certificate from DER"); + let client = reqwest::Client::builder() + .add_root_certificate(reqwest_root_certificate) + .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. + .build() + .expect("Failed to build HTTP client"); + + client + .get(uri.clone()) + .send() + .await + .expect("Failed to send request to the mock server"); + } + + #[async_std::test] + async fn test_tls_with_TODO() { + let certs = MockTlsCertificates::new(); + + let mock_server = wiremock::MockServer::builder() + .start_https( + certs + .get_rustls_config() + .await + .expect("Failed to create RustlsConfig"), + ) + .await; + todo!(); + let uri = mock_server.uri(); + + let reqwest_root_certificate = reqwest::Certificate::from_der(certs.get_root_cert().der()) + .expect("Failed to create certificate from DER"); + let client = reqwest::Client::builder() + .add_root_certificate(reqwest_root_certificate) + .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. + .build() + .expect("Failed to build HTTP client"); + + client + .get(uri.clone()) + .send() + .await + .expect("Failed to send request to the mock server"); + } + + #[async_std::test] + async fn test_tls_from_file() { + let rustls_config = RustlsConfig::from_pem( + include_bytes!("fixtures/tls/server.crt").to_vec(), + include_bytes!("fixtures/tls/server.key").to_vec(), + ) + .await + .expect("Failed to create RustlsConfig from file"); + + let mock_server = wiremock::MockServer::builder() + .start_https(rustls_config) + .await; + let uri = mock_server.uri(); + + let root_cert = reqwest::Certificate::from_pem(include_bytes!("fixtures/tls/rootCA.crt")) + .expect("Failed to create certificate from PEM"); + let client = reqwest::Client::builder() + .add_root_certificate(root_cert) + .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. + .build() + .expect("Failed to build HTTP client"); + + client + .get(uri.clone()) + .send() + .await + .expect("Failed to send request to the mock server"); + } +} From 04d1722179e3eae62d41ed3722769e6a1668a27c Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Sat, 21 Jun 2025 06:30:42 +0200 Subject: [PATCH 05/12] client cert test --- tests/tls.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/tls.rs b/tests/tls.rs index f5648a3..992fd3d 100644 --- a/tests/tls.rs +++ b/tests/tls.rs @@ -77,7 +77,7 @@ mod tlstests { } #[async_std::test] - async fn test_tls_with_TODO() { + async fn test_tls_with_client_cert() { let certs = MockTlsCertificates::new(); let mock_server = wiremock::MockServer::builder() @@ -88,13 +88,19 @@ mod tlstests { .expect("Failed to create RustlsConfig"), ) .await; - todo!(); let uri = mock_server.uri(); let reqwest_root_certificate = reqwest::Certificate::from_der(certs.get_root_cert().der()) .expect("Failed to create certificate from DER"); + let (client_cert, client_key) = certs.gen_client_cert("johnny@house-of-leaves.test"); + let client_cert_pem = client_cert.pem(); + let client_key_pem = client_key.serialize_pem(); + let client_cert = + reqwest::Identity::from_pem((client_cert_pem + &client_key_pem).as_bytes()) + .expect("Failed to create Identity from PEM"); let client = reqwest::Client::builder() .add_root_certificate(reqwest_root_certificate) + .identity(client_cert) .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. .build() .expect("Failed to build HTTP client"); From fe8fc6ff83b9d6142efbfecc1014abae401a1a2d Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Sat, 21 Jun 2025 08:58:54 +0200 Subject: [PATCH 06/12] Refactor: use `MockServerTlsConfig` Use it instead of `RustlsConfig` in the public API. --- src/mock_server/builder.rs | 19 ++++++--- src/mock_server/tls_certs.rs | 75 +++++++++++++++++++++++++++++------- tests/tls.rs | 44 ++++++--------------- 3 files changed, 86 insertions(+), 52 deletions(-) diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index 1af913e..c64add7 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -7,6 +7,9 @@ use hyper_server::tls_rustls::RustlsConfig; use std::env; use std::net::TcpListener; +#[cfg(feature = "tls")] +use super::tls_certs::MockServerTlsConfig; + /// A builder providing a fluent API to assemble a [`MockServer`] step-by-step. /// Use [`MockServer::builder`] to get started. pub struct MockServerBuilder { @@ -127,7 +130,7 @@ impl MockServerBuilder { /// Finalise the builder to get an instance of a [`BareMockServer`]. #[cfg(feature = "tls")] - pub(super) async fn build_bare_https(self, rustls_config: RustlsConfig) -> BareMockServer { + pub(super) async fn build_bare_https(self, certs: MockServerTlsConfig) -> BareMockServer { use hyper_server::tls_rustls::RustlsAcceptor; let listener = if let Some(listener) = self.listener { @@ -140,6 +143,14 @@ impl MockServerBuilder { } else { RequestRecording::Disabled }; + + let rustls_config = RustlsConfig::from_der( + vec![certs.server_cert_der, certs.root_cert_der], + certs.server_key_der, + ) + .await + .expect("Failed to build RustlsConfig"); + BareMockServer::start( listener, recording, @@ -157,9 +168,7 @@ impl MockServerBuilder { /// Finalise the builder and launch the HTTPS [`MockServer`] instance! #[cfg(feature = "tls")] - pub async fn start_https(self, rustls_config: RustlsConfig) -> MockServer { - MockServer::new(InnerServer::Bare( - self.build_bare_https(rustls_config).await, - )) + pub async fn start_https(self, tls_conf: MockServerTlsConfig) -> MockServer { + MockServer::new(InnerServer::Bare(self.build_bare_https(tls_conf).await)) } } diff --git a/src/mock_server/tls_certs.rs b/src/mock_server/tls_certs.rs index 75dca60..cdfb1e5 100644 --- a/src/mock_server/tls_certs.rs +++ b/src/mock_server/tls_certs.rs @@ -9,13 +9,11 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; -use hyper_server::tls_rustls::RustlsConfig; use rcgen::{ BasicConstraints, Certificate, CertificateParams, DistinguishedName, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose, PKCS_ED25519, SanType, SerialNumber, SignatureAlgorithm, }; - -use rustls_pki_types::{CertificateDer, PrivateKeyDer}; +use rustls_pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject}; pub const DEFAULT_ALGORITHM: &SignatureAlgorithm = &PKCS_ED25519; @@ -41,21 +39,69 @@ const EE_KEY_USAGES: &[KeyUsagePurpose; 2] = &[ static SERIAL_NUMBER: AtomicU64 = AtomicU64::new(1); +pub struct MockServerTlsConfig { + pub root_cert_der: Vec, + pub server_cert_der: Vec, + pub server_key_der: Vec, +} + +impl MockServerTlsConfig { + #[inline] + pub fn from_der( + root_cert_der: Vec, + server_cert_der: Vec, + server_key_der: Vec, + ) -> Self { + Self { + root_cert_der, + server_cert_der, + server_key_der, + } + } + + /// Create a new `MockServerTlsConfig` from PEM-encoded certificates and key. + /// + /// Panics if the data cannot be parsed as valid PEM. + #[inline] + pub fn from_pem( + root_cert_pem: Vec, + server_cert_pem: Vec, + server_key_pem: Vec, + ) -> Self { + let root_cert_der = CertificateDer::from_pem_slice(&root_cert_pem) + .expect("Failed to parse root certificate from PEM") + .to_vec(); + let server_cert_der = CertificateDer::from_pem_slice(&server_cert_pem) + .expect("Failed to parse server certificate from PEM") + .to_vec(); + let server_key_der = PrivateKeyDer::from_pem_slice(&server_key_pem) + .expect("Failed to parse server key from PEM") + .secret_der() + .to_vec(); + + Self { + root_cert_der, + server_cert_der, + server_key_der, + } + } +} + pub struct MockTlsCertificates { - root_cert: Certificate, - server_cert: Certificate, - server_key: KeyPair, + pub root_cert: Certificate, + pub server_cert: Certificate, + pub server_key: KeyPair, } impl MockTlsCertificates { - /// Creates an instance with "localhost" and "127.0.0.1" as hostnames. + /// Generate server certificates and key with "localhost" and "127.0.0.1" as hostnames. // On the good old M1 processor it takes ~77 µs #[inline] pub fn new() -> Self { Self::with_hostnames(default_hostnames()) } - /// Creates an instance with custom hostnames and IPs. + /// Generate server certificates and key with custom hostnames and IPs. pub fn with_hostnames(hostnames: impl Into>) -> Self { let (root_cert, root_key) = gen_root_cert(DEFAULT_ALGORITHM); // We do not bother to have an intermediate certificate because CAs use them for flexibility only. @@ -96,12 +142,13 @@ impl MockTlsCertificates { ) } - pub async fn get_rustls_config(&self) -> Result { - let server_cert_der = self.server_cert.der().to_vec(); - let root_cert_der = self.get_root_cert().der().to_vec(); - let server_private_key_der = self.server_key.serialize_der(); - - RustlsConfig::from_der(vec![server_cert_der, root_cert_der], server_private_key_der).await + #[inline] + pub fn get_server_config(&self) -> MockServerTlsConfig { + MockServerTlsConfig { + root_cert_der: self.root_cert.der().to_vec(), + server_cert_der: self.server_cert.der().to_vec(), + server_key_der: self.server_key.serialize_der(), + } } } diff --git a/tests/tls.rs b/tests/tls.rs index 992fd3d..1d984b7 100644 --- a/tests/tls.rs +++ b/tests/tls.rs @@ -1,19 +1,13 @@ #[cfg(feature = "tls")] mod tlstests { - use hyper_server::tls_rustls::RustlsConfig; - use wiremock::tls_certs::MockTlsCertificates; + use wiremock::tls_certs::{MockServerTlsConfig, MockTlsCertificates}; #[async_std::test] async fn test_tls_basic() { let certs = MockTlsCertificates::new(); let mock_server = wiremock::MockServer::builder() - .start_https( - certs - .get_rustls_config() - .await - .expect("Failed to create RustlsConfig"), - ) + .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); let port = mock_server.address().port(); @@ -26,12 +20,7 @@ mod tlstests { let certs = MockTlsCertificates::new(); let mock_server = wiremock::MockServer::builder() - .start_https( - certs - .get_rustls_config() - .await - .expect("Failed to create RustlsConfig"), - ) + .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); @@ -52,12 +41,7 @@ mod tlstests { let certs = MockTlsCertificates::new(); let mock_server = wiremock::MockServer::builder() - .start_https( - certs - .get_rustls_config() - .await - .expect("Failed to create RustlsConfig"), - ) + .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); @@ -81,12 +65,7 @@ mod tlstests { let certs = MockTlsCertificates::new(); let mock_server = wiremock::MockServer::builder() - .start_https( - certs - .get_rustls_config() - .await - .expect("Failed to create RustlsConfig"), - ) + .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); @@ -114,15 +93,14 @@ mod tlstests { #[async_std::test] async fn test_tls_from_file() { - let rustls_config = RustlsConfig::from_pem( - include_bytes!("fixtures/tls/server.crt").to_vec(), - include_bytes!("fixtures/tls/server.key").to_vec(), - ) - .await - .expect("Failed to create RustlsConfig from file"); + let root_cert_pem = include_bytes!("fixtures/tls/rootCA.crt").to_vec(); + let server_cert_pem = include_bytes!("fixtures/tls/server.crt").to_vec(); + let server_key_pem = include_bytes!("fixtures/tls/server.key").to_vec(); + let mock_server_tls_config = + MockServerTlsConfig::from_pem(root_cert_pem, server_cert_pem, server_key_pem); let mock_server = wiremock::MockServer::builder() - .start_https(rustls_config) + .start_https(mock_server_tls_config) .await; let uri = mock_server.uri(); From 641d5a7ec6bd34e0dfc3768052cbe1b219088970 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Sat, 21 Jun 2025 11:54:35 +0200 Subject: [PATCH 07/12] Make clippy happy --- src/mock_server/tls_certs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mock_server/tls_certs.rs b/src/mock_server/tls_certs.rs index cdfb1e5..14a8b75 100644 --- a/src/mock_server/tls_certs.rs +++ b/src/mock_server/tls_certs.rs @@ -1,6 +1,6 @@ //! Certificate generation. //! -//! Based on https://github.com/rustls/rustls/blob/main/rustls/examples/internal/test_ca.rs +// Based on https://github.com/rustls/rustls/blob/main/rustls/examples/internal/test_ca.rs use std::{ convert::TryInto, fmt::Display, @@ -97,6 +97,7 @@ impl MockTlsCertificates { /// Generate server certificates and key with "localhost" and "127.0.0.1" as hostnames. // On the good old M1 processor it takes ~77 µs #[inline] + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self::with_hostnames(default_hostnames()) } From f31c550de9251349cb8bef9d8973b91098d8611d Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Mon, 23 Jun 2025 15:45:44 +0200 Subject: [PATCH 08/12] Docs and refactorings --- benches/tls_certs.rs | 5 ++- src/lib.rs | 10 ++++++ src/mock_server/builder.rs | 2 +- src/mock_server/tls_certs.rs | 67 ++++++++++++++++++++++-------------- tests/tls.rs | 20 ++++++----- 5 files changed, 65 insertions(+), 39 deletions(-) diff --git a/benches/tls_certs.rs b/benches/tls_certs.rs index 6894390..aa37b8e 100644 --- a/benches/tls_certs.rs +++ b/benches/tls_certs.rs @@ -8,14 +8,13 @@ use wiremock::tls_certs::MockTlsCertificates; // On the good old M1 processor it takes ~77 µs pub fn tls_mock_tls_certificates_new(c: &mut Criterion) { c.bench_function("MockTlsCertificates::new", |b| { - b.iter(|| MockTlsCertificates::new()) + b.iter(|| MockTlsCertificates::random()) }); } #[cfg(feature = "tls")] -// TODO measure with a charger connected pub fn tls_mock_tls_certificates_client(c: &mut Criterion) { - let mock_tls_certificates = MockTlsCertificates::new(); + let mock_tls_certificates = MockTlsCertificates::random(); c.bench_function("MockTlsCertificates::gen_client", |b| { b.iter(|| mock_tls_certificates.gen_client_cert("user@myserver.test")) }); diff --git a/src/lib.rs b/src/lib.rs index abef306..03bd21f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,16 @@ //! The pool is designed to be invisible: it makes your life easier and your tests faster. If you //! end up having to worry about it, it's a bug: open an issue! //! +//! ## HTTPS +//! +//! You may start a HTTPS server with `MockServer::start_https(MockServerTlsConfig)` method. +//! The `MockServerTlsConfig` can be created from pregenerated TLS certificates, or you can +//! generate self-signed server and client certificates with a `MockTlsCertificates` instance. +//! +//! HTTPS servers are not pooled yet. +//! +//! HTTPS functionality is gated by the `tls` feature. +//! //! ## Prior art //! //! [`mockito`] and [`httpmock`] provide HTTP mocking for Rust. diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index c64add7..4f8f528 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -146,7 +146,7 @@ impl MockServerBuilder { let rustls_config = RustlsConfig::from_der( vec![certs.server_cert_der, certs.root_cert_der], - certs.server_key_der, + certs.server_keypair_der, ) .await .expect("Failed to build RustlsConfig"); diff --git a/src/mock_server/tls_certs.rs b/src/mock_server/tls_certs.rs index 14a8b75..a8840e6 100644 --- a/src/mock_server/tls_certs.rs +++ b/src/mock_server/tls_certs.rs @@ -1,4 +1,4 @@ -//! Certificate generation. +//! TLS Certificate generation helpers. //! // Based on https://github.com/rustls/rustls/blob/main/rustls/examples/internal/test_ca.rs use std::{ @@ -39,10 +39,14 @@ const EE_KEY_USAGES: &[KeyUsagePurpose; 2] = &[ static SERIAL_NUMBER: AtomicU64 = AtomicU64::new(1); +/// Configuration for a mock server TLS setup. pub struct MockServerTlsConfig { + /// Root CA certificate in DER format. pub root_cert_der: Vec, + /// Server certificate in DER format. pub server_cert_der: Vec, - pub server_key_der: Vec, + /// Server keypair in DER format. + pub server_keypair_der: Vec, } impl MockServerTlsConfig { @@ -50,23 +54,22 @@ impl MockServerTlsConfig { pub fn from_der( root_cert_der: Vec, server_cert_der: Vec, - server_key_der: Vec, + server_keypair_der: Vec, ) -> Self { Self { root_cert_der, server_cert_der, - server_key_der, + server_keypair_der, } } /// Create a new `MockServerTlsConfig` from PEM-encoded certificates and key. /// /// Panics if the data cannot be parsed as valid PEM. - #[inline] pub fn from_pem( root_cert_pem: Vec, server_cert_pem: Vec, - server_key_pem: Vec, + server_keypair_pem: Vec, ) -> Self { let root_cert_der = CertificateDer::from_pem_slice(&root_cert_pem) .expect("Failed to parse root certificate from PEM") @@ -74,7 +77,7 @@ impl MockServerTlsConfig { let server_cert_der = CertificateDer::from_pem_slice(&server_cert_pem) .expect("Failed to parse server certificate from PEM") .to_vec(); - let server_key_der = PrivateKeyDer::from_pem_slice(&server_key_pem) + let server_keypair_der = PrivateKeyDer::from_pem_slice(&server_keypair_pem) .expect("Failed to parse server key from PEM") .secret_der() .to_vec(); @@ -82,73 +85,85 @@ impl MockServerTlsConfig { Self { root_cert_der, server_cert_der, - server_key_der, + server_keypair_der, } } } +/// Mock self-signed TLS certificates for testing purposes. +/// +/// This struct generates a root CA certificate and a server certificate signed by it, along with a key pair for the +/// server. pub struct MockTlsCertificates { pub root_cert: Certificate, pub server_cert: Certificate, - pub server_key: KeyPair, + pub server_keypair: KeyPair, } impl MockTlsCertificates { - /// Generate server certificates and key with "localhost" and "127.0.0.1" as hostnames. + /// Generate server certificates and keypair with "localhost" and "127.0.0.1" as hostnames. + /// + /// Ed25519 is used as the default signature algorithm. // On the good old M1 processor it takes ~77 µs #[inline] - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self::with_hostnames(default_hostnames()) + pub fn random() -> Self { + Self::random_with_hostnames(default_hostnames()) } /// Generate server certificates and key with custom hostnames and IPs. - pub fn with_hostnames(hostnames: impl Into>) -> Self { + pub fn random_with_hostnames(hostnames: impl Into>) -> Self { let (root_cert, root_key) = gen_root_cert(DEFAULT_ALGORITHM); // We do not bother to have an intermediate certificate because CAs use them for flexibility only. - let (server_cert, server_key) = + let (server_cert, server_keypair) = gen_server_cert(&root_cert, &root_key, DEFAULT_ALGORITHM, hostnames.into()); Self { root_cert, server_cert, - server_key, + server_keypair, } } + /// Get the root CA certificate. #[inline] - pub fn get_root_cert(&self) -> &Certificate { + pub fn get_root_ca_cert(&self) -> &Certificate { &self.root_cert } + /// Get the server certificate signed by CA certificate, in DER format. #[inline] pub fn server_cert_der(&self) -> &CertificateDer<'_> { self.server_cert.der() } - pub fn server_private_key_der(&self) -> PrivateKeyDer<'_> { - self.server_key + /// Get the server keypair in DER format. + pub fn server_private_keypair_der(&self) -> PrivateKeyDer<'_> { + self.server_keypair .serialize_der() .try_into() .expect("Failed to deserialize a serialized key") } + /// Generate a client certificate signed by the CA certificate. + /// + /// Each invocation generates a new keypair and a certificate. #[inline] - pub fn gen_client_cert(&self, email: &str) -> (Certificate, KeyPair) { + pub fn generate_client_cert(&self, email: &str) -> (Certificate, KeyPair) { gen_client_cert( &self.server_cert, - &self.server_key, + &self.server_keypair, DEFAULT_ALGORITHM, email, ) } + /// Get the server configuration for use with a mock server. #[inline] pub fn get_server_config(&self) -> MockServerTlsConfig { MockServerTlsConfig { root_cert_der: self.root_cert.der().to_vec(), server_cert_der: self.server_cert.der().to_vec(), - server_key_der: self.server_key.serialize_der(), + server_keypair_der: self.server_keypair.serialize_der(), } } } @@ -180,7 +195,7 @@ fn gen_root_cert(alg: &'static SignatureAlgorithm) -> (Certificate, KeyPair) { fn gen_server_cert( signer_cert: &Certificate, - signer_key: &KeyPair, + signer_keypair: &KeyPair, alg: &'static SignatureAlgorithm, hostnames: Vec, ) -> (Certificate, KeyPair) { @@ -195,13 +210,13 @@ fn gen_server_cert( params.key_usages = EE_KEY_USAGES.to_vec(); params.subject_alt_names = hostnames; - let cert = params.signed_by(&keypair, signer_cert, signer_key).unwrap(); + let cert = params.signed_by(&keypair, signer_cert, signer_keypair).unwrap(); (cert, keypair) } fn gen_client_cert( signer_cert: &Certificate, - signer_key: &KeyPair, + signer_keypair: &KeyPair, alg: &'static SignatureAlgorithm, email: &str, ) -> (Certificate, KeyPair) { @@ -222,7 +237,7 @@ fn gen_client_cert( .unwrap_or_else(|_| panic!("Invalid email: {}", email)), )]; - let cert = params.signed_by(&keypair, signer_cert, signer_key).unwrap(); + let cert = params.signed_by(&keypair, signer_cert, signer_keypair).unwrap(); (cert, keypair) } diff --git a/tests/tls.rs b/tests/tls.rs index 1d984b7..c63a82d 100644 --- a/tests/tls.rs +++ b/tests/tls.rs @@ -4,7 +4,7 @@ mod tlstests { #[async_std::test] async fn test_tls_basic() { - let certs = MockTlsCertificates::new(); + let certs = MockTlsCertificates::random(); let mock_server = wiremock::MockServer::builder() .start_https(certs.get_server_config()) @@ -17,7 +17,7 @@ mod tlstests { #[async_std::test] async fn test_tls_invalid() { - let certs = MockTlsCertificates::new(); + let certs = MockTlsCertificates::random(); let mock_server = wiremock::MockServer::builder() .start_https(certs.get_server_config()) @@ -38,15 +38,16 @@ mod tlstests { #[async_std::test] async fn test_tls_anonymous() { - let certs = MockTlsCertificates::new(); + let certs = MockTlsCertificates::random(); let mock_server = wiremock::MockServer::builder() .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); - let reqwest_root_certificate = reqwest::Certificate::from_der(certs.get_root_cert().der()) - .expect("Failed to create certificate from DER"); + let reqwest_root_certificate = + reqwest::Certificate::from_der(certs.get_root_ca_cert().der()) + .expect("Failed to create certificate from DER"); let client = reqwest::Client::builder() .add_root_certificate(reqwest_root_certificate) .use_rustls_tls() // It fails on MacOS with native-tls no mattter what, so use rustls. @@ -62,16 +63,17 @@ mod tlstests { #[async_std::test] async fn test_tls_with_client_cert() { - let certs = MockTlsCertificates::new(); + let certs = MockTlsCertificates::random(); let mock_server = wiremock::MockServer::builder() .start_https(certs.get_server_config()) .await; let uri = mock_server.uri(); - let reqwest_root_certificate = reqwest::Certificate::from_der(certs.get_root_cert().der()) - .expect("Failed to create certificate from DER"); - let (client_cert, client_key) = certs.gen_client_cert("johnny@house-of-leaves.test"); + let reqwest_root_certificate = + reqwest::Certificate::from_der(certs.get_root_ca_cert().der()) + .expect("Failed to create certificate from DER"); + let (client_cert, client_key) = certs.generate_client_cert("johnny@house-of-leaves.test"); let client_cert_pem = client_cert.pem(); let client_key_pem = client_key.serialize_pem(); let client_cert = From 086e4391f8d389c246bcac44f0c207c6b6dfa1df Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Mon, 23 Jun 2025 15:54:37 +0200 Subject: [PATCH 09/12] Fix Cargo.toml --- Cargo.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08f4f30..5257398 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,15 +46,16 @@ rustls-pki-types = { version = "1.11.0", optional = true } [dev-dependencies] async-std = { version = "1.13.2", features = ["attributes", "tokio1"] } -reqwest = { version = "0.12.23", features = ["json", "rustls-tls"] } +reqwest = { version = "0.12.23", features = ["json"] } tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] } actix-rt = "2.10.0" serde = { version = "1", features = ["derive"] } criterion = "0.5.1" [features] -tls = ["rcgen", "hyper-server/tls-rustls", "rustls-pki-types"] -default = ["tls"] +default = [] +# Enable HTTPS mock server support. +tls = ["hyper-server/tls-rustls", "rcgen", "rustls-pki-types", "reqwest/rustls-tls"] [[bench]] name = "tls_certs" From 2bb902dec10ae801ce711fd9cbc7b9de389d82e9 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Mon, 23 Jun 2025 16:43:25 +0200 Subject: [PATCH 10/12] make fmt happy --- src/mock_server/tls_certs.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mock_server/tls_certs.rs b/src/mock_server/tls_certs.rs index a8840e6..e9a82c7 100644 --- a/src/mock_server/tls_certs.rs +++ b/src/mock_server/tls_certs.rs @@ -210,7 +210,9 @@ fn gen_server_cert( params.key_usages = EE_KEY_USAGES.to_vec(); params.subject_alt_names = hostnames; - let cert = params.signed_by(&keypair, signer_cert, signer_keypair).unwrap(); + let cert = params + .signed_by(&keypair, signer_cert, signer_keypair) + .unwrap(); (cert, keypair) } @@ -237,7 +239,9 @@ fn gen_client_cert( .unwrap_or_else(|_| panic!("Invalid email: {}", email)), )]; - let cert = params.signed_by(&keypair, signer_cert, signer_keypair).unwrap(); + let cert = params + .signed_by(&keypair, signer_cert, signer_keypair) + .unwrap(); (cert, keypair) } From 8fd9e69cf13fbd31ee088e217e5d6a5b43fd5463 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Sat, 28 Jun 2025 08:46:05 +0200 Subject: [PATCH 11/12] Improve `MockServerBuilder::build_bare_https` Extend its docstring and make `.expect` message clearer. --- src/mock_server/builder.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index 4f8f528..02e257d 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -128,7 +128,9 @@ impl MockServerBuilder { .await } - /// Finalise the builder to get an instance of a [`BareMockServer`]. + /// Finalise the builder to get an HTTPS instance of a [`BareMockServer`]. + /// + /// Panics if DER data the `certs` is invalid. #[cfg(feature = "tls")] pub(super) async fn build_bare_https(self, certs: MockServerTlsConfig) -> BareMockServer { use hyper_server::tls_rustls::RustlsAcceptor; @@ -149,7 +151,7 @@ impl MockServerBuilder { certs.server_keypair_der, ) .await - .expect("Failed to build RustlsConfig"); + .expect("Failed to parse TLS configuration from DER data"); BareMockServer::start( listener, From c11807cded3e18b82486c041776656cacae55187 Mon Sep 17 00:00:00 2001 From: Ivan Boldyrev Date: Wed, 22 Oct 2025 23:35:31 +0200 Subject: [PATCH 12/12] Use axum-server to avoid duplicate deps hyper-server is not updated and uses old deps. --- Cargo.lock | 462 +++++++++++++++++++++------------ Cargo.toml | 4 +- src/mock_server/bare_server.rs | 2 +- src/mock_server/builder.rs | 6 +- src/mock_server/hyper.rs | 2 +- 5 files changed, 302 insertions(+), 174 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00c9134..aa0e841 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,7 +136,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix", + "rustix 1.0.7", "slab", "tracing", "windows-sys 0.59.0", @@ -199,10 +199,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] -name = "base64" -version = "0.21.7" +name = "aws-lc-rs" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "axum-server" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab" +dependencies = [ + "arc-swap", + "bytes", + "fs-err", + "http", + "http-body", + "hyper", + "hyper-util", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] [[package]] name = "base64" @@ -210,6 +249,29 @@ 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.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.100", + "which", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -259,9 +321,20 @@ version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" 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" @@ -301,6 +374,17 @@ dependencies = [ "half", ] +[[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 = "4.5.37" @@ -326,6 +410,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -456,6 +549,12 @@ dependencies = [ "syn 2.0.100", ] +[[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" @@ -550,6 +649,22 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-err" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ad492b2cf1d89d568a43508ab24f98501fe03f2f31c01e1d0fe7366a71745d2" +dependencies = [ + "autocfg", + "tokio", +] + +[[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" @@ -667,6 +782,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "gloo-timers" version = "0.3.0" @@ -679,25 +812,6 @@ dependencies = [ "wasm-bindgen", ] -[[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.3", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.10" @@ -709,7 +823,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.3.1", + "http", "indexmap", "slab", "tokio", @@ -749,14 +863,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] -name = "http" -version = "0.2.3" +name = "home" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "bytes", - "fnv", - "itoa 0.4.7", + "windows-sys 0.59.0", ] [[package]] @@ -770,16 +882,6 @@ dependencies = [ "itoa 1.0.15", ] -[[package]] -name = "http-body" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" -dependencies = [ - "bytes", - "http 0.2.3", -] - [[package]] name = "http-body" version = "1.0.1" @@ -787,7 +889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] @@ -798,8 +900,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -815,30 +917,6 @@ 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.3", - "http-body 0.4.0", - "httparse", - "httpdate", - "itoa 1.0.15", - "pin-project-lite", - "socket2 0.5.9", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.7.0" @@ -849,9 +927,9 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.10", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa 1.0.15", @@ -868,37 +946,17 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.3.1", - "hyper 1.7.0", + "http", + "hyper", "hyper-util", - "rustls 0.23.27", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower-service", "webpki-roots", ] -[[package]] -name = "hyper-server" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2aaf9c44c3bc702a0a3266ab6d1933d9083f2d85ab3701b6d14c9acb048bd4" -dependencies = [ - "arc-swap", - "bytes", - "futures-util", - "http 0.2.3", - "http-body 0.4.0", - "hyper 0.14.32", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile", - "tokio", - "tokio-rustls 0.24.1", - "tower-service", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -907,7 +965,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-util", "native-tls", "tokio", @@ -921,14 +979,14 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-channel", "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.7.0", + "http", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", @@ -1106,6 +1164,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -1131,12 +1199,34 @@ 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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[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" @@ -1179,6 +1269,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "1.0.3" @@ -1207,6 +1303,16 @@ dependencies = [ "tempfile", ] +[[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-conv" version = "0.1.0" @@ -1323,7 +1429,7 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" dependencies = [ - "base64 0.22.1", + "base64", "serde", ] @@ -1400,7 +1506,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.5.0", "pin-project-lite", - "rustix", + "rustix 1.0.7", "tracing", "windows-sys 0.59.0", ] @@ -1426,6 +1532,16 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "prettyplease" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" +dependencies = [ + "proc-macro2", + "syn 2.0.100", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -1445,8 +1561,8 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", - "rustls 0.23.27", + "rustc-hash 2.1.1", + "rustls", "socket2 0.5.9", "thiserror", "tokio", @@ -1460,11 +1576,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", - "getrandom", + "getrandom 0.2.15", "rand", "ring", - "rustc-hash", - "rustls 0.23.27", + "rustc-hash 2.1.1", + "rustls", "rustls-pki-types", "slab", "thiserror", @@ -1496,6 +1612,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.2" @@ -1524,7 +1646,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -1631,15 +1753,15 @@ version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "encoding_rs", "futures-core", - "h2 0.4.10", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-rustls", "hyper-tls", "hyper-util", @@ -1650,7 +1772,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.27", + "rustls", "rustls-pki-types", "serde", "serde_json", @@ -1658,7 +1780,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -1677,12 +1799,18 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "untrusted", "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" @@ -1691,27 +1819,28 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" -version = "1.0.7" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.9.0", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.59.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.52.0", ] [[package]] -name = "rustls" -version = "0.21.12" +name = "rustix" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", ] [[package]] @@ -1720,21 +1849,22 @@ version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ + "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.3", + "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-pemfile" -version = "1.0.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.21.7", + "rustls-pki-types", ] [[package]] @@ -1746,22 +1876,13 @@ dependencies = [ "web-time", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[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", @@ -1804,16 +1925,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "security-framework" version = "2.0.0" @@ -2131,23 +2242,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.27", + "rustls", "tokio", ] @@ -2188,8 +2289,8 @@ dependencies = [ "bitflags 2.9.0", "bytes", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "iri-string", "pin-project-lite", "tower", @@ -2313,6 +2414,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -2412,6 +2522,18 @@ 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 0.38.44", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2656,14 +2778,14 @@ dependencies = [ "actix-rt", "assert-json-diff", "async-std", - "base64 0.22.1", + "axum-server", + "base64", "criterion", "deadpool", "futures", - "http 1.3.1", + "http", "http-body-util", - "hyper 1.7.0", - "hyper-server", + "hyper", "hyper-util", "log", "once_cell", @@ -2677,6 +2799,12 @@ dependencies = [ "url", ] +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + [[package]] name = "writeable" version = "0.6.1" diff --git a/Cargo.toml b/Cargo.toml index 5257398..aed428c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3.31" http = "1.3" http-body-util = "0.1" hyper = { version = "1.7", features = ["full"] } -hyper-server = "0.6.0" +axum-server = "0.7.2" hyper-util = { version = "0.1", features = [ "tokio", "server", @@ -55,7 +55,7 @@ criterion = "0.5.1" [features] default = [] # Enable HTTPS mock server support. -tls = ["hyper-server/tls-rustls", "rcgen", "rustls-pki-types", "reqwest/rustls-tls"] +tls = ["axum-server/tls-rustls", "rcgen", "rustls-pki-types", "reqwest/rustls-tls"] [[bench]] name = "tls_certs" diff --git a/src/mock_server/bare_server.rs b/src/mock_server/bare_server.rs index b2c54f1..fbe41b8 100644 --- a/src/mock_server/bare_server.rs +++ b/src/mock_server/bare_server.rs @@ -3,9 +3,9 @@ use crate::mock_set::MockId; use crate::mock_set::MountedMockSet; use crate::request::BodyPrintLimit; use crate::{ErrorResponse, Request, mock::Mock, verification::VerificationOutcome}; +use axum_server::accept::Accept; use http_body_util::Full; use hyper::body::Bytes; -use hyper_server::accept::Accept; use std::fmt::{Debug, Write}; use std::net::{SocketAddr, TcpListener, TcpStream}; use std::pin::pin; diff --git a/src/mock_server/builder.rs b/src/mock_server/builder.rs index 02e257d..5dd0c5f 100644 --- a/src/mock_server/builder.rs +++ b/src/mock_server/builder.rs @@ -3,7 +3,7 @@ use crate::mock_server::bare_server::{BareMockServer, RequestRecording}; use crate::mock_server::exposed_server::InnerServer; use crate::request::{BODY_PRINT_LIMIT, BodyPrintLimit}; #[cfg(feature = "tls")] -use hyper_server::tls_rustls::RustlsConfig; +use axum_server::tls_rustls::RustlsConfig; use std::env; use std::net::TcpListener; @@ -106,7 +106,7 @@ impl MockServerBuilder { /// Finalise the builder to get an instance of a [`BareMockServer`]. pub(super) async fn build_bare_http(self) -> BareMockServer { - use hyper_server::accept::DefaultAcceptor; + use axum_server::accept::DefaultAcceptor; let listener = if let Some(listener) = self.listener { listener @@ -133,7 +133,7 @@ impl MockServerBuilder { /// Panics if DER data the `certs` is invalid. #[cfg(feature = "tls")] pub(super) async fn build_bare_https(self, certs: MockServerTlsConfig) -> BareMockServer { - use hyper_server::tls_rustls::RustlsAcceptor; + use axum_server::tls_rustls::RustlsAcceptor; let listener = if let Some(listener) = self.listener { listener diff --git a/src/mock_server/hyper.rs b/src/mock_server/hyper.rs index cafc487..7a0412a 100644 --- a/src/mock_server/hyper.rs +++ b/src/mock_server/hyper.rs @@ -1,8 +1,8 @@ use crate::mock_server::bare_server::MockServerState; +use axum_server::accept::Accept; use futures::future::{BoxFuture, FutureExt as _}; use http_body_util::Full; use hyper::body::Bytes; -use hyper_server::accept::Accept; use hyper_util::rt::TokioIo; use std::sync::Arc; use tokio::io::{AsyncRead, AsyncWrite};