http-cache-0.21.0/.cargo_vcs_info.json0000644000000001500000000000100131300ustar { "git": { "sha1": "76207cb48e5bb7ed7e3fa65021560484101147dd" }, "path_in_vcs": "http-cache" }http-cache-0.21.0/CHANGELOG.md000064400000000000000000000153711046102023000135440ustar 00000000000000# Changelog ## [0.21.0] - 2025-06-25 ### Added - `remove_opts` field to `CACacheManager` struct. This field is an instance of `cacache::RemoveOpts` that allows for customization of the removal options when deleting items from the cache. - MSRV is now 1.82.0 ## [0.20.1] - 2025-01-30 ### Changed - Fixed missing implementation of CacheMode::Reload variant logic. - MSRV is now 1.81.1 - Updated the minimum versions of the following dependencies: - async-trait [0.1.85] - cacache [13.1.0] - httpdate [1.0.2] - moka [0.12.10] - serde [1.0.217] - url [2.5.4] ## [0.20.0] - 2024-11-12 ### Added - `cache_status_headers` field to `HttpCacheOptions` struct. This field is a boolean that determines if the cache status headers should be added to the response. ## [0.19.0] - 2024-04-10 ### Changed - Updated the minimum versions of the following dependencies: - cacache [13.0.0] - http [1.1.0] - http-cache-semantics [2.1.0] ## [0.18.0] - 2024-01-15 ### Added - `overridden_cache_mode` method to `Middleware` trait. This method allows for overriding any cache mode set in the configuration, including `cache_mode_fn`. - Derive `Default` for the `CacheMode` enum with the mode `Default` selected to be used. ## [0.17.0] - 2023-11-01 ### Added - `cache_mode_fn` field to `HttpCacheOptions` struct. This is a closure that takes a `&http::request::Parts` and returns a `CacheMode` enum variant. This allows for the overriding of cache mode on a per-request basis. - `cache_bust` field to `HttpCacheOptions` struct. This is a closure that takes `http::request::Parts`, `Option`, the default cache key (`&str`) and returns `Vec` of keys to bust the cache for. ### Changed - Updated the minimum versions of the following dependencies: - cacache [12.0.0] ## [0.16.0] - 2023-09-28 ### Added - `can_cache_request` method to `HttpCache` struct. This can be used by client implementations to determine if the request should be cached. - `run_no_cache` method to `HttpCache` struct. This should be run by client implementations if the request is determined to not be cached. ### Changed - MSRV is now 1.67.1 ## [0.15.0] - 2023-09-26 ### Added - `IgnoreRules` variant to the `CacheMode` enum. This mode will ignore the HTTP headers and always store a response given it was a 200 response. It will also ignore the staleness when retrieving a response from the cache, so expiration of the cached response will need to be handled manually. If there was no cached response it will create a normal request, and will update the cache with the response. ### Changed - Updated the minimum versions of the following dependencies: - moka [0.12.0] ## [0.14.0] - 2023-07-28 ### Added - `cacache-async-std` feature, which enables `async_std` runtime support in the `cacache` backend manager. This feature is enabled by default. - `cacache-tokio` feature, which enables `tokio` runtime support in the `cacache` backend manager. This feature is disabled by default. ### Changed - Updated the minimum versions of the following dependencies: - async-std [1.12.0] - async-trait [0.1.72] - serde [1.0.178] - tokio [1.29.1] ## [0.13.0] - 2023-07-19 ### Added - `CacheKey` type, a closure that takes [`http::request::Parts`] and returns a [`String`]. - `HttpCacheOptions` struct that contains the cache key (`CacheKey`) and the cache options (`CacheOptions`). ### Changed - `CacheManager` trait `get`, `put`, and `delete` methods now require a `cache_key` argument rather than `method` and `url` arguments. This allows for custom keys to be specified. - Both the `CACacheManager` trait and `MokaManager` implementation have been updated to reflect the above change. - Updated the minimum versions of the following dependencies: - async-trait [0.1.71] - moka [0.11.2] - serde [1.0.171] ## [0.12.0] - 2023-06-05 ### Changed - MSRV is now 1.66.1 - `CACacheManager` field `path` has changed to `std::path::PathBuf` - Updated the minimum versions of the following dependencies: - cacache [11.6.0] - moka [0.11.1] - serde [1.0.163] - url [2.4.0] ## [0.11.0] - 2023-03-29 ### Added - `BoxError` type alias for `Box`. - `BadVersion` error type for unknown http versions. - `BadHeader` error type for bad http header values. ### Removed - `CacheError` enum. - The following dependencies: - anyhow - thiserror - miette ### Changed - `CacheError` enum has been replaced in function by `Box`. - `Result` typedef is now `std::result::Result`. - `Error` type for the TryFrom implentation for the `HttpVersion` struct is now `BoxError` containing a `BadVersion` error. - `CacheManager` trait `put` method now returns `Result<(), BoxError>`. - Updated the minimum versions of the following dependencies: - async-trait [0.1.68] - cacache [11.4.0] - moka [0.10.1] - serde [1.0.159] ## [0.10.1] - 2023-03-08 ### Changed - Set conditional check for `CacheError::Bincode` to `cfg(feature = "bincode")` ## [0.10.0] - 2023-03-08 ### Changed - MSRV is now 1.63.0 - Updated the minimum versions of the following dependencies: - async-trait [0.1.66] - cacache [11.3.0] - serde [1.0.154] - thiserror [1.0.39] ## [0.9.2] - 2023-02-23 ### Changed - Updated the minimum versions of the following dependencies: - cacache [11.1.0] ## [0.9.1] - 2023-02-17 ### Changed - Updated the minimum versions of the following dependencies: - http [0.2.9] ## [0.9.0] - 2023-02-16 ### Changed - MSRV is now 1.62.1 - Updated the minimum versions of the following dependencies: - moka [0.10.0] ## [0.8.0] - 2023-02-07 ### Changed - MSRV is now 1.60.0 - Updated the minimum versions of the following dependencies: - anyhow [1.0.69] - async-trait [0.1.64] - cacache [11.0.0] - miette [5.5.0] - moka [0.9.7] - serde [1.0.152] - thiserror [1.0.38] ## [0.7.2] - 2022-11-16 - Added derive `Eq` to `HttpVersion` enum. ### Changed ## [0.7.1] - 2022-11-06 ### Changed - Updated the minimum versions of the following dependencies: - anyhow [1.0.66] - async-trait [0.1.58] - miette [5.4.1] - moka [0.9.6] - serde [1.0.147] - thiserror [1.0.37] - url [2.3.1] ## [0.7.0] - 2022-06-17 ### Changed - The `CacheManager` trait is now implemented directly against the `MokaManager` struct rather than `Arc`. The Arc is now internal to the `MokaManager` struct as part of the `cache` field. - Updated the minimum versions of the following dependencies: - async-trait [0.1.56] - http [0.2.8] - miette [4.7.1] - moka [0.8.5] - serde [1.0.137] - thiserror [1.0.31] ## [0.6.5] - 2022-04-30 ### Changed - Updated the minimum versions of the following dependencies: - http [0.2.7] ## [0.6.4] - 2022-04-26 ### Added - This changelog to keep a record of notable changes to the project. http-cache-0.21.0/Cargo.lock0000644000001632460000000000100111230ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "async-attributes" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote", "syn 1.0.109", ] [[package]] name = "async-channel" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-channel" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-executor" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ "async-task", "concurrent-queue", "fastrand 2.3.0", "futures-lite 2.6.0", "pin-project-lite", "slab", ] [[package]] name = "async-global-executor" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ "async-channel 2.3.1", "async-executor", "async-io", "async-lock", "blocking", "futures-lite 2.6.0", "once_cell", ] [[package]] name = "async-io" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" dependencies = [ "async-lock", "cfg-if", "concurrent-queue", "futures-io", "futures-lite 2.6.0", "parking", "polling", "rustix", "slab", "tracing", "windows-sys 0.59.0", ] [[package]] name = "async-lock" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener 5.4.0", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-process" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" dependencies = [ "async-channel 2.3.1", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", "event-listener 5.4.0", "futures-lite 2.6.0", "rustix", "tracing", ] [[package]] name = "async-signal" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" dependencies = [ "async-io", "async-lock", "atomic-waker", "cfg-if", "futures-core", "futures-io", "rustix", "signal-hook-registry", "slab", "windows-sys 0.59.0", ] [[package]] name = "async-std" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ "async-channel 1.9.0", "async-global-executor", "async-io", "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", "futures-lite 2.6.0", "gloo-timers", "kv-log-macro", "log", "memchr", "once_cell", "pin-project-lite", "pin-utils", "slab", "wasm-bindgen-futures", ] [[package]] name = "async-task" version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", ] [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bincode" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "blocking" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ "async-channel 2.3.1", "async-task", "futures-io", "futures-lite 2.6.0", "piper", ] [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cacache" version = "13.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5063741c7b2e260bbede781cf4679632dd90e2718e99f7715e46824b65670b" dependencies = [ "async-std", "digest", "either", "futures", "hex", "libc", "memmap2", "miette", "reflink-copy", "serde", "serde_derive", "serde_json", "sha1", "sha2", "ssri", "tempfile", "thiserror", "tokio", "tokio-stream", "walkdir", ] [[package]] name = "cc" version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "concurrent-queue" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "deranged" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "errno" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", "windows-sys 0.60.2", ] [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", "pin-project-lite", ] [[package]] name = "event-listener-strategy" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.4.0", "pin-project-lite", ] [[package]] name = "fastrand" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ "fastrand 1.9.0", "futures-core", "futures-io", "memchr", "parking", "pin-project-lite", "waker-fn", ] [[package]] name = "futures-lite" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand 2.3.0", "futures-core", "futures-io", "parking", "pin-project-lite", ] [[package]] name = "futures-macro" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generator" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" dependencies = [ "cc", "cfg-if", "libc", "log", "rustversion", "windows", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gloo-timers" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", ] [[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-cache" version = "0.21.0" dependencies = [ "async-attributes", "async-std", "async-trait", "bincode", "cacache", "http", "http-cache-semantics", "http-types", "httpdate", "moka", "serde", "tokio", "url", ] [[package]] name = "http-cache-semantics" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92baf25cf0b8c9246baecf3a444546360a97b569168fdf92563ee6a47829920c" dependencies = [ "http", "http-serde", "serde", "time", ] [[package]] name = "http-serde" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" dependencies = [ "http", "serde", ] [[package]] name = "http-types" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" dependencies = [ "anyhow", "async-channel 1.9.0", "base64 0.13.1", "futures-lite 1.13.0", "infer", "pin-project-lite", "rand", "serde", "serde_json", "serde_qs", "serde_urlencoded", "url", ] [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "icu_collections" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locale_core" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_normalizer" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", "zerotrie", "zerovec", ] [[package]] name = "idna" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "infer" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" [[package]] name = "instant" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "kv-log-macro" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 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.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "value-bag", ] [[package]] name = "loom" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ "cfg-if", "generator", "scoped-tls", "tracing", "tracing-subscriber", ] [[package]] name = "matchers" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ "regex-automata 0.1.10", ] [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] [[package]] name = "miette" version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" dependencies = [ "miette-derive", "once_cell", "thiserror", "unicode-width", ] [[package]] name = "miette-derive" version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "miniz_oxide" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "moka" version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" dependencies = [ "async-lock", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "event-listener 5.4.0", "futures-util", "loom", "parking_lot", "portable-atomic", "rustc_version", "smallvec", "tagptr", "thiserror", "uuid", ] [[package]] name = "nu-ansi-term" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", "winapi", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.52.6", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand 2.3.0", "futures-io", ] [[package]] name = "polling" version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", "rustix", "tracing", "windows-sys 0.59.0", ] [[package]] name = "portable-atomic" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ "zerovec", ] [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", "libc", "rand_chacha", "rand_core", "rand_hc", ] [[package]] name = "rand_chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ "getrandom 0.1.16", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ "rand_core", ] [[package]] name = "redox_syscall" version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags", ] [[package]] name = "reflink-copy" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c81d000a2c524133cc00d2f92f019d399e57906c3b7119271a2495354fe895" dependencies = [ "cfg-if", "libc", "rustix", "windows", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.9", "regex-syntax 0.8.5", ] [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ "regex-syntax 0.6.29", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax 0.8.5", ] [[package]] name = "regex-syntax" version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_qs" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ "percent-encoding", "serde", "thiserror", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "sha-1" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha2" version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sharded-slab" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] [[package]] name = "slab" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "ssri" version = "9.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7a2b3c2bc9693bcb40870c4e9b5bf0d79f9cb46273321bf855ec513e919082" dependencies = [ "base64 0.21.7", "digest", "hex", "miette", "serde", "sha-1", "sha2", "thiserror", "xxhash-rust", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "synstructure" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "tagptr" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand 2.3.0", "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.59.0", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "thread_local" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", ] [[package]] name = "time" version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", ] [[package]] name = "tinystr" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tokio" version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", "pin-project-lite", "tokio-macros", ] [[package]] name = "tokio-macros" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "tokio-stream" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", "tokio", ] [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", ] [[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", ] [[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "url" version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", ] [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom 0.3.3", "js-sys", "wasm-bindgen", ] [[package]] name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "waker-fn" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "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" version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", "windows-core", "windows-future", "windows-link", "windows-numerics", ] [[package]] name = "windows-collections" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ "windows-core", ] [[package]] name = "windows-core" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-future" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", "windows-link", "windows-threading", ] [[package]] name = "windows-implement" version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "windows-interface" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "windows-link" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core", "windows-link", ] [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets 0.53.2", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows-targets" version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", "windows_i686_gnullvm 0.53.0", "windows_i686_msvc 0.53.0", "windows_x86_64_gnu 0.53.0", "windows_x86_64_gnullvm 0.53.0", "windows_x86_64_msvc 0.53.0", ] [[package]] name = "windows-threading" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ "windows-link", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "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 = "xxhash-rust" version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yoke" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", "synstructure", ] [[package]] name = "zerocopy" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] [[package]] name = "zerofrom" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", "synstructure", ] [[package]] name = "zerotrie" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ "displaydoc", "yoke", "zerofrom", ] [[package]] name = "zerovec" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] http-cache-0.21.0/Cargo.toml0000644000000045200000000000100111330ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.82.0" name = "http-cache" version = "0.21.0" authors = [ "Christian Haynes <06chaynes@gmail.com>", "Kat Marchán ", ] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "An HTTP caching middleware" homepage = "https://http-cache.rs" readme = "README.md" keywords = [ "cache", "http", "middleware", ] categories = [ "caching", "web-programming::http-client", ] license = "MIT OR Apache-2.0" repository = "https://github.com/06chaynes/http-cache" [package.metadata.docs.rs] rustdoc-args = [ "--cfg", "docsrs", ] [features] cacache-async-std = ["cacache/async-std"] cacache-tokio = ["cacache/tokio-runtime"] default = [ "manager-cacache", "cacache-async-std", ] manager-cacache = [ "cacache", "bincode", ] manager-moka = [ "moka", "bincode", ] with-http-types = ["http-types"] [lib] name = "http_cache" path = "src/lib.rs" [dependencies.async-trait] version = "0.1.85" [dependencies.bincode] version = "1.3.3" optional = true [dependencies.cacache] version = "13.1.0" features = ["mmap"] optional = true default-features = false [dependencies.http] version = "1.2.0" [dependencies.http-cache-semantics] version = "2.1.0" [dependencies.http-types] version = "2.12.0" optional = true default-features = false [dependencies.httpdate] version = "1.0.3" [dependencies.moka] version = "0.12.10" features = ["future"] optional = true [dependencies.serde] version = "1.0.217" features = ["derive"] [dependencies.url] version = "2.5.4" features = ["serde"] [dev-dependencies.async-attributes] version = "1.1.2" [dev-dependencies.async-std] version = "1.13.0" [dev-dependencies.http-cache-semantics] version = "2.1.0" [dev-dependencies.tokio] version = "1.43.0" features = [ "macros", "rt", "rt-multi-thread", ] http-cache-0.21.0/Cargo.toml.orig000064400000000000000000000027171046102023000146220ustar 00000000000000[package] name = "http-cache" version = "0.21.0" description = "An HTTP caching middleware" authors = ["Christian Haynes <06chaynes@gmail.com>", "Kat Marchán "] repository = "https://github.com/06chaynes/http-cache" homepage = "https://http-cache.rs" license = "MIT OR Apache-2.0" readme = "README.md" keywords = ["cache", "http", "middleware"] categories = [ "caching", "web-programming::http-client" ] edition = "2021" rust-version = "1.82.0" [dependencies] async-trait = "0.1.85" bincode = { version = "1.3.3", optional = true } cacache = { version = "13.1.0", default-features = false, features = ["mmap"], optional = true } http = "1.2.0" http-cache-semantics = "2.1.0" http-types = { version = "2.12.0", default-features = false, optional = true } httpdate = "1.0.3" moka = { version = "0.12.10", features = ["future"], optional = true } serde = { version = "1.0.217", features = ["derive"] } url = { version = "2.5.4", features = ["serde"] } [dev-dependencies] async-attributes = "1.1.2" async-std = { version = "1.13.0" } http-cache-semantics = "2.1.0" tokio = { version = "1.43.0", features = [ "macros", "rt", "rt-multi-thread" ] } [features] default = ["manager-cacache", "cacache-async-std"] manager-cacache = ["cacache", "bincode"] cacache-tokio = ["cacache/tokio-runtime"] cacache-async-std = ["cacache/async-std"] manager-moka = ["moka", "bincode"] with-http-types = ["http-types"] [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] http-cache-0.21.0/README.md000064400000000000000000000065471046102023000132170ustar 00000000000000# http-cache [![CI](https://img.shields.io/github/actions/workflow/status/06chaynes/http-cache/http-cache.yml?label=CI&style=for-the-badge)](https://github.com/06chaynes/http-cache/actions/workflows/http-cache.yml) [![Crates.io](https://img.shields.io/crates/v/http-cache?style=for-the-badge)](https://crates.io/crates/http-cache) [![Docs.rs](https://img.shields.io/docsrs/http-cache?style=for-the-badge)](https://docs.rs/http-cache) [![Codecov](https://img.shields.io/codecov/c/github/06chaynes/http-cache?style=for-the-badge)](https://app.codecov.io/gh/06chaynes/http-cache) ![Crates.io](https://img.shields.io/crates/l/http-cache?style=for-the-badge) A caching middleware that follows HTTP caching rules, thanks to [http-cache-semantics](https://github.com/kornelski/rusty-http-cache-semantics). By default, it uses [cacache](https://github.com/zkat/cacache-rs) as the backend cache manager. ## How do I use this? Likely you won't! At least not directly. Unless you are looking to implement a custom backend cache manager or client middleware you'll probably want to pull in one of the existing client implementations instead. See the [Provided Client Implementations](#provided-client-implementations) section below. ## Minimum Supported Rust Version (MSRV) 1.82.0 ## Install With [cargo add](https://github.com/killercup/cargo-edit#Installation) installed : ```sh cargo add http-cache ``` ## Features The following features are available. By default `manager-cacache` and `cacache-async-std` are enabled. - `manager-cacache` (default): enable [cacache](https://github.com/zkat/cacache-rs), a high-performance disk cache, backend manager. - `cacache-async-std` (default): enable [async-std](https://github.com/async-rs/async-std) runtime support for cacache. - `cacache-tokio` (disabled): enable [tokio](https://github.com/tokio-rs/tokio) runtime support for cacache. - `manager-moka` (disabled): enable [moka](https://github.com/moka-rs/moka), a high-performance in-memory cache, backend manager. - `with-http-types` (disabled): enable [http-types](https://github.com/http-rs/http-types) type conversion support ## Documentation - [API Docs](https://docs.rs/http-cache) ## Provided Client Implementations - **Surf**: See [README](https://github.com/06chaynes/http-cache/blob/main/http-cache-surf/README.md) for more details - **Reqwest**: See [README](https://github.com/06chaynes/http-cache/blob/main/http-cache-reqwest/README.md) for more details ## Additional Manager Implementations - **quick-cache**: See [README](https://github.com/06chaynes/http-cache/blob/main/http-cache-quickcache/README.md) for more details ## License Licensed under either of - Apache License, Version 2.0 ([LICENSE-APACHE](https://github.com/06chaynes/http-cache/blob/main/LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](https://github.com/06chaynes/http-cache/blob/main/LICENSE-MIT) or ) at your option. ## Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. http-cache-0.21.0/src/error.rs000064400000000000000000000014721046102023000142160ustar 00000000000000use std::fmt; /// Generic error type for the `HttpCache` middleware. pub type BoxError = Box; /// A `Result` typedef to use with the [`BoxError`] type pub type Result = std::result::Result; /// Error type for unknown http versions #[derive(Debug, Default, Copy, Clone)] pub struct BadVersion; impl fmt::Display for BadVersion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Unknown HTTP version") } } impl std::error::Error for BadVersion {} /// Error type for bad header values #[derive(Debug, Default, Copy, Clone)] pub struct BadHeader; impl fmt::Display for BadHeader { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Error parsing header value") } } impl std::error::Error for BadHeader {} http-cache-0.21.0/src/lib.rs000064400000000000000000000676131046102023000136440ustar 00000000000000#![forbid(unsafe_code, future_incompatible)] #![deny( missing_docs, missing_debug_implementations, missing_copy_implementations, nonstandard_style, unused_qualifications, unused_import_braces, unused_extern_crates, trivial_casts, trivial_numeric_casts )] #![allow(clippy::doc_lazy_continuation)] #![cfg_attr(docsrs, feature(doc_cfg))] //! A caching middleware that follows HTTP caching rules, thanks to //! [`http-cache-semantics`](https://github.com/kornelski/rusty-http-cache-semantics). //! By default, it uses [`cacache`](https://github.com/zkat/cacache-rs) as the backend cache manager. //! //! ## Features //! //! The following features are available. By default `manager-cacache` and `cacache-async-std` are enabled. //! //! - `manager-cacache` (default): enable [cacache](https://github.com/zkat/cacache-rs), //! a high-performance disk cache, backend manager. //! - `cacache-async-std` (default): enable [async-std](https://github.com/async-rs/async-std) runtime support for cacache. //! - `cacache-tokio` (disabled): enable [tokio](https://github.com/tokio-rs/tokio) runtime support for cacache. //! - `manager-moka` (disabled): enable [moka](https://github.com/moka-rs/moka), //! a high-performance in-memory cache, backend manager. //! - `with-http-types` (disabled): enable [http-types](https://github.com/http-rs/http-types) //! type conversion support mod error; mod managers; use std::{ collections::HashMap, convert::TryFrom, fmt::{self, Debug}, str::FromStr, sync::Arc, time::SystemTime, }; use http::{header::CACHE_CONTROL, request, response, StatusCode}; use http_cache_semantics::{AfterResponse, BeforeRequest, CachePolicy}; use serde::{Deserialize, Serialize}; use url::Url; pub use error::{BadHeader, BadVersion, BoxError, Result}; #[cfg(feature = "manager-cacache")] pub use managers::cacache::CACacheManager; #[cfg(feature = "manager-moka")] pub use managers::moka::MokaManager; // Exposing the moka cache for convenience, renaming to avoid naming conflicts #[cfg(feature = "manager-moka")] #[cfg_attr(docsrs, doc(cfg(feature = "manager-moka")))] pub use moka::future::{Cache as MokaCache, CacheBuilder as MokaCacheBuilder}; // Custom headers used to indicate cache status (hit or miss) /// `x-cache` header: Value will be HIT if the response was served from cache, MISS if not pub const XCACHE: &str = "x-cache"; /// `x-cache-lookup` header: Value will be HIT if a response existed in cache, MISS if not pub const XCACHELOOKUP: &str = "x-cache-lookup"; /// Represents a basic cache status /// Used in the custom headers `x-cache` and `x-cache-lookup` #[derive(Debug, Copy, Clone)] pub enum HitOrMiss { /// Yes, there was a hit HIT, /// No, there was no hit MISS, } impl fmt::Display for HitOrMiss { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::HIT => write!(f, "HIT"), Self::MISS => write!(f, "MISS"), } } } /// Represents an HTTP version #[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)] #[non_exhaustive] pub enum HttpVersion { /// HTTP Version 0.9 #[serde(rename = "HTTP/0.9")] Http09, /// HTTP Version 1.0 #[serde(rename = "HTTP/1.0")] Http10, /// HTTP Version 1.1 #[serde(rename = "HTTP/1.1")] Http11, /// HTTP Version 2.0 #[serde(rename = "HTTP/2.0")] H2, /// HTTP Version 3.0 #[serde(rename = "HTTP/3.0")] H3, } impl fmt::Display for HttpVersion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { HttpVersion::Http09 => write!(f, "HTTP/0.9"), HttpVersion::Http10 => write!(f, "HTTP/1.0"), HttpVersion::Http11 => write!(f, "HTTP/1.1"), HttpVersion::H2 => write!(f, "HTTP/2.0"), HttpVersion::H3 => write!(f, "HTTP/3.0"), } } } /// A basic generic type that represents an HTTP response #[derive(Debug, Clone, Deserialize, Serialize)] pub struct HttpResponse { /// HTTP response body pub body: Vec, /// HTTP response headers pub headers: HashMap, /// HTTP response status code pub status: u16, /// HTTP response url pub url: Url, /// HTTP response version pub version: HttpVersion, } impl HttpResponse { /// Returns `http::response::Parts` pub fn parts(&self) -> Result { let mut converted = response::Builder::new().status(self.status).body(())?; { let headers = converted.headers_mut(); for header in &self.headers { headers.insert( http::header::HeaderName::from_str(header.0.as_str())?, http::HeaderValue::from_str(header.1.as_str())?, ); } } Ok(converted.into_parts().0) } /// Returns the status code of the warning header if present #[must_use] pub fn warning_code(&self) -> Option { self.headers.get("warning").and_then(|hdr| { hdr.as_str().chars().take(3).collect::().parse().ok() }) } /// Adds a warning header to a response pub fn add_warning(&mut self, url: &Url, code: usize, message: &str) { // warning = "warning" ":" 1#warning-value // warning-value = warn-code SP warn-agent SP warn-text [SP warn-date] // warn-code = 3DIGIT // warn-agent = ( host [ ":" port ] ) | pseudonym // ; the name or pseudonym of the server adding // ; the warning header, for use in debugging // warn-text = quoted-string // warn-date = <"> HTTP-date <"> // (https://tools.ietf.org/html/rfc2616#section-14.46) self.headers.insert( "warning".to_string(), format!( "{} {} {:?} \"{}\"", code, url.host().expect("Invalid URL"), message, httpdate::fmt_http_date(SystemTime::now()) ), ); } /// Removes a warning header from a response pub fn remove_warning(&mut self) { self.headers.remove("warning"); } /// Update the headers from `http::response::Parts` pub fn update_headers(&mut self, parts: &response::Parts) -> Result<()> { for header in parts.headers.iter() { self.headers.insert( header.0.as_str().to_string(), header.1.to_str()?.to_string(), ); } Ok(()) } /// Checks if the Cache-Control header contains the must-revalidate directive #[must_use] pub fn must_revalidate(&self) -> bool { self.headers.get(CACHE_CONTROL.as_str()).is_some_and(|val| { val.as_str().to_lowercase().contains("must-revalidate") }) } /// Adds the custom `x-cache` header to the response pub fn cache_status(&mut self, hit_or_miss: HitOrMiss) { self.headers.insert(XCACHE.to_string(), hit_or_miss.to_string()); } /// Adds the custom `x-cache-lookup` header to the response pub fn cache_lookup_status(&mut self, hit_or_miss: HitOrMiss) { self.headers.insert(XCACHELOOKUP.to_string(), hit_or_miss.to_string()); } } /// A trait providing methods for storing, reading, and removing cache records. #[async_trait::async_trait] pub trait CacheManager: Send + Sync + 'static { /// Attempts to pull a cached response and related policy from cache. async fn get( &self, cache_key: &str, ) -> Result>; /// Attempts to cache a response and related policy. async fn put( &self, cache_key: String, res: HttpResponse, policy: CachePolicy, ) -> Result; /// Attempts to remove a record from cache. async fn delete(&self, cache_key: &str) -> Result<()>; } /// Describes the functionality required for interfacing with HTTP client middleware #[async_trait::async_trait] pub trait Middleware: Send { /// Allows the cache mode to be overridden. /// /// This overrides any cache mode set in the configuration, including cache_mode_fn. fn overridden_cache_mode(&self) -> Option { None } /// Determines if the request method is either GET or HEAD fn is_method_get_head(&self) -> bool; /// Returns a new cache policy with default options fn policy(&self, response: &HttpResponse) -> Result; /// Returns a new cache policy with custom options fn policy_with_options( &self, response: &HttpResponse, options: CacheOptions, ) -> Result; /// Attempts to update the request headers with the passed `http::request::Parts` fn update_headers(&mut self, parts: &request::Parts) -> Result<()>; /// Attempts to force the "no-cache" directive on the request fn force_no_cache(&mut self) -> Result<()>; /// Attempts to construct `http::request::Parts` from the request fn parts(&self) -> Result; /// Attempts to determine the requested url fn url(&self) -> Result; /// Attempts to determine the request method fn method(&self) -> Result; /// Attempts to fetch an upstream resource and return an [`HttpResponse`] async fn remote_fetch(&mut self) -> Result; } /// Similar to [make-fetch-happen cache options](https://github.com/npm/make-fetch-happen#--optscache). /// Passed in when the [`HttpCache`] struct is being built. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum CacheMode { /// Will inspect the HTTP cache on the way to the network. /// If there is a fresh response it will be used. /// If there is a stale response a conditional request will be created, /// and a normal request otherwise. /// It then updates the HTTP cache with the response. /// If the revalidation request fails (for example, on a 500 or if you're offline), /// the stale response will be returned. #[default] Default, /// Behaves as if there is no HTTP cache at all. NoStore, /// Behaves as if there is no HTTP cache on the way to the network. /// Ergo, it creates a normal request and updates the HTTP cache with the response. Reload, /// Creates a conditional request if there is a response in the HTTP cache /// and a normal request otherwise. It then updates the HTTP cache with the response. NoCache, /// Uses any response in the HTTP cache matching the request, /// not paying attention to staleness. If there was no response, /// it creates a normal request and updates the HTTP cache with the response. ForceCache, /// Uses any response in the HTTP cache matching the request, /// not paying attention to staleness. If there was no response, /// it returns a network error. OnlyIfCached, /// Overrides the check that determines if a response can be cached to always return true on 200. /// Uses any response in the HTTP cache matching the request, /// not paying attention to staleness. If there was no response, /// it creates a normal request and updates the HTTP cache with the response. IgnoreRules, } impl TryFrom for HttpVersion { type Error = BoxError; fn try_from(value: http::Version) -> Result { Ok(match value { http::Version::HTTP_09 => Self::Http09, http::Version::HTTP_10 => Self::Http10, http::Version::HTTP_11 => Self::Http11, http::Version::HTTP_2 => Self::H2, http::Version::HTTP_3 => Self::H3, _ => return Err(Box::new(BadVersion)), }) } } impl From for http::Version { fn from(value: HttpVersion) -> Self { match value { HttpVersion::Http09 => Self::HTTP_09, HttpVersion::Http10 => Self::HTTP_10, HttpVersion::Http11 => Self::HTTP_11, HttpVersion::H2 => Self::HTTP_2, HttpVersion::H3 => Self::HTTP_3, } } } #[cfg(feature = "http-types")] impl TryFrom for HttpVersion { type Error = BoxError; fn try_from(value: http_types::Version) -> Result { Ok(match value { http_types::Version::Http0_9 => Self::Http09, http_types::Version::Http1_0 => Self::Http10, http_types::Version::Http1_1 => Self::Http11, http_types::Version::Http2_0 => Self::H2, http_types::Version::Http3_0 => Self::H3, _ => return Err(Box::new(BadVersion)), }) } } #[cfg(feature = "http-types")] impl From for http_types::Version { fn from(value: HttpVersion) -> Self { match value { HttpVersion::Http09 => Self::Http0_9, HttpVersion::Http10 => Self::Http1_0, HttpVersion::Http11 => Self::Http1_1, HttpVersion::H2 => Self::Http2_0, HttpVersion::H3 => Self::Http3_0, } } } /// Options struct provided by /// [`http-cache-semantics`](https://github.com/kornelski/rusty-http-cache-semantics). pub use http_cache_semantics::CacheOptions; /// A closure that takes [`http::request::Parts`] and returns a [`String`]. /// By default, the cache key is a combination of the request method and uri with a colon in between. pub type CacheKey = Arc String + Send + Sync>; /// A closure that takes [`http::request::Parts`] and returns a [`CacheMode`] pub type CacheModeFn = Arc CacheMode + Send + Sync>; /// A closure that takes [`http::request::Parts`], [`Option`], the default cache key ([`&str``]) and returns [`Vec`] of keys to bust the cache for. /// An empty vector means that no cache busting will be performed. pub type CacheBust = Arc< dyn Fn(&request::Parts, &Option, &str) -> Vec + Send + Sync, >; /// Can be used to override the default [`CacheOptions`] and cache key. /// The cache key is a closure that takes [`http::request::Parts`] and returns a [`String`]. #[derive(Clone)] pub struct HttpCacheOptions { /// Override the default cache options. pub cache_options: Option, /// Override the default cache key generator. pub cache_key: Option, /// Override the default cache mode. pub cache_mode_fn: Option, /// Bust the caches of the returned keys. pub cache_bust: Option, /// Determines if the cache status headers should be added to the response. pub cache_status_headers: bool, } impl Default for HttpCacheOptions { fn default() -> Self { Self { cache_options: None, cache_key: None, cache_mode_fn: None, cache_bust: None, cache_status_headers: true, } } } impl Debug for HttpCacheOptions { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("HttpCacheOptions") .field("cache_options", &self.cache_options) .field("cache_key", &"Fn(&request::Parts) -> String") .field("cache_mode_fn", &"Fn(&request::Parts) -> CacheMode") .field("cache_bust", &"Fn(&request::Parts) -> Vec") .field("cache_status_headers", &self.cache_status_headers) .finish() } } impl HttpCacheOptions { fn create_cache_key( &self, parts: &request::Parts, override_method: Option<&str>, ) -> String { if let Some(cache_key) = &self.cache_key { cache_key(parts) } else { format!( "{}:{}", override_method.unwrap_or_else(|| parts.method.as_str()), parts.uri ) } } } /// Caches requests according to http spec. #[derive(Debug, Clone)] pub struct HttpCache { /// Determines the manager behavior. pub mode: CacheMode, /// Manager instance that implements the [`CacheManager`] trait. /// By default, a manager implementation with [`cacache`](https://github.com/zkat/cacache-rs) /// as the backend has been provided, see [`CACacheManager`]. pub manager: T, /// Override the default cache options. pub options: HttpCacheOptions, } #[allow(dead_code)] impl HttpCache { /// Determines if the request should be cached pub fn can_cache_request( &self, middleware: &impl Middleware, ) -> Result { let mode = self.cache_mode(middleware)?; Ok(mode == CacheMode::IgnoreRules || middleware.is_method_get_head() && mode != CacheMode::NoStore) } /// Runs the actions to preform when the client middleware is running without the cache pub async fn run_no_cache( &self, middleware: &mut impl Middleware, ) -> Result<()> { self.manager .delete( &self .options .create_cache_key(&middleware.parts()?, Some("GET")), ) .await .ok(); let cache_key = self.options.create_cache_key(&middleware.parts()?, None); if let Some(cache_bust) = &self.options.cache_bust { for key_to_cache_bust in cache_bust( &middleware.parts()?, &self.options.cache_key, &cache_key, ) { self.manager.delete(&key_to_cache_bust).await?; } } Ok(()) } /// Attempts to run the passed middleware along with the cache pub async fn run( &self, mut middleware: impl Middleware, ) -> Result { let is_cacheable = self.can_cache_request(&middleware)?; if !is_cacheable { return self.remote_fetch(&mut middleware).await; } let cache_key = self.options.create_cache_key(&middleware.parts()?, None); if let Some(cache_bust) = &self.options.cache_bust { for key_to_cache_bust in cache_bust( &middleware.parts()?, &self.options.cache_key, &cache_key, ) { self.manager.delete(&key_to_cache_bust).await?; } } if let Some(store) = self.manager.get(&cache_key).await? { let (mut res, policy) = store; if self.options.cache_status_headers { res.cache_lookup_status(HitOrMiss::HIT); } if let Some(warning_code) = res.warning_code() { // https://tools.ietf.org/html/rfc7234#section-4.3.4 // // If a stored response is selected for update, the cache MUST: // // * delete any warning header fields in the stored response with // warn-code 1xx (see Section 5.5); // // * retain any warning header fields in the stored response with // warn-code 2xx; // if (100..200).contains(&warning_code) { res.remove_warning(); } } match self.cache_mode(&middleware)? { CacheMode::Default => { self.conditional_fetch(middleware, res, policy).await } CacheMode::NoCache => { middleware.force_no_cache()?; let mut res = self.remote_fetch(&mut middleware).await?; if self.options.cache_status_headers { res.cache_lookup_status(HitOrMiss::HIT); } Ok(res) } CacheMode::ForceCache | CacheMode::OnlyIfCached | CacheMode::IgnoreRules => { // 112 Disconnected operation // SHOULD be included if the cache is intentionally disconnected from // the rest of the network for a period of time. // (https://tools.ietf.org/html/rfc2616#section-14.46) res.add_warning( &res.url.clone(), 112, "Disconnected operation", ); if self.options.cache_status_headers { res.cache_status(HitOrMiss::HIT); } Ok(res) } _ => self.remote_fetch(&mut middleware).await, } } else { match self.cache_mode(&middleware)? { CacheMode::OnlyIfCached => { // ENOTCACHED let mut res = HttpResponse { body: b"GatewayTimeout".to_vec(), headers: HashMap::default(), status: 504, url: middleware.url()?, version: HttpVersion::Http11, }; if self.options.cache_status_headers { res.cache_status(HitOrMiss::MISS); res.cache_lookup_status(HitOrMiss::MISS); } Ok(res) } _ => self.remote_fetch(&mut middleware).await, } } } fn cache_mode(&self, middleware: &impl Middleware) -> Result { Ok(if let Some(mode) = middleware.overridden_cache_mode() { mode } else if let Some(cache_mode_fn) = &self.options.cache_mode_fn { cache_mode_fn(&middleware.parts()?) } else { self.mode }) } async fn remote_fetch( &self, middleware: &mut impl Middleware, ) -> Result { let mut res = middleware.remote_fetch().await?; if self.options.cache_status_headers { res.cache_status(HitOrMiss::MISS); res.cache_lookup_status(HitOrMiss::MISS); } let policy = match self.options.cache_options { Some(options) => middleware.policy_with_options(&res, options)?, None => middleware.policy(&res)?, }; let is_get_head = middleware.is_method_get_head(); let mode = self.cache_mode(middleware)?; let mut is_cacheable = is_get_head && mode != CacheMode::NoStore && res.status == 200 && policy.is_storable(); if mode == CacheMode::IgnoreRules && res.status == 200 { is_cacheable = true; } if is_cacheable { Ok(self .manager .put( self.options.create_cache_key(&middleware.parts()?, None), res, policy, ) .await?) } else if !is_get_head { self.manager .delete( &self .options .create_cache_key(&middleware.parts()?, Some("GET")), ) .await .ok(); Ok(res) } else { Ok(res) } } async fn conditional_fetch( &self, mut middleware: impl Middleware, mut cached_res: HttpResponse, mut policy: CachePolicy, ) -> Result { let before_req = policy.before_request(&middleware.parts()?, SystemTime::now()); match before_req { BeforeRequest::Fresh(parts) => { cached_res.update_headers(&parts)?; if self.options.cache_status_headers { cached_res.cache_status(HitOrMiss::HIT); cached_res.cache_lookup_status(HitOrMiss::HIT); } return Ok(cached_res); } BeforeRequest::Stale { request: parts, matches } => { if matches { middleware.update_headers(&parts)?; } } } let req_url = middleware.url()?; match middleware.remote_fetch().await { Ok(mut cond_res) => { let status = StatusCode::from_u16(cond_res.status)?; if status.is_server_error() && cached_res.must_revalidate() { // 111 Revalidation failed // MUST be included if a cache returns a stale response // because an attempt to revalidate the response failed, // due to an inability to reach the server. // (https://tools.ietf.org/html/rfc2616#section-14.46) cached_res.add_warning( &req_url, 111, "Revalidation failed", ); if self.options.cache_status_headers { cached_res.cache_status(HitOrMiss::HIT); } Ok(cached_res) } else if cond_res.status == 304 { let after_res = policy.after_response( &middleware.parts()?, &cond_res.parts()?, SystemTime::now(), ); match after_res { AfterResponse::Modified(new_policy, parts) | AfterResponse::NotModified(new_policy, parts) => { policy = new_policy; cached_res.update_headers(&parts)?; } } if self.options.cache_status_headers { cached_res.cache_status(HitOrMiss::HIT); cached_res.cache_lookup_status(HitOrMiss::HIT); } let res = self .manager .put( self.options .create_cache_key(&middleware.parts()?, None), cached_res, policy, ) .await?; Ok(res) } else if cond_res.status == 200 { let policy = match self.options.cache_options { Some(options) => middleware .policy_with_options(&cond_res, options)?, None => middleware.policy(&cond_res)?, }; if self.options.cache_status_headers { cond_res.cache_status(HitOrMiss::MISS); cond_res.cache_lookup_status(HitOrMiss::HIT); } let res = self .manager .put( self.options .create_cache_key(&middleware.parts()?, None), cond_res, policy, ) .await?; Ok(res) } else { if self.options.cache_status_headers { cached_res.cache_status(HitOrMiss::HIT); } Ok(cached_res) } } Err(e) => { if cached_res.must_revalidate() { Err(e) } else { // 111 Revalidation failed // MUST be included if a cache returns a stale response // because an attempt to revalidate the response failed, // due to an inability to reach the server. // (https://tools.ietf.org/html/rfc2616#section-14.46) cached_res.add_warning( &req_url, 111, "Revalidation failed", ); if self.options.cache_status_headers { cached_res.cache_status(HitOrMiss::HIT); } Ok(cached_res) } } } } } #[cfg(test)] mod test; http-cache-0.21.0/src/managers/cacache.rs000064400000000000000000000041551046102023000162320ustar 00000000000000use std::path::PathBuf; use crate::{CacheManager, HttpResponse, Result}; use http_cache_semantics::CachePolicy; use serde::{Deserialize, Serialize}; /// Implements [`CacheManager`] with [`cacache`](https://github.com/zkat/cacache-rs) as the backend. #[derive(Clone)] pub struct CACacheManager { /// Directory where the cache will be stored. pub path: PathBuf, /// Options for removing cache entries. pub remove_opts: cacache::RemoveOpts, } impl std::fmt::Debug for CACacheManager { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CACacheManager").field("path", &self.path).finish() } } #[derive(Debug, Deserialize, Serialize)] struct Store { response: HttpResponse, policy: CachePolicy, } #[allow(dead_code)] impl CACacheManager { /// Creates a new [`CACacheManager`] with the given path. pub fn new(path: PathBuf, remove_fully: bool) -> Self { Self { path, remove_opts: cacache::RemoveOpts::new().remove_fully(remove_fully), } } /// Clears out the entire cache. pub async fn clear(&self) -> Result<()> { cacache::clear(&self.path).await?; Ok(()) } } #[async_trait::async_trait] impl CacheManager for CACacheManager { async fn get( &self, cache_key: &str, ) -> Result> { let store: Store = match cacache::read(&self.path, cache_key).await { Ok(d) => bincode::deserialize(&d)?, Err(_e) => { return Ok(None); } }; Ok(Some((store.response, store.policy))) } async fn put( &self, cache_key: String, response: HttpResponse, policy: CachePolicy, ) -> Result { let data = Store { response, policy }; let bytes = bincode::serialize(&data)?; cacache::write(&self.path, cache_key, bytes).await?; Ok(data.response) } async fn delete(&self, cache_key: &str) -> Result<()> { self.remove_opts.clone().remove(&self.path, cache_key).await?; Ok(()) } } http-cache-0.21.0/src/managers/mod.rs000064400000000000000000000001451046102023000154350ustar 00000000000000#[cfg(feature = "manager-cacache")] pub mod cacache; #[cfg(feature = "manager-moka")] pub mod moka; http-cache-0.21.0/src/managers/moka.rs000064400000000000000000000043101046102023000156030ustar 00000000000000use crate::{CacheManager, HttpResponse, Result}; use std::{fmt, sync::Arc}; use http_cache_semantics::CachePolicy; use moka::future::Cache; use serde::{Deserialize, Serialize}; /// Implements [`CacheManager`] with [`moka`](https://github.com/moka-rs/moka) as the backend. #[cfg_attr(docsrs, doc(cfg(feature = "manager-moka")))] #[derive(Clone)] pub struct MokaManager { /// The instance of `moka::future::Cache` pub cache: Arc>>>, } impl fmt::Debug for MokaManager { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // need to add more data, anything helpful f.debug_struct("MokaManager").finish_non_exhaustive() } } impl Default for MokaManager { fn default() -> Self { Self::new(Cache::new(42)) } } #[derive(Debug, Deserialize, Serialize)] struct Store { response: HttpResponse, policy: CachePolicy, } impl MokaManager { /// Create a new manager from a pre-configured Cache pub fn new(cache: Cache>>) -> Self { Self { cache: Arc::new(cache) } } /// Clears out the entire cache. pub async fn clear(&self) -> Result<()> { self.cache.invalidate_all(); self.cache.run_pending_tasks().await; Ok(()) } } #[async_trait::async_trait] impl CacheManager for MokaManager { async fn get( &self, cache_key: &str, ) -> Result> { let store: Store = match self.cache.get(cache_key).await { Some(d) => bincode::deserialize(&d)?, None => return Ok(None), }; Ok(Some((store.response, store.policy))) } async fn put( &self, cache_key: String, response: HttpResponse, policy: CachePolicy, ) -> Result { let data = Store { response: response.clone(), policy }; let bytes = bincode::serialize(&data)?; self.cache.insert(cache_key, Arc::new(bytes)).await; self.cache.run_pending_tasks().await; Ok(response) } async fn delete(&self, cache_key: &str) -> Result<()> { self.cache.invalidate(cache_key).await; self.cache.run_pending_tasks().await; Ok(()) } } http-cache-0.21.0/src/test.rs000064400000000000000000000257441046102023000140540ustar 00000000000000use crate::{ error, CacheMode, HitOrMiss, HttpCacheOptions, HttpResponse, HttpVersion, Result, }; use http::{header::CACHE_CONTROL, StatusCode}; use http_cache_semantics::CacheOptions; use url::Url; use std::{collections::HashMap, str::FromStr}; const GET: &str = "GET"; const TEST_BODY: &[u8] = b"test"; #[test] fn hit_miss() -> Result<()> { // Testing the Debug, Display, and Clone traits for the HitOrMiss ebnum let hit = HitOrMiss::HIT; assert_eq!(format!("{:?}", hit.clone()), "HIT"); assert_eq!(hit.to_string(), "HIT".to_string(),); let miss = HitOrMiss::MISS; assert_eq!(format!("{:?}", miss.clone()), "MISS"); assert_eq!(miss.to_string(), "MISS".to_string(),); Ok(()) } #[test] fn cache_mode() -> Result<()> { // Testing the Debug and Clone traits for the CacheMode enum let mode = CacheMode::Default; assert_eq!(mode.clone(), CacheMode::Default); assert_eq!(format!("{:?}", mode), "Default"); Ok(()) } #[test] fn cache_options() -> Result<()> { // Testing the Debug, Default and Clone traits for the HttpCacheOptions struct let mut opts = HttpCacheOptions::default(); assert_eq!(format!("{:?}", opts.clone()), "HttpCacheOptions { cache_options: None, cache_key: \"Fn(&request::Parts) -> String\", cache_mode_fn: \"Fn(&request::Parts) -> CacheMode\", cache_bust: \"Fn(&request::Parts) -> Vec\", cache_status_headers: true }"); opts.cache_options = Some(CacheOptions::default()); assert_eq!(format!("{:?}", opts.clone()), "HttpCacheOptions { cache_options: Some(CacheOptions { shared: true, cache_heuristic: 0.1, immutable_min_time_to_live: 86400s, ignore_cargo_cult: false }), cache_key: \"Fn(&request::Parts) -> String\", cache_mode_fn: \"Fn(&request::Parts) -> CacheMode\", cache_bust: \"Fn(&request::Parts) -> Vec\", cache_status_headers: true }"); opts.cache_options = None; opts.cache_key = Some(std::sync::Arc::new(|req: &http::request::Parts| { format!("{}:{}:{:?}:test", req.method, req.uri, req.version) })); assert_eq!(format!("{:?}", opts), "HttpCacheOptions { cache_options: None, cache_key: \"Fn(&request::Parts) -> String\", cache_mode_fn: \"Fn(&request::Parts) -> CacheMode\", cache_bust: \"Fn(&request::Parts) -> Vec\", cache_status_headers: true }"); opts.cache_status_headers = false; assert_eq!(format!("{:?}", opts), "HttpCacheOptions { cache_options: None, cache_key: \"Fn(&request::Parts) -> String\", cache_mode_fn: \"Fn(&request::Parts) -> CacheMode\", cache_bust: \"Fn(&request::Parts) -> Vec\", cache_status_headers: false }"); Ok(()) } #[test] #[allow(clippy::default_constructed_unit_structs)] fn test_errors() -> Result<()> { // Testing the Debug, Default, Display and Clone traits for the error types let bv = error::BadVersion::default(); assert_eq!(format!("{:?}", bv.clone()), "BadVersion",); assert_eq!(bv.to_string(), "Unknown HTTP version".to_string(),); let bh = error::BadHeader::default(); assert_eq!(format!("{:?}", bh.clone()), "BadHeader",); assert_eq!(bh.to_string(), "Error parsing header value".to_string(),); Ok(()) } #[test] fn response_methods_work() -> Result<()> { let url = Url::from_str("http://example.com")?; let mut res = HttpResponse { body: TEST_BODY.to_vec(), headers: HashMap::default(), status: 200, url: url.clone(), version: HttpVersion::Http11, }; assert_eq!(format!("{:?}", res.clone()), "HttpResponse { body: [116, 101, 115, 116], headers: {}, status: 200, url: Url { scheme: \"http\", cannot_be_a_base: false, username: \"\", password: None, host: Some(Domain(\"example.com\")), port: None, path: \"/\", query: None, fragment: None }, version: Http11 }"); res.add_warning(&url, 112, "Test Warning"); let code = res.warning_code(); assert!(code.is_some()); assert_eq!(code.unwrap(), 112); res.remove_warning(); let code = res.warning_code(); assert!(code.is_none()); let http_res = http::Response::builder() .header(CACHE_CONTROL.as_str(), "must-revalidate") .status(StatusCode::OK) .body(())?; let parts = http_res.into_parts().0; let cloned_headers = parts.headers.clone(); res.update_headers(&parts)?; assert!(res.must_revalidate()); assert_eq!(res.parts()?.headers, cloned_headers); res.headers.remove(CACHE_CONTROL.as_str()); assert!(!res.must_revalidate()); Ok(()) } #[test] fn version_http() -> Result<()> { assert_eq!(format!("{:?}", HttpVersion::Http09), "Http09"); assert_eq!(format!("{}", HttpVersion::Http09), "HTTP/0.9"); assert_eq!(format!("{:?}", HttpVersion::Http10), "Http10"); assert_eq!(format!("{}", HttpVersion::Http10), "HTTP/1.0"); assert_eq!(format!("{:?}", HttpVersion::Http11), "Http11"); assert_eq!(format!("{}", HttpVersion::Http11), "HTTP/1.1"); assert_eq!(format!("{:?}", HttpVersion::H2), "H2"); assert_eq!(format!("{}", HttpVersion::H2), "HTTP/2.0"); assert_eq!(format!("{:?}", HttpVersion::H3), "H3"); assert_eq!(format!("{}", HttpVersion::H3), "HTTP/3.0"); Ok(()) } #[test] fn can_convert_versions_from_http() -> Result<()> { let v: HttpVersion = http::Version::HTTP_09.try_into()?; assert_eq!(v, HttpVersion::Http09); let v: http::Version = HttpVersion::Http09.into(); assert_eq!(v, http::Version::HTTP_09); let v: HttpVersion = http::Version::HTTP_10.try_into()?; assert_eq!(v, HttpVersion::Http10); let v: http::Version = HttpVersion::Http10.into(); assert_eq!(v, http::Version::HTTP_10); let v: HttpVersion = http::Version::HTTP_11.try_into()?; assert_eq!(v, HttpVersion::Http11); let v: http::Version = HttpVersion::Http11.into(); assert_eq!(v, http::Version::HTTP_11); let v: HttpVersion = http::Version::HTTP_2.try_into()?; assert_eq!(v, HttpVersion::H2); let v: http::Version = HttpVersion::H2.into(); assert_eq!(v, http::Version::HTTP_2); let v: HttpVersion = http::Version::HTTP_3.try_into()?; assert_eq!(v, HttpVersion::H3); let v: http::Version = HttpVersion::H3.into(); assert_eq!(v, http::Version::HTTP_3); Ok(()) } #[cfg(all(test, feature = "with-http-types"))] mod with_http_types { use super::*; #[test] fn can_convert_versions_from_http_types() -> Result<()> { let v: HttpVersion = http_types::Version::Http0_9.try_into()?; assert_eq!(v, HttpVersion::Http09); let v: http_types::Version = HttpVersion::Http09.into(); assert_eq!(v, http_types::Version::Http0_9); let v: HttpVersion = http_types::Version::Http1_0.try_into()?; assert_eq!(v, HttpVersion::Http10); let v: http_types::Version = HttpVersion::Http10.into(); assert_eq!(v, http_types::Version::Http1_0); let v: HttpVersion = http_types::Version::Http1_1.try_into()?; assert_eq!(v, HttpVersion::Http11); let v: http_types::Version = HttpVersion::Http11.into(); assert_eq!(v, http_types::Version::Http1_1); let v: HttpVersion = http_types::Version::Http2_0.try_into()?; assert_eq!(v, HttpVersion::H2); let v: http_types::Version = HttpVersion::H2.into(); assert_eq!(v, http_types::Version::Http2_0); let v: HttpVersion = http_types::Version::Http3_0.try_into()?; assert_eq!(v, HttpVersion::H3); let v: http_types::Version = HttpVersion::H3.into(); assert_eq!(v, http_types::Version::Http3_0); Ok(()) } } #[cfg(feature = "manager-cacache")] mod with_cacache { use super::*; use crate::{CACacheManager, CacheManager}; use http_cache_semantics::CachePolicy; #[cfg(feature = "cacache-async-std")] use async_attributes::test as async_test; #[cfg(feature = "cacache-tokio")] use tokio::test as async_test; #[async_test] async fn cacache() -> Result<()> { let url = Url::parse("http://example.com")?; let manager = CACacheManager::new("./http-cacache-test".into(), true); let http_res = HttpResponse { body: TEST_BODY.to_vec(), headers: Default::default(), status: 200, url: url.clone(), version: HttpVersion::Http11, }; let req = http::Request::get("http://example.com").body(())?; let res = http::Response::builder().status(200).body(TEST_BODY.to_vec())?; let policy = CachePolicy::new(&req, &res); manager .put(format!("{}:{}", GET, &url), http_res.clone(), policy.clone()) .await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_some()); assert_eq!(data.unwrap().0.body, TEST_BODY); let clone = manager.clone(); let clonedata = clone.get(&format!("{}:{}", GET, &url)).await?; assert!(clonedata.is_some()); assert_eq!(clonedata.unwrap().0.body, TEST_BODY); manager.delete(&format!("{}:{}", GET, &url)).await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_none()); manager.put(format!("{}:{}", GET, &url), http_res, policy).await?; manager.clear().await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_none()); std::fs::remove_dir_all("./http-cacache-test")?; Ok(()) } } #[cfg(feature = "manager-moka")] mod with_moka { use super::*; use crate::{CacheManager, MokaManager}; use http_cache_semantics::CachePolicy; use std::sync::Arc; #[async_attributes::test] async fn moka() -> Result<()> { // Added to test custom Debug impl let mm = MokaManager::default(); assert_eq!(format!("{:?}", mm.clone()), "MokaManager { .. }",); let url = Url::parse("http://example.com")?; let manager = Arc::new(mm); let http_res = HttpResponse { body: TEST_BODY.to_vec(), headers: Default::default(), status: 200, url: url.clone(), version: HttpVersion::Http11, }; let req = http::Request::get("http://example.com").body(())?; let res = http::Response::builder().status(200).body(TEST_BODY.to_vec())?; let policy = CachePolicy::new(&req, &res); manager .put(format!("{}:{}", GET, &url), http_res.clone(), policy.clone()) .await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_some()); assert_eq!(data.unwrap().0.body, TEST_BODY); let clone = manager.clone(); let clonedata = clone.get(&format!("{}:{}", GET, &url)).await?; assert!(clonedata.is_some()); assert_eq!(clonedata.unwrap().0.body, TEST_BODY); manager.delete(&format!("{}:{}", GET, &url)).await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_none()); manager.put(format!("{}:{}", GET, &url), http_res, policy).await?; manager.clear().await?; let data = manager.get(&format!("{}:{}", GET, &url)).await?; assert!(data.is_none()); Ok(()) } }