[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [seanmonstar]\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\n\n# Only enable cargo, turn off npm from wasm example\nupdates:\n  - package-ecosystem: \"github-actions\"\n    # Workflow files stored in the\n    # default location of `.github/workflows`\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n    # todo: if only this worked, see https://github.com/dependabot/dependabot-core/issues/4009\n    # only tell us if there's a new 'breaking' change we could upgrade to\n    # versioning-strategy: increase-if-necessary\n    # disable regular version updates, security updates are unaffected\n    open-pull-requests-limit: 0\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n\nenv:\n  REQWEST_TEST_BODY_FULL: 1\n  RUST_BACKTRACE: 1\n  CARGO_INCREMENTAL: 0\n  CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse\n\njobs:\n  ci-pass:\n    name: CI is green\n    runs-on: ubuntu-latest\n    needs:\n      - style\n      - test\n      - features\n      - unstable\n      - nightly\n      - msrv_default\n      - msrv_oldest\n      - android\n      - wasm\n      - docs\n    steps:\n      - run: exit 0\n\n  style:\n    name: Check Style\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          components: rustfmt\n\n      - name: cargo fmt -- --check\n        run: cargo fmt -- --check\n\n      - name: temporary workaround - fmt all files under src\n        # Workaround for rust-lang/cargo#7732\n        run: cargo fmt -- --check $(find . -name '*.rs' -print)\n\n  test:\n    name: ${{ matrix.name }}\n    needs: [style]\n\n    runs-on: ${{ matrix.os || 'ubuntu-latest' }}\n\n    env:\n      AWS_LC_SYS_PREBUILT_NASM: ${{ matrix.aws_lc_sys_prebuilt_nasm || 0 }}\n\n    # The build matrix does not yet support 'allow failures' at job level.\n    # See `jobs.nightly` for the active nightly job definition.\n    strategy:\n      matrix:\n        name:\n          - linux / stable\n          - linux / stable-aarch64-gnu\n          - linux / beta\n          # - linux / nightly\n          - macOS / stable\n          - windows / stable-x86_64-msvc\n          - windows / stable-i686-msvc\n          - windows / stable-aarch64-msvc\n          - windows / stable-x86_64-gnu\n          - windows / stable-i686-gnu\n          - \"feat.: default-tls disabled\"\n          - \"feat.: rustls\"\n          - \"feat.: rustls-no-provider\"\n          - \"feat.: native-tls\"\n          - \"feat.: default-tls and native-tls\"\n          - \"feat.: rustls and rustls-no-provider\"\n          - \"feat.: cookies\"\n          - \"feat.: blocking\"\n          - \"feat.: blocking only\"\n          - \"feat.: gzip\"\n          - \"feat.: brotli\"\n          - \"feat.: deflate\"\n          - \"feat.: query\"\n          - \"feat.: form\"\n          - \"feat.: json\"\n          - \"feat.: multipart\"\n          - \"feat.: stream\"\n          - \"feat.: socks/default-tls\"\n          - \"feat.: socks/native-tls\"\n          - \"feat.: hickory-dns\"\n\n        include:\n          - name: linux / stable\n          - name: linux / stable-aarch64-gnu\n            os: ubuntu-24.04-arm\n            target: aarch64-unknown-linux-gnu\n          - name: linux / beta\n            rust: beta\n          # - name: linux / nightly\n          #   rust: nightly\n          - name: macOS / stable\n            os: macOS-latest\n\n          - name: windows / stable-x86_64-msvc\n            os: windows-latest\n            target: x86_64-pc-windows-msvc\n            features: \"--features blocking,gzip,brotli,zstd,deflate,query,form,json,multipart,stream\"\n            aws_lc_sys_prebuilt_nasm: 1\n          - name: windows / stable-i686-msvc\n            os: windows-latest\n            target: i686-pc-windows-msvc\n            features: \"--features blocking,gzip,brotli,zstd,deflate,query,form,json,multipart,stream\"\n            aws_lc_sys_prebuilt_nasm: 1\n          - name: windows / stable-aarch64-msvc\n            os: windows-11-arm\n            target: aarch64-pc-windows-msvc\n            features: \"--features blocking,gzip,brotli,zstd,deflate,query,form,json,multipart,stream\"\n            aws_lc_sys_prebuilt_nasm: 1\n          - name: windows / stable-x86_64-gnu\n            os: windows-latest\n            rust: stable-x86_64-pc-windows-gnu\n            target: x86_64-pc-windows-gnu\n            features: \"--features blocking,gzip,brotli,zstd,deflate,query,form,json,multipart,stream\"\n            package_name: mingw-w64-x86_64-gcc\n            mingw64_path: \"C:\\\\msys64\\\\mingw64\\\\bin\"\n            aws_lc_sys_prebuilt_nasm: 1\n          - name: windows / stable-i686-gnu\n            os: windows-latest\n            rust: stable-i686-pc-windows-gnu\n            target: i686-pc-windows-gnu\n            features: \"--no-default-features --features blocking,gzip,brotli,zstd,deflate,query,form,json,multipart,stream,native-tls,http2\"\n            package_name: mingw-w64-i686-gcc\n            mingw64_path: \"C:\\\\msys64\\\\mingw32\\\\bin\"\n\n          - name: \"feat.: default-tls disabled\"\n            features: \"--no-default-features\"\n          - name: \"feat.: rustls\"\n            features: \"--no-default-features --features rustls\"\n          - name: \"feat.: rustls-no-provider\"\n            features: \"--no-default-features --features rustls-no-provider\"\n          - name: \"feat.: native-tls\"\n            features: \"--features native-tls\"\n          - name: \"feat.: rustls and rustls-no-provider\"\n            features: \"--features rustls,rustls-no-provider\"\n          - name: \"feat.: default-tls and native-tls\"\n            features: \"--features native-tls\"\n          - name: \"feat.: cookies\"\n            features: \"--features cookies\"\n          - name: \"feat.: blocking\"\n            features: \"--features blocking\"\n          - name: \"feat.: blocking only\"\n            features: \"--no-default-features --features blocking\"\n          - name: \"feat.: gzip\"\n            features: \"--features gzip,stream\"\n          - name: \"feat.: brotli\"\n            features: \"--features brotli,stream\"\n          - name: \"feat.: zstd\"\n            features: \"--features zstd,stream\"\n          - name: \"feat.: deflate\"\n            features: \"--features deflate,stream\"\n          - name: \"feat.: query\"\n            features: \"--features query\"\n          - name: \"feat.: form\"\n            features: \"--features form\"\n          - name: \"feat.: json\"\n            features: \"--features json\"\n          - name: \"feat.: multipart\"\n            features: \"--features multipart\"\n          - name: \"feat.: stream\"\n            features: \"--features stream\"\n          - name: \"feat.: socks/default-tls\"\n            features: \"--features socks\"\n          - name: \"feat.: socks/native-tls\"\n            features: \"--features socks,native-tls\"\n          - name: \"feat.: hickory-dns\"\n            features: \"--features hickory-dns\"\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ matrix.rust || 'stable' }}\n          targets: ${{ matrix.target }}\n\n      - name: Add mingw-w64 to path for i686-gnu\n        run: |\n          echo \"${{ matrix.mingw64_path }}\" >> $GITHUB_PATH\n          echo \"C:\\msys64\\usr\\bin\" >> $GITHUB_PATH\n        if: matrix.mingw64_path\n        shell: bash\n\n      - name: Install x86_64 Clang & NASM\n        if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }}\n        run: pacman.exe -Sy --noconfirm mingw-w64-x86_64-clang mingw-w64-x86_64-nasm\n        shell: bash\n\n      - name: Add libclang to the environment for windows x86_64-gnu\n        run: echo \"LIBCLANG_PATH=C:\\msys64\\mingw64\\bin\" >> $env:GITHUB_ENV\n        if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }}\n        shell: bash\n\n      - name: Update gcc\n        if: matrix.package_name\n        run: pacman.exe -Sy --noconfirm ${{ matrix.package_name }}\n\n      - name: Create Cargo.lock\n        run: cargo update\n\n      - uses: Swatinem/rust-cache@v2\n\n      - uses: taiki-e/install-action@v2\n        with:\n          tool: cargo-nextest\n\n      - name: Run tests\n        run: |\n          set -euxo pipefail\n          cargo nextest run --locked --workspace ${{ matrix.features }} ${{ matrix.test-features }}\n          cargo test --locked --workspace --doc ${{ matrix.features }} ${{ matrix.test-features }}\n        shell: bash\n\n  features:\n    name: features\n    needs: [style]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n\n      - name: Install cargo-hack\n        uses: taiki-e/install-action@cargo-hack\n\n      - uses: Swatinem/rust-cache@v2\n\n      - name: check --feature-powerset\n        run: cargo hack --no-dev-deps check --feature-powerset --depth 2 --skip http3,__tls,__rustls,__rustls-aws-lc-rs,native-tls-vendored,trust-dns\n        env:\n          RUSTFLAGS: \"-D dead_code -D unused_imports\"\n\n  unstable:\n    name: \"unstable features\"\n    needs: [style]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: 'stable'\n\n      - name: Check\n        run: cargo test --features http3,stream\n        env:\n          RUSTFLAGS: --cfg reqwest_unstable\n          RUSTDOCFLAGS: --cfg reqwest_unstable\n\n  docs:\n    name: Docs\n    needs: [test]\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@stable\n\n      - name: Check documentation\n        env:\n          RUSTDOCFLAGS: --cfg reqwest_unstable -D warnings\n        run: cargo doc --no-deps --document-private-items --all-features\n\n  # Separate build job for nightly because of the missing feature for allowed failures at\n  # job level. See `jobs.build.strategy.matrix`.\n  nightly:\n    name: linux / nightly\n    needs: [style]\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@nightly\n\n      - name: Check minimal versions\n        env:\n          RUSTFLAGS: --cfg reqwest_unstable\n        # See https://github.com/rust-lang/rust/issues/113152\n        # We don't force a newer openssl, but a newer one is required for\n        # this CI runner, because of the version of Ubuntu.\n        run: |\n          cargo clean\n          cargo update -Z minimal-versions\n          cargo update -p proc-macro2 --precise 1.0.87\n          cargo update -p aws-lc-rs --precise 1.13.1\n          cargo update -p aws-lc-sys --precise 0.29.0\n          cargo update -p openssl-sys\n          cargo update -p openssl\n          cargo check\n          cargo check --all-features\n\n  msrv_default:\n    name: MSRV Default\n    needs: [style]\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - uses: dtolnay/rust-toolchain@stable\n      - name: Resolve MSRV aware dependencies\n        run: cargo update\n        env:\n          CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback\n\n      # required by rustls-platform-verifier\n      - name: Install rust (1.71.0)\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: 1.71.0\n\n      - uses: Swatinem/rust-cache@v2\n\n      - name: Check\n        run: cargo check\n\n  msrv_oldest:\n    name: MSRV Oldest\n    needs: [style]\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - uses: dtolnay/rust-toolchain@stable\n      - name: Resolve MSRV aware dependencies\n        run: cargo update\n        env:\n          CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback\n\n      - name: Get MSRV package metadata\n        id: metadata\n        run: cargo metadata --no-deps --format-version 1 | jq -r '\"msrv=\" + .packages[0].rust_version' >> $GITHUB_OUTPUT\n\n      - name: Install rust (${{ steps.metadata.outputs.msrv }})\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ steps.metadata.outputs.msrv }}\n\n      - uses: Swatinem/rust-cache@v2\n\n      - name: Check\n        run: cargo check --no-default-features --features=\"http2,charset,native-tls\"\n\n  android:\n    name: Android\n    needs: [style]\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          target: aarch64-linux-android\n\n      - name: Install cargo-ndk\n        run: cargo install cargo-ndk\n\n      - name: Build\n        run: cargo ndk --target aarch64-linux-android build\n\n  wasm:\n    name: WASM\n    needs: [style]\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install rust\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: wasm32-unknown-unknown\n\n      - name: Check\n        run: cargo check --target wasm32-unknown-unknown\n\n      - name: Check cookies\n        run: cargo check --target wasm32-unknown-unknown --features cookies\n\n      - name: Install wasm-pack\n        run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh\n\n      - name: Wasm-pack test firefox\n        run: wasm-pack test --headless --firefox\n\n      - name: Wasm-pack test chrome\n        run: wasm-pack test --headless --chrome\n"
  },
  {
    "path": ".gitignore",
    "content": "target\nCargo.lock\n*.swp\n.idea"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## v0.13.2\n\n- Fix HTTP/2 and native-tls ALPN feature combinations.\n- Fix HTTP/3 to send h3 ALPN.\n- (wasm) fix `RequestBuilder::json()` from override previously set content-type.\n\n## v0.13.1\n\n- Fixes compiling with rustls on Android targets.\n\n# v0.13.0\n\n- **Breaking changes**:\n  - `rustls` is now the default TLS backend, instead of `native-tls`.\n  - `rustls` crypto provider defaults to aws-lc instead of _ring_. (`rustls-no-provider` exists if you want a different crypto provider)\n  - `rustls-tls` has been renamed to `rustls`.\n  - rustls roots features removed, `rustls-platform-verifier` is used by default.\n    - To use different roots, call `tls_certs_only(your_roots)`.\n  - `native-tls` now includes ALPN. To disable, use `native-tls-no-alpn`.\n  - `query` and `form` are now crate features, disabled by default.\n  - Long-deprecated methods and crate features have been removed (such as `trust-dns`, which was renamed `hickory-dns` a while ago).\n- Many TLS-related methods renamed to improve autocompletion and discovery, but previous name left in place with a \"soft\" deprecation. (just documented, no warnings)\n  - For example, prefer `tls_backend_rustls()` over `use_rustls_tls()`.\n\n\n## v0.12.28\n\n- Fix compiling on Windows if TLS and SOCKS features are not enabled.\n\n## v0.12.27\n\n- Add `ClientBuilder::windows_named_pipe(name)` option that will force all requests over that Windows Named Piper.\n\n## v0.12.26\n\n- Fix sending `Accept-Encoding` header only with values configured with reqwest, regardless of underlying tower-http config.\n\n## v0.12.25\n\n- Add `Error::is_upgrade()` to determine if the error was from an HTTP upgrade.\n- Fix sending `Proxy-Authorization` if only username is configured.\n- Fix sending `Proxy-Authorization` to HTTPS proxies when the target is HTTP.\n- Refactor internal decompression handling to use tower-http.\n\n## v0.12.24\n\n- Refactor cookie handling to an internal middleware.\n- Refactor internal random generator.\n- Refactor base64 encoding to reduce a copy.\n- Documentation updates.\n\n## v0.12.23\n\n- Add `ClientBuilder::unix_socket(path)` option that will force all requests over that Unix Domain Socket.\n- Add `ClientBuilder::retry(policy)` and `reqwest::retry::Builder` to configure automatic retries.\n- Add `ClientBuilder::dns_resolver2()` with more ergonomic argument bounds, allowing more resolver implementations.\n- Add `http3_*` options to `blocking::ClientBuilder`.\n- Fix default TCP timeout values to enabled and faster.\n- Fix SOCKS proxies to default to port 1080\n- (wasm) Add cache methods to `RequestBuilder`.\n\n## v0.12.22\n\n- Fix socks proxies when resolving IPv6 destinations.\n\n## v0.12.21\n\n- Fix socks proxy to use `socks4a://` instead of `socks4h://`.\n- Fix `Error::is_timeout()` to check for hyper and IO timeouts too.\n- Fix request `Error` to again include URLs when possible.\n- Fix socks connect error to include more context.\n- (wasm) implement `Default` for `Body`.\n\n## v0.12.20\n\n- Add `ClientBuilder::tcp_user_timeout(Duration)` option to set `TCP_USER_TIMEOUT`.\n- Fix proxy headers only using the first matched proxy.\n- (wasm) Fix re-adding `Error::is_status()`.\n\n## v0.12.19\n\n- Fix redirect that changes the method to GET should remove payload headers.\n- Fix redirect to only check the next scheme if the policy action is to follow.\n- (wasm) Fix compilation error if `cookies` feature is enabled (by the way, it's a noop feature in wasm).\n\n## v0.12.18\n\n- Fix compilation when `socks` enabled without TLS.\n\n## v0.12.17\n\n- Fix compilation on macOS.\n\n## v0.12.16\n\n- Add `ClientBuilder::http3_congestion_bbr()` to enable BBR congestion control.\n- Add `ClientBuilder::http3_send_grease()` to configure whether to send use QUIC grease.\n- Add `ClientBuilder::http3_max_field_section_size()` to configure the maximum response headers.\n- Add `ClientBuilder::tcp_keepalive_interval()` to configure TCP probe interval.\n- Add `ClientBuilder::tcp_keepalive_retries()` to configure TCP probe count.\n- Add `Proxy::headers()` to add extra headers that should be sent to a proxy.\n- Fix `redirect::Policy::limit()` which had an off-by-1 error, allowing 1 more redirect than specified.\n- Fix HTTP/3 to support streaming request bodies.\n- (wasm) Fix null bodies when calling `Response::bytes_stream()`.\n\n## v0.12.15\n\n- Fix Windows to support both `ProxyOverride` and `NO_PROXY`.\n- Fix http3 to support streaming response bodies.\n- Fix http3 dependency from public API misuse.\n\n## v0.12.14\n\n- Fix missing `fetch_mode_no_cors()`, marking as deprecated when not on WASM.\n\n## v0.12.13\n\n- Add `Form::into_reader()` for blocking `multipart` forms.\n- Add `Form::into_stream()` for async `multipart` forms.\n- Add support for SOCKS4a proxies.\n- Fix decoding responses with multiple zstd frames.\n- Fix `RequestBuilder::form()` from overwriting a previously set `Content-Type` header, like the other builder methods.\n- Fix cloning of request timeout in `blocking::Request`.\n- Fix http3 synchronization of connection creation, reducing unneccesary extra connections.\n- Fix Windows system proxy to use `ProxyOverride` as a `NO_PROXY` value.\n- Fix blocking read to correctly reserve and zero read buffer.\n- (wasm) Add support for request timeouts.\n- (wasm) Fix `Error::is_timeout()` to return true when from a request timeout.\n\n## v0.12.12\n\n- (wasm) Fix compilation by not compiler `tokio/time` on WASM.\n\n## v0.12.11\n\n- Fix decompression returning an error when HTTP/2 ends with an empty data frame.\n\n## v0.12.10\n\n- Add `ClientBuilder::connector_layer()` to allow customizing the connector stack.\n- Add `ClientBuilder::http2_max_header_list_size()` option.\n- Fix propagating body size hint (`content-length`) information when wrapping bodies.\n- Fix decompression of chunked bodies so the connections can be reused more often.\n\n## v0.12.9\n\n- Add `tls::CertificateRevocationLists` support.\n- Add crate features to enable webpki roots without selecting a rustls provider.\n- Fix `connection_verbose()` to output read logs.\n- Fix `multipart::Part::file()` to automatically include content-length.\n- Fix proxy to internally no longer cache system proxy settings.\n\n## v0.12.8\n\n- Add support for SOCKS4 proxies.\n- Add `multipart::Form::file()` method for adding files easily.\n- Add `Body::wrap()` to wrap any `http_body::Body` type.\n- Fix the pool configuration to use a timer to remove expired connections.\n\n\n## v0.12.7\n\n- Revert adding `impl Service<http::Request<_>>` for `Client`.\n\n## v0.12.6\n\n- Add support for `danger_accept_invalid_hostnames` for `rustls`.\n- Add `impl Service<http::Request<Body>>` for `Client` and `&'_ Client`.\n- Add support for `!Sync` bodies in `Body::wrap_stream()`.\n- Enable happy eyeballs when `hickory-dns` is used.\n- Fix `Proxy` so that `HTTP(S)_PROXY` values take precedence over `ALL_PROXY`.\n- Fix `blocking::RequestBuilder::header()` from unsetting `sensitive` on passed header values.\n\n## v0.12.5\n\n- Add `blocking::ClientBuilder::dns_resolver()` method to change DNS resolver in blocking client.\n- Add `http3` feature back, still requiring `reqwest_unstable`.\n- Add `rustls-tls-no-provider` Cargo feature to use rustls without a crypto provider.\n- Fix `Accept-Encoding` header combinations.\n- Fix http3 resolving IPv6 addresses.\n- Internal: upgrade to rustls 0.23.\n\n## v0.12.4\n\n- Add `zstd` support, enabled with `zstd` Cargo feature.\n- Add `ClientBuilder::read_timeout(Duration)`, which applies the duration for each read operation. The timeout resets after a successful read.\n\n## v0.12.3\n\n- Add `FromStr` for `dns::Name`.\n- Add `ClientBuilder::built_in_webpki_certs(bool)` to enable them separately.\n- Add `ClientBuilder::built_in_native_certs(bool)` to enable them separately.\n- Fix sending `content-length: 0` for GET requests.\n- Fix response body `content_length()` to return value when timeout is configured.\n- Fix `ClientBuilder::resolve()` to use lowercase domain names.\n\n## v0.12.2\n\n- Fix missing ALPN when connecting to socks5 proxy with rustls.\n- Fix TLS version limits with rustls.\n- Fix not detected ALPN h2 from server with native-tls.\n\n## v0.12.1\n\n- Fix `ClientBuilder::interface()` when no TLS is enabled.\n- Fix `TlsInfo::peer_certificate()` being truncated with rustls.\n- Fix panic if `http2` feature disabled but TLS negotiated h2 in ALPN.\n- Fix `Display` for `Error` to not include its source error.\n\n# v0.12.0\n\n- Upgrade to `hyper`, `http`, and `http-body` v1.\n- Add better support for converting to and from `http::Request` and `http::Response`.\n- Add `http2` optional cargo feature, default on.\n- Add `charset` optional cargo feature, default on.\n- Add `macos-system-configuration` cargo feature, default on.\n- Change all optional dependencies to no longer be exposed as implicit features.\n- Add `ClientBuilder::interface(str)` to specify the local interface to bind to.\n- Experimental: disables the `http3` feature temporarily.\n\n## v0.11.27\n\n- Add `hickory-dns` feature, deprecating `trust-dns`.\n- (wasm) Fix `Form::text()` to not set octet-stream for plain text fields.\n\n## v0.11.26\n\n- Revert `system-configuration` upgrade, which broke MSRV on macOS.\n\n## v0.11.25\n\n- Fix `Certificate::from_pem_bundle()` parsing.\n- Fix Apple linker errors from detecting system proxies.\n\n## v0.11.24\n\n- Add `Certificate::from_pem_bundle()` to add a bundle.\n- Add `http3_prior_knowledge()` to blocking client builder.\n- Remove `Sync` bounds requirement for `Body::wrap_stream()`.\n- Fix HTTP/2 to retry `REFUSED_STREAM` requests.\n- Fix instances of converting `Url` to `Uri` that could panic.\n\n## v0.11.23\n\n- Add `Proxy::custom_http_auth(val)` for setting the raw `Proxy-Authorization` header when connecting to proxies.\n- Fix redirect to reject locations that are not `http://` or `https://`.\n- Fix setting `nodelay` when TLS is enabled but URL is HTTP.\n- (wasm) Add `ClientBuilder::user_agent(val)`.\n- (wasm) add `multipart::Form::headers(headers)`.\n\n## v0.11.22\n\n- Fix compilation on Windows when `trust-dns` is enabled.\n\n## v0.11.21\n\n- Add automatically detecting macOS proxy settings.\n- Add `ClientBuilder::tls_info(bool)`, which will put `tls::TlsInfo` into the response extensions.\n- Fix trust-dns resolver from possible hangs.\n- Fix connect timeout to be split among multiple IP addresses.\n\n## v0.11.20\n\n- Fix `deflate` decompression back to using zlib, as outlined in the spec.\n\n## v0.11.19\n\n- Add `ClientBuilder::http1_ignore_invalid_headers_in_responses()` option.\n- Add `ClientBuilder::http1_allow_spaces_after_header_name_in_responses()` option.\n- Add support for `ALL_PROXY` environment variable.\n- Add support for `use_preconfigured_tls` when combined with HTTP/3.\n- Fix `deflate` decompression from using the zlib decoder.\n- Fix `Response::{text, text_with_charset}()` to strip BOM characters.\n- Fix a panic when HTTP/3 is used if UDP isn't able to connect.\n- Fix some dependencies for HTTP/3.\n- Increase MSRV to 1.63.\n\n## v0.11.18\n\n- Fix `RequestBuilder::json()` method from overriding a previously set `content-type` header. An existing value will be left in place.\n- Upgrade internal dependencies for rustls and compression.\n\n## v0.11.17\n\n- Upgrade internal dependencies of Experimental HTTP/3 to use quinn v0.9\n- (wasm) Fix blob url support\n\n## v0.11.16\n\n- Chore: set MSRV in `Cargo.toml`.\n- Docs: fix build on docs.rs\n\n## v0.11.15\n\n- Add `RequestBuilder` methods to split and reconstruct from its parts.\n- Add experimental HTTP/3 support.\n- Fix `connection_verbose` to log `write_vectored` calls.\n- (wasm) Make requests actually cancel if the future is dropped.\n\n## v0.11.14\n\n- Adds `Proxy::no_proxy(url)` that works like the NO_PROXY environment variable.\n- Adds `multipart::Part::headers(headers)` method to add custom headers.\n- (wasm) Add `Response::bytes_stream()`.\n- Perf: several internal optimizations reducing copies and memory allocations.\n\n## v0.11.13\n\n- Add `ClientBuilder::dns_resolver()` option for custom DNS resolvers.\n- Add `ClientBuilder::tls_sni(bool)` option to enable or disable TLS Server Name Indication.\n- Add `Identity::from_pkcs8_pem()` constructor when using `native-tls`.\n- Fix `redirect::Policy::limited(0)` from following any redirects.\n\n## v0.11.12\n\n- Add `ClientBuilder::resolve_to_addrs()` which allows a slice of IP addresses to be specified for a single host.\n- Add `Response::upgrade()` to await whether the server agrees to an HTTP upgrade.\n\n## v0.11.11\n\n- Add HTTP/2 keep-alive configuration methods on `ClientBuilder`.\n- Add `ClientBuilder::http1_allow_obsolete_multiline_headers_in_responses()`.\n- Add `impl Service<Request>` for `Client` and `&'_ Client`.\n- (wasm) Add `RequestBuilder::basic_auth()`.\n- Fix `RequestBuilder::header` to not override `sensitive` if user explicitly set on a `HeaderValue`.\n- Fix rustls parsing of elliptic curve private keys.\n- Fix Proxy URL parsing of some invalid targets.\n\n## v0.11.10\n\n- Add `Error::url()` to access the URL of an error.\n- Add `Response::extensions()` to access the `http::Extensions` of a response.\n- Fix `rustls-native-certs` to log an error instead of panicking when loading an invalid system certificate.\n- Fix passing Basic Authorization header to proxies.\n\n## v0.11.9\n\n- Add `ClientBuilder::http09_responses(bool)` option to allow receiving HTTP/0.9 responses.\n- Fix HTTP/2 to retry requests interrupted by an HTTP/2 graceful shutdown.\n- Fix proxy loading from environment variables to ignore empty values.\n\n## v0.11.8\n\n- Update internal webpki-roots dependency.\n\n## v0.11.7\n\n- Add `blocking::ClientBuilder::resolve()` option, matching the async builder.\n- Implement `From<tokio::fs::File>` for `Body`.\n- Fix `blocking` request-scoped timeout applying to bodies as well.\n- (wasm) Fix request bodies using multipart vs formdata.\n- Update internal `rustls` to 0.20.\n\n## v0.11.6\n\n- (wasm) Fix request bodies more.\n\n## v0.11.5\n\n- Add `ClientBuilder::http1_only()` method.\n- Add `tls::Version` type, and `ClientBuilder::min_tls_version()` and `ClientBuilder::max_tls_version()` methods.\n- Implement `TryFrom<Request>` for `http::Request`.\n- Implement `Clone` for `Identity`.\n- Fix `NO_PROXY`environment variable parsing to more closely match curl's. Comma-separated entries are now trimmed for whitespace, and `*` is allowed to match everything.\n- Fix redirection to respect `https_only` option.\n- (wasm) Add `Body::as_bytes()` method.\n- (wasm) Fix sometimes wrong conversation of bytes into a `JsValue`.\n- (wasm) Avoid dependency on serde-serialize feature.\n\n## v0.11.4\n\n- Add `ClientBuilder::resolve()` option to override DNS resolution for specific domains.\n- Add `native-tls-alpn` Cargo feature to use ALPN with the native-tls backend.\n- Add `ClientBuilder::deflate()` option and `deflate` Cargo feature to support decoding response bodies using deflate.\n- Add `RequestBuilder::version()` to allow setting the HTTP version of a request.\n- Fix allowing \"invalid\" certificates with the `rustls-tls` backend, when the server uses TLS v1.2 or v1.3.\n- (wasm) Add `try_clone` to `Request` and `RequestBuilder`\n\n## v0.11.3\n\n- Add `impl From<hyper::Body> for reqwest::Body`.\n- (wasm) Add credentials mode methods to `RequestBuilder`.\n\n## v0.11.2\n\n- Add `CookieStore` trait to customize the type that stores and retrieves cookies for a session.\n- Add `cookie::Jar` as a default `CookieStore`, easing creating some session cookies before creating the `Client`.\n- Add `ClientBuilder::http2_adaptive_window()` option to configure an adaptive HTTP2 flow control behavior.\n- Add `ClientBuilder::http2_max_frame_size()` option to adjust the maximum HTTP2 frame size that can be received.\n- Implement `IntoUrl` for `String`, making it more convenient to create requests with `format!`.\n\n## v0.11.1\n\n- Add `ClientBuilder::tls_built_in_root_certs()` option to disable built-in root certificates.\n- Fix `rustls-tls` glue to more often support ALPN to upgrade to HTTP/2.\n- Fix proxy parsing to assume `http://` if no scheme is found.\n- Fix connection pool idle reaping by enabling hyper's `runtime` feature.\n- (wasm) Add `Request::new()` constructor.\n\n# v0.11.0\n\n- Change `multipart` to be an optional cargo feature.\n- Remove deprecated methods.\n\n- Update to Tokio v1.0.\n- Update to Bytes v1.0.\n- Update to hyper v0.14.\n\n## v0.10.10\n\n- Add `tcp_keepalive` option to `blocking::ClientBuilder`.\n- Add `multipart::Part::stream_with_length` constructor, to create a streaming part with a known length.\n- Add `ClientBuilder::https_only` option, to allow requiring URLs to be `https`.\n- Change default `tcp_keepalive` value to be disabled.\n\n## v0.10.9\n\n- Add `rustls-tls-native-roots`, `rustls-tls-webpki-roots`, and `rustls-tls-manual-roots` Cargo features, to configure which certificate roots to use with rustls.\n- Add `ClientBuilder::tcp_keepalive()` method to enable TCP keepalive.\n- Add `ClientBuilder::http1_writev()` method to force enable or disable vectored writes.\n- Add `Error::is_connect()` method to identify if the error is related to connection-establishment.\n- Add `blocking::ClientBuilder::brotli()` method.\n- Windows: Update default protocol to HTTP for HTTPS system proxies, when a protocol is not specified.\n- (wasm) Add support for Cloudflare workers runtime.\n- (wasm) Add `ClientBuilder::default_headers()` method.\n- (wasm) Add `RequestBuilder::build()` method.\n\n## v0.10.8\n\n- Add `must_use` to `RequestBuilder` and `ClientBuilder`.\n- Fix Windows system proxy detection of Fiddler proxies.\n- (wasm) Add `headers` method to `RequestBuilder`.\n- (wasm) Add `execute` method to `Client`.\n- (wasm) Add `TryFrom<http::Request>` for `Request`.\n- (wasm) Fix checking for global `window` to work in non-browser environments.\n- (wasm) Fix sending of an empty body when not required.\n\n## v0.10.7\n\n- Add `NO_PROXY` environment variable support.\n- Add more `Error::{is_request, is_body, is_decode}` getters.\n- Add conversion of `reqwest::ClientBuilder` to `reqwest::blocking::ClientBuilder`.\n- Add `headers_mut()` to `reqwest::blocking::Response`.\n- (wasm) Add `form()`, `query()`, `multipart` and `bearer_auth()` to `RequestBuilder`.\n\n## v0.10.6\n\n- Changed handling of URLs that don't have `http:` or `https:` schemes, returning an error instead.\n- Fixed a potential hyper-rustls feature conflict.\n\n## v0.10.5\n\n- Add `ClientBuilder::pool_idle_timeout` option.\n- Add `ClientBuilder::pool_max_idle_per_host` option, deprecate `max_idle_per_host`.\n- Add `Response::content_length` for WASM target.\n- Enable TCP_NODELAY by default.\n- Implement `TryFrom<http::Request>` for `blocking::Request`.\n- Implement `TryFrom<http::Request>` for `Request`.\n  - Removes `From<http::Request>` for `Request`.\n  - This is technically a breaking change, but was a mistake. It was not valid to convert from an `http::Request` to a `reqwest::Request` in an infallible fashion. It would panic if the conversion was not possible. Instead, the implementation has been changed to `TryFrom` to indicate it could fail.\n\n## v0.10.4\n\n- Add `trust-dns` optional feature to change DNS resolver.\n- Add `bytes()` method to `reqwest::blocking::Response`.\n- Add `buffer()` method to `reqwest::blocking::Body`.\n- Implement `From<http::Request>` for `reqwest::Request`.\n\n## v0.10.3\n\n- Upgrade internal `rustls` version.\n\n## v0.10.2\n\n- Add Brotli support, enabled with the optional `brotli` feature.\n- Add `Client::use_preconfigured_tls(tls_connector)` allowing manual configuration of TLS options.\n- Implement `Default` for blocking `Client`, `ClientBuilder`, and `multipart::Form`.\n- (wasm) Add `Response::error_for_status()` method.\n- (wasm) Add `Response::json()` method.\n- (wasm) Implement `Default` for `Client` and `ClientBuilder`.\n\n## v0.10.1\n\n- Add `socks` optional feature to support SOCKS5 proxies.\n- Add `RequestBuilder::timeout()` to configure a timeout for a single request, instead of using the client's timeout.\n- Add `ClientBuilder::connection_verbose()` option to enable verbose IO logs.\n- (wasm) Add `RequestBuilder::fetch_mode_no_cors()` option.\n- (wasm) Add `Response::url()` getter method.\n\n# v0.10.0\n\n- Add `std::future::Future` support.\n- Add `wasm32-unknown-unknown` support (with fewer features).\n- Add ability to pass async `Response` as the `body` of another `Request`.\n- Add `Body::as_bytes()` method.\n- Add `Response::bytes_stream()` method to get body as an `impl Stream`.\n- Add `Request::try_clone()` method.\n\n- Change default `Client` API to async. The previous blocking client API is available at `reqwest::blocking`.\n- Change to no longer send a default `User-Agent` header. Add one via `ClientBuilder::user_agent()`.\n- Change to enable system/environment proxy detection by default.\n- Change `default-tls` feature to only include `ClientBuilder` options that both `native-tls` and `rustls` support.\n- Change default feature set to reduce unnecessary dependencies. Most features are disabled by default:\n  - `blocking`: The `reqwest::blocking` (synchronous) client API.\n  - `cookies`: Cookie store support.\n  - `gzip`: Automatic response body decompression.\n  - `json`: Request and response JSON body methods.\n  - `stream`: `futures::Stream` support.\n- Change `Error` internal design, removing several `Error::is_*` inspector methods.\n- Change Redirect API:\n  - Renamed types to be part of the `redirect` module (for example, `reqwest::RedirectPolicy` is now `reqwest::redirect::Policy`).\n  - Removed `loop_detected` and `too_many_redirect` methods from `redirect::Attempt`, replaced with a generic `error` method.\n  - The default policy no longer specifically looks for redirect loops (but they should be caught by the maximum limit).\n\n- Fix checking `HTTP_PROXY` environment variable if it the environment is from a CGI script.\n- Fix removal of username/password of parsed proxy URL.\n\n- Update `url` to v2.0.\n- Update `hyper` to v0.13.\n- Update `http` to v0.2.\n\n\n## v0.9.19\n\n- Add `ClientBuilder::use_sys_proxy()` to enable automatic detect of HTTP proxies configured on the system.\n- Add `ClientBuilder::no_proxy()` to disable system proxies. This is the default for 0.9, but will change to detecting system proxies by default in 0.10.\n- Add support for streaming request bodies in the async client.\n- Add `async::Response::text()` that returns a `Future` of the full body decoded to a `String`.\n- Add `Clone` for `Certificate`.\n\n## v0.9.18\n\n- Fix `Cookie` headers to no longer send as percent-encoded (instead, exactly as sent by the server).\n\n## v0.9.17\n\n- Fix `Cookie` headers to not include attributes from the `Set-Cookie` (like `HttpOnly`, `Secure`, etc.)\n\n## v0.9.16\n\n- Add `Response::text_with_charset()` to allow setting the default charset to decode.\n- Add `Error::source()` implementation.\n- Add `async::ClientBuilder::timeout()` option, will timeout the connect, request, and response body futures.\n- Fix gzip + chunked transfer encoding issue preventing connection reuse.\n- Fix `RequestBuilder::query()` to not add just `\"?\"` if the encoded query is empty.\n- Fix including new cookie headers when response is a redirect.\n\n## v0.9.15\n\n- Fix sending of \"appended\" request headers.\n\n## v0.9.14\n\n- Add optional support for SOCKS5 proxies, by enabling the `socks5` cargo feature.\n- Add Cookie Store support to `Client`, automatically handling cookies for a session.\n- Add `ClientBuilder::cookie_store(enable: bool)` method to enable a cookie store that persists across requests.\n- Add `Response::cookies()` accessor that allows iterating over response cookies.\n- Fix `Proxy` to check the URL for a username and password.\n\n## v0.9.13\n\n### Fixes\n\n- Fix panic on some invalid `Location` headers during redirects (error is logged and redirect response is returned instead).\n- Fix instance when server notices streaming request body is complete before reqwest does.\n\n## v0.9.12\n\n### Features\n\n- Add `ClientBuilder::tcp_nodelay()` to allow disabling Nagle's algorithm.\n- Add `ClientBuilder::max_idle_per_host()` to allow reducing the number of idle pooled connections.\n- Add `RequestBuilder::bearer_auth()` method to async builder.\n\n### Fixes\n\n- Fix capitalization error in async `RequestBuilder::basic_auth()`.\n- Fix ALPN causing issues when using a Proxy.\n\n## v0.9.11\n\n### Features\n\n- Add `multipart::Form::percent_encode_noop()` to allow for servers which don't support percent encoding of parameters.\n- Add `ClientBuilder::http1_title_case_headers()` to force request headers to use Title-Case.\n- Add `ClientBuilder::connect_timeout()` to allow setting only a connect timeout.\n\n## v0.9.10\n\n### Features\n\n- Add `ClientBuilder::local_address()` to bind to a local IP address.\n- Add `Response::error_for_status_ref()` to return an `Error` while borrowing a `Response`.\n\n### Fixes\n\n- Fix `Identity::from_pem` with `rustls-tls` backend when using RSA private keys.\n\n## v0.9.9\n\n### Features\n\n- Add `ClientBuilder::h2_prior_knowledge()` option to force HTTP2.\n- Add `Response::content_length()` to get the content-length of a response.\n- Enable ALPN h2 with the rustls-tls backend.\n\n## v0.9.8\n\n### Fixes\n\n- Revert default DNS resolver to `getaddrinfo` in a threadpool. There is now a `trust-dns` optional feature to enable the Trust-DNS resolver.\n- Detect `Certificate` and `Identity` errors at construction time.\n\n## v0.9.7\n\n### Fixes\n\n- Fix DNS resolver on Android (reverted back to `getaddrinfo`).\n- Fix sending unicode `filename`s in `multipart/form-data` requests.\n\n## v0.9.6\n\n### Features\n\n- Add `Proxy::basic_auth` method to support proxy authorization.\n- Add `rustls-tls` optional feature to use rustls instead of native-tls.\n- Add `try_clone` method to `Request` and `RequestBuilder`.\n- Add `reqwest::async::multipart` support, similar to the synchronous API.\n- Adds `default-tls-vendored` optional feature to vendor OpenSSL.\n\n### Fixes\n\n- Fix panic from top-level `reqwest::get` if client builder fails to build.\n- Removed timeout waiting for `reqwest::Client` runtime to startup.\n- Fix `RequestBuilder::headers` to properly append extra headers of the same name.\n\n\n### Performance\n\n- Replaced DNS threadpool using `getaddrinfo` with a non-blocking DNS resolver.\n\n## v0.9.5\n\n### Features\n\n- Adds `Response::remote_addr()` method to check the address of the connection used.\n- Adds `default-tls` crate feature, enabled by default, which allows users to *disable* TLS.\n\n## v0.9.4\n\n### Features\n\n- Adds `percent_encoding_path_segment` and `percent_encoding_attr_char` configuration to `multipart::Form`.\n\n### Fixes\n\n- Reverts `multipart::Form` default percent encoding format to `path-segment`.\n\n## v0.9.3\n\n### Features\n\n- Adds `multipart::Part::bytes()` to create a part of raw bytes.\n- Adds constructors for `Response` to help with testing.\n\n### Fixes\n\n- Properly percent-encoding more illegal characters in multipart filenames.\n- Ensure timed out requests cancel the associated async task.\n\n## v0.9.2\n\n### Fixes\n\n- Fix panic when `Location` header has UTF-8 characters.\n\n## v0.9.1\n\n### Fixes\n\n- Fix large request bodies failing because of improper handling of backpressure.\n- Remove body-related headers when redirect changes a `POST` into a `GET`.\n- Reduce memory size of `Response` and `Error` significantly.\n\n# v0.9.0\n\n### Features\n\n- Upgrade to `tokio` 0.1.\n- Upgrade to `hyper` 0.12.\n- Upgrade to `native-tls` 0.2.\n- Add `ClientBuilder::danger_accept_invalid_certs(bool)` to disable\n  certificate verification.\n- Add `RequestBuilder::bearer_auth(token)` to ease sending bearer tokens.\n- Add `headers()` and `headers_mut()` to `multipart::Part` to allow sending\n  extra headers for a specific part.\n- Moved `request::unstable::async` to `reqwest::async`.\n\n### Fixes\n\n- Fix panicking when passing a `Url` with a `file://` scheme. Instead, an\n  `Error` is returned.\n\n### Breaking Changes\n\n- Changed `ClientBuilder::danger_disable_hostname_verification()`\n  to `ClientBuilder::danger_accept_invalid_hostnames(bool)`.\n- Changed `ClientBuilder` to be a by-value builder instead of by-ref.\n\n  For single chains of method calls, this shouldn't affect you. For code that\n  conditionally uses the builder, this kind of change is needed:\n\n  ```rust\n  // Old\n  let mut builder = ClientBuilder::new();\n  if some_val {\n      builder.gzip(false);\n  }\n  let client = builder.build()?;\n\n  // New\n  let mut builder = ClientBuilder::new();\n  if some_val {\n      builder = builder.gzip(false);\n  }\n  let client = builder.build()?;\n  ```\n- Changed `RequestBuilder` to be a by-value builder of by-ref.\n\n  See the previous note about `ClientBuilder` for affected code and\n  how to change it.\n- Removed the `unstable` cargo-feature, and moved `reqwest::unstable::async`\n  to `reqwest::async`.\n- Changed `multipart::Part::mime()` to `mime_str()`.\n\n  ```rust\n  // Old\n  let part = multipart::Part::file(path)?\n      .mime(mime::TEXT_PLAIN);\n\n  // New\n  let part = multipart::Part::file(path)?\n      .mime_str(\"text/plain\")?;\n  ```\n- The upgrade to `hyper` 0.12 means a temporary removal of the typed headers.\n\n  The `RequestBuilder` has simple methods to set headers using strings, which\n  can work in most places.\n\n  ```rust\n  // Old\n  client\n      .get(\"https://hyper.rs\")\n      .header(UserAgent::new(\"hallo\"))\n      .send()?;\n\n  // New\n  client\n      .get(\"https://hyper.rs\")\n      .header(\"user-agent\", \"hallo\")\n      .send()?;\n  ```\n\n  To ease the transition, there is a `hyper-011` cargo-feature that can be\n  enabled.\n\n  ```toml\n  [dependencies]\n  reqwest = { version = \"0.9\", features = [\"hyper-011\"] }\n  ```\n\n  And then usage:\n\n  ```rust\n  client\n      .get(\"https://hyper.rs\")\n      .header_011(reqwest::hyper_011::header::UserAgent::new(\"hallo\"))\n      .send()?;\n  ```\n\n\n## v0.8.8\n\n- Fix docs.rs/reqwest build.\n\n## v0.8.7\n\n### Fixes\n\n- Send an extra CRLF at the end of multipart requests, since some servers expect it.\n- Removed internal dependency on `tokio-proto`, which removed unsafe `small-vec`\n  dependency.\n\n## v0.8.6\n\n### Features\n\n- Add `RedirectAttempt::status` to check status code that triggered redirect.\n- Add `RedirectPolicy::redirect` method publicly, to allow composing policies.\n\n## v0.8.5\n\n### Features\n\n- Try to auto-detect encoding in `Response::text()`.\n- Add `Certificate::from_pem` to load PEM encoded client certificates.\n- Allow unsized types in `query`, `form`, and `json`.\n- Add `unstable::async::RequestBuilder::query`, mirroring the stable builder method.\n\n## v0.8.4\n\n### Features\n\n- Add `RequestBuilder::query` to easily adjust query parameters of requests.\n\n## v0.8.3\n\n### Features\n\n- Upgrades internal log crate usage to v0.4\n\n## v0.8.2\n\n### Fixes\n\n- Enable hyper's `no_proto` config, fixing several bugs in hyper.\n\n## v0.8.1\n\n### Features\n\n- Add `ClientBuilder::default_headers` to set headers used for every request.\n- Add `async::ClientBuilder::dns_threads` to set number of threads use for DNS.\n- Add `Response::text` as shortcut to read the full body into a `String`.\n- Add `Response::copy_to` as shortcut for `std::io::copy`.\n\n# v0.8.0\n\n### Features\n\n- Client TLS Certificates (#43)\n- GZIP decoding has been added to the **async** Client (#161)\n- `ClientBuilder` and `RequestBuilder` hold their errors till consumed (#189)\n- `async::Response::body()` now returns a reference to the body instead of consuming the `Response`\n- A default timeout for `reqwest::Client` is used set to 30 seconds (#181)\n\n### Breaking Changes\n\n- `Client::new` no longer returns a `Result`.\n\n  To handle any panics that come from `Client::new`, the builder can be used instead.\n- `ClientBuilder` and `RequestBuilder` hold their errors till consumed (#189).\n\n  This means a bunch of `?` will be going away, but means using the builders will be far easier now. Any error encountered inside the builders will now be returned when the builder is consumed.\n\n  To get errors back immediately, the `Request` type can be used directly, by building pieces separately and calling setters.\n- `async::Response::body()` now returns a reference to the body instead of consuming the `Response`.\n- A default timeout for `reqwest::Client` is used set to 30 seconds (#181)\n\n  For uses where the timeout is too short, it can be changed on the `ClientBuilder`, using the `timeout` method. Passing `None` will disable the timeout, reverting to the pre-0.8 behavior.\n\n## v0.7.3\n\n### Features\n\n- `Proxy::custom(fn)` to allow dynamically picking a proxy URL\n\n### Fixes\n\n- fix occasional panic when program exits while `Client` or `Response` are dropping.\n\n## v0.7.2\n\n### Fixes\n\n- fix a panic when redirecting and a `Authorization<Basic>` header was added (https://github.com/seanmonstar/reqwest/commit/cf246d072badd9b31b487e7a0b00490e4cc9584f)\n- fix redirects so that a GET will follow 307/308 responses (https://github.com/seanmonstar/reqwest/commit/2d11a4bd7167e1bf3a35b62f5aeb36d5d294e56e)\n\n## v0.7.1\n\n### Fixes\n\n- fix remove accidental `println`s in the sending of a body\n- some documentation improvements\n\n# v0.7.0\n\n### Features\n\n- Proxy support (#30)\n- Self-signed TLS certificates (#97)\n- Disabling TLS hostname validation (#89)\n- A `Request` type that can be used instead of the `RequestBuilder` (#85)\n- Add `Response::error_for_status()` to easily convert 400 and 500 status responses into an `Error`  (#98)\n- Upgrade hyper to 0.11\n  - Synchronous `Client` remains.\n  - Timeouts now affect DNS and socket connection.\n  - Pool much better at evicting sockets when they die.\n  - An `unstable` Cargo feature to enable `reqwest::unstable::async`.\n- A huge docs improvement! \n\n### Fixes\n\n- Publicly exports `RedirectAction` and `RedirectAttempt`\n- `Error::get_ref` returns `Error + Send + Sync`\n\n### Breaking Changes\n\n- hyper has been upgraded to 0.11, so `header`, `StatusCode`, and `Method` have breaking changes.\n- `mime` has been upgraded to 0.3, with a very different API.\n- All configuration methods have been removed from the `Client`, and moved to the `ClientBuilder`.\n- The `HttpVersion` type was completely removed.\n- `Error::cause()` now returns `Error::get_ref().cause()`.\n- All methods on `Client` that start a `RequestBuilder` now return a `Result` immediately, instead of delaying the URL parse error for later.\n- The `RequestBuilder` methods all take `&mut self`, instead of moving the builder, and return `&mut Self`. (This shouldn't actually affect most people who are building a request in a single chain.)\n- `Response::status()` returns a `StatusCode` instead of `&StatusCode`.\n\n## v0.6.2\n\n### Features\n\n- adds `Client::referer(bool)` option to disable setting the `Referer` header during redirects (https://github.com/seanmonstar/reqwest/commit/bafcd7ae6fc232856dd6ddb8bf5b20dbbbfe0bc9)\n\n### Fixes\n\n- fixes filtering sensitive headers during redirects (https://github.com/seanmonstar/reqwest/issues/10)\n- fixes sending of the Referer to an HTTP site when coming from HTTPS, and removes username and fragment explicitly (https://github.com/seanmonstar/reqwest/commit/d8696045b4c6bc4d9e33789cff6a9e1fa75462d7)\n- documentation updates\n\n## v0.6.1\n\n### Features\n\n- adds `Error::get_ref` to get the underlying error that may have occurred. Includes a `'static` bounds, which allows for downcasting (as opposed to `Error::cause`).\n\n# v0.6.0\n\n### Features\n\n- Upgraded to serde `1.0`\n- Added a `url` [method](https://docs.rs/reqwest/0.6.0/reqwest/struct.Error.html#method.url) to `Error`, which returns a possible associated `Url` that occurred with this error.\n- Added `req.basic_auth(user, optional_pass)` [method](https://docs.rs/reqwest/0.6.0/reqwest/struct.RequestBuilder.html#method.basic_auth) to ease using `Basic` authentication.\n\n### Breaking Changes\n\n- The publicly exposed peer dependency serde was upgraded. It is now `serde@1.0`. Mismatched version will give a compiler error that a serde trait is not implemented.\n- `Error` is no longer an `enum`, but an opaque struct. Details about it can be checked with `std::error::Error::cause()`, and methods on `reqwest::Error` include `is_http()`, `is_serialization()`, and `is_redirect()`.\n- `RedirectPolicy::custom` receives different arguments, and returns different values. See the [docs](https://docs.rs/reqwest/0.6.0/reqwest/struct.RedirectPolicy.html#method.custom) for an example.\n\n## v0.5.2\n\n### Fixes\n\n- fix panic with Gzip decoder on an empty body (https://github.com/seanmonstar/reqwest/issues/82)\n\n## v0.5.1\n\n### Features\n\n- add `Clone` implementation for `Client`\n\n# v0.5.0\n\n### Features\n\n- Automatic GZIP decoding: By default, `Client` will try to decode any responses that appear to be gzip encoded (based on headers). This can be disabled via `client.gzip(false)` (https://github.com/seanmonstar/reqwest/commit/ab5e477a123319efd4b17f3666b41b44ec244bee)\n- Specify a timeout for requests using `client.timeout(duration)`. (https://github.com/seanmonstar/reqwest/commit/ec049fefbae7355f6e4ddbbc7ebedcadb30e1e04)\n- Request bodies with a known length can be constructed with `Body::sized()` (https://github.com/seanmonstar/reqwest/commit/82f1877d4b6cba2fac432670ec306160aee5c501)\n- Add `Client.put`, `Client.patch`, and `Client.delete` convenience methods (https://github.com/seanmonstar/reqwest/commit/c37b8aa0338ac4142763d206c6df79856915056d, https://github.com/seanmonstar/reqwest/commit/4d6582d22b23c27927e481a9c8a83ad08cfd1a2a, https://github.com/seanmonstar/reqwest/commit/a3983f3122b2d1495ea36bb5a8fd019a7605ae56)\n- Add `reqwest::mime` (https://github.com/seanmonstar/reqwest/commit/0615c6d65e03ba9cb5364169c9e74f4f2a91554b)\n\n### Breaking Changes\n\nThe only breaking change is a behavioral one, all programs should still compile without modification. The automatic GZIP decoding could interfere in cases where a user was expecting the GZIP bytes, either to save to a file or decode themselves. To restore this functionality, set `client.gzip(false)`. \n\n# v0.4.0\n\n- updated to serde 0.9\n\n# v0.3.0\n\n- updated to hyper 0.10\n\n# v0.2.0\n\n### Features\n- add `Response.json()` method (https://github.com/seanmonstar/reqwest/commit/2d10ecc99e2aaed66616294baaf65380b446e1c6)\n- add `RedirectPolicy` (https://github.com/seanmonstar/reqwest/commit/e92b3e862a1a94c0b4173a7d49a315bc121da31e)\n- set an `Accept: */*` header by default if no `Accept` header is set (https://github.com/seanmonstar/reqwest/commit/559ae8011a2c098f4fe1821ec1d3444a46f4bf5e)\n- add support for 307 and 308 redirects (https://github.com/seanmonstar/reqwest/commit/a54447c1d9c75dab639333265f51a91a43e99c2e)\n- implement `Sync` for `Client`, and `Send` for `RequestBuilder` and `Response` (https://github.com/seanmonstar/reqwest/commit/d18a53b3fcc81c4a60875755c8e95d777a343319)\n- implement `Send` for `Error` (https://github.com/seanmonstar/reqwest/commit/20b161096e67d22c962e69b2656ae9741ac73c25)\n- implement `std::fmt::Debug` for all public types (https://github.com/seanmonstar/reqwest/commit/d624b0ef29020c6085ec94651a990f58ccd684e2)\n\n### Breaking Changes\n- `Error::Serialize` now has a `Box<StdError + Send + Sync>` instead of `Box<StdError>`\n- `RequestBuilder` no longer has an associated lifetime (was `RequestBuilder<'a>`)\n\n# v0.1.0\n\nInitial release: http://seanmonstar.com/post/153221119046/introducing-reqwest\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"reqwest\"\nversion = \"0.13.2\"\ndescription = \"higher level HTTP client library\"\nkeywords = [\"http\", \"request\", \"client\"]\ncategories = [\"web-programming::http-client\", \"wasm\"]\nrepository = \"https://github.com/seanmonstar/reqwest\"\ndocumentation = \"https://docs.rs/reqwest\"\nauthors = [\"Sean McArthur <sean@seanmonstar.com>\"]\nreadme = \"README.md\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.64.0\"\nautotests = true\ninclude = [\n    \"README.md\",\n    \"Cargo.toml\",\n    \"LICENSE-APACHE\",\n    \"LICENSE-MIT\",\n    \"src/**/*.rs\"\n]\n\n[package.metadata.docs.rs]\nall-features = true\nrustdoc-args = [\"--cfg\", \"docsrs\", \"--cfg\", \"reqwest_unstable\"]\ntargets = [\"x86_64-unknown-linux-gnu\", \"wasm32-unknown-unknown\"]\n\n[package.metadata.playground]\nfeatures = [\n    \"blocking\",\n    \"cookies\",\n    \"query\",\n    \"form\",\n    \"json\",\n    \"multipart\",\n]\n\n[features]\ndefault = [\"default-tls\", \"charset\", \"http2\", \"system-proxy\"]\n\ndefault-tls = [\"rustls\"]\n\nhttp2 = [\"dep:h2\", \"hyper/http2\", \"hyper-util/http2\", \"hyper-rustls?/http2\"]\n\nrustls = [\"__rustls-aws-lc-rs\", \"dep:rustls-platform-verifier\", \"__rustls\"]\nrustls-no-provider = [\"dep:rustls-platform-verifier\", \"__rustls\"]\n\nnative-tls = [\"__native-tls\", \"__native-tls-alpn\"]\nnative-tls-no-alpn = [\"__native-tls\"]\nnative-tls-vendored = [\"__native-tls\", \"native-tls-crate?/vendored\", \"__native-tls-alpn\"]\nnative-tls-vendored-no-alpn = [\"__native-tls\", \"native-tls-crate?/vendored\"]\n\nblocking = [\"dep:futures-channel\", \"futures-channel?/sink\", \"dep:futures-util\", \"futures-util?/io\", \"futures-util?/sink\", \"tokio/sync\"]\n\ncharset = [\"dep:encoding_rs\", \"dep:mime\"]\n\ncookies = [\"dep:cookie_crate\", \"dep:cookie_store\"]\n\ngzip = [\"tower-http/decompression-gzip\"]\nbrotli = [\"tower-http/decompression-br\"]\nzstd = [\"tower-http/decompression-zstd\"]\ndeflate = [\"tower-http/decompression-deflate\"]\n\nquery = [\"dep:serde\", \"dep:serde_urlencoded\"]\nform = [\"dep:serde\", \"dep:serde_urlencoded\"]\njson = [\"dep:serde\", \"dep:serde_json\"]\n\nmultipart = [\"dep:mime_guess\", \"dep:futures-util\"]\n\nhickory-dns = [\"dep:hickory-resolver\", \"dep:once_cell\"]\n\nstream = [\"tokio/fs\", \"dep:futures-util\", \"dep:tokio-util\", \"dep:wasm-streams\"]\n\nsocks = []\n\n# Use the system's proxy configuration.\nsystem-proxy = [\"hyper-util/client-proxy-system\"]\n\n# Experimental HTTP/3 client.\nhttp3 = [\"rustls\", \"dep:h3\", \"dep:h3-quinn\", \"dep:quinn\", \"tokio/macros\"]\n\n\n# Internal (PRIVATE!) features used to aid testing.\n# Don't rely on these whatsoever. They may disappear at any time.\n\n# Enables common types used for TLS. Useless on its own.\n__tls = [\"dep:rustls-pki-types\", \"tokio/io-util\"]\n\n# Enables common rustls code.\n__rustls = [\"dep:hyper-rustls\", \"dep:tokio-rustls\", \"dep:rustls\", \"__tls\"]\n__rustls-aws-lc-rs = [\"hyper-rustls?/aws-lc-rs\", \"tokio-rustls?/aws-lc-rs\", \"rustls?/aws-lc-rs\", \"quinn?/rustls-aws-lc-rs\"]\n\n# Enables common native-tls code.\n__native-tls = [\"dep:hyper-tls\", \"dep:native-tls-crate\", \"__tls\", \"dep:tokio-native-tls\"]\n__native-tls-alpn = [\"native-tls-crate?/alpn\", \"hyper-tls?/alpn\"]\n\n[dependencies]\nbase64 = \"0.22\"\nhttp = \"1.1\"\nurl = \"2.4\"\nbytes = \"1.2\"\nfutures-core = { version = \"0.3.28\", default-features = false }\nfutures-util = { version = \"0.3.28\", default-features = false, optional = true }\nsync_wrapper = { version = \"1.0\", features = [\"futures\"] }\n\n# Optional deps...\n\nserde = { version = \"1.0\", optional = true }\n## query/form\nserde_urlencoded = { version = \"0.7.1\", optional = true }\n## json\nserde_json = { version = \"1.0\", optional = true }\n## multipart\nmime_guess = { version = \"2.0\", default-features = false, optional = true }\n\n[target.'cfg(not(target_arch = \"wasm32\"))'.dependencies]\nencoding_rs = { version = \"0.8\", optional = true }\nhttp-body = \"1\"\nhttp-body-util = \"0.1.2\"\nhyper = { version = \"1.1\", features = [\"http1\", \"client\"] }\nhyper-util = { version = \"0.1.12\", features = [\"http1\", \"client\", \"client-legacy\", \"client-proxy\", \"tokio\"] }\nh2 = { version = \"0.4\", optional = true }\nlog = \"0.4.17\"\npercent-encoding = \"2.3\"\ntokio = { version = \"1.0\", default-features = false, features = [\"net\", \"time\"] }\ntower = { version = \"0.5.2\", default-features = false, features = [\"retry\", \"timeout\", \"util\"] }\ntower-service = \"0.3\"\ntower-http = { version = \"0.6.8\", default-features = false, features = [\"follow-redirect\"] }\npin-project-lite = \"0.2.11\"\n\n# Optional deps...\nrustls-pki-types = { version = \"1.9.0\", features = [\"std\"], optional = true }\nmime = { version = \"0.3.16\", optional = true }\n\n# native-tls\nhyper-tls = { version = \"0.6\", optional = true }\nnative-tls-crate = { version = \"0.2.10\", optional = true, package = \"native-tls\" }\ntokio-native-tls = { version = \"0.3.0\", optional = true }\n\n# default rustls\nhyper-rustls = { version = \"0.27.0\", default-features = false, optional = true, features = [\"http1\", \"tls12\"] }\nrustls = { version = \"0.23.4\", optional = true, default-features = false, features = [\"std\", \"tls12\"] }\ntokio-rustls = { version = \"0.26\", optional = true, default-features = false, features = [\"tls12\"] }\nrustls-platform-verifier = { version = \"0.6\", optional = true }\n\n## cookies\ncookie_crate = { version = \"0.18.0\", package = \"cookie\", optional = true }\ncookie_store = { version = \"0.22.0\", optional = true }\n\n## stream\ntokio-util = { version = \"0.7.9\", default-features = false, features = [\"io\"], optional = true }\n\n## hickory-dns\nhickory-resolver = { version = \"0.25\", optional = true, features = [\"tokio\"] }\nonce_cell = { version = \"1.18\", optional = true }\n\n# HTTP/3 experimental support\nh3 = { version = \"0.0.8\", optional = true }\nh3-quinn = { version = \"0.0.10\", optional = true }\nquinn = { version = \"0.11.1\", default-features = false, features = [\"runtime-tokio\"], optional = true }\nfutures-channel = { version = \"0.3\", optional = true }\n\n[target.'cfg(not(target_arch = \"wasm32\"))'.dev-dependencies]\nenv_logger = \"0.10\"\nhyper = { version = \"1.1.0\", default-features = false, features = [\"http1\", \"http2\", \"client\", \"server\"] }\nhyper-util = { version = \"0.1.12\", features = [\"http1\", \"http2\", \"client\", \"client-legacy\", \"server-auto\", \"server-graceful\", \"tokio\"] }\nserde = { version = \"1.0\", features = [\"derive\"] }\nflate2 = \"1.0.13\"\nbrotli_crate = { package = \"brotli\", version = \"8\" }\nzstd_crate = { package = \"zstd\", version = \"0.13\" }\ndoc-comment = \"0.3\"\ntokio = { version = \"1.0\", default-features = false, features = [\"macros\", \"rt-multi-thread\"] }\nfutures-util = { version = \"0.3.28\", default-features = false, features = [\"std\", \"alloc\"] }\n\n# wasm\n\n[target.'cfg(target_arch = \"wasm32\")'.dependencies]\njs-sys = \"0.3.77\"\nwasm-bindgen = \"0.2.89\"\nwasm-bindgen-futures = \"0.4.18\"\nwasm-streams = { version = \"0.5\", optional = true }\n\n[target.'cfg(target_arch = \"wasm32\")'.dependencies.web-sys]\nversion = \"0.3.28\"\nfeatures = [\n    \"AbortController\",\n    \"AbortSignal\",\n    \"Headers\",\n    \"Request\",\n    \"RequestInit\",\n    \"RequestMode\",\n    \"Response\",\n    \"Window\",\n    \"FormData\",\n    \"Blob\",\n    \"BlobPropertyBag\",\n    \"ServiceWorkerGlobalScope\",\n    \"RequestCredentials\",\n    \"File\",\n    \"ReadableStream\",\n    \"RequestCache\"\n]\n\n[target.'cfg(target_arch = \"wasm32\")'.dev-dependencies]\nwasm-bindgen = { version = \"0.2.89\", features = [\"serde-serialize\"] }\nwasm-bindgen-test = \"0.3\"\n\n[dev-dependencies]\ntower = { version = \"0.5.2\", default-features = false, features = [\"limit\"] }\nnum_cpus = \"1.0\"\nlibc = \"0\"\n\n[lints.rust]\nunexpected_cfgs = { level = \"warn\", check-cfg = ['cfg(reqwest_unstable)'] }\n\n[[example]]\nname = \"blocking\"\npath = \"examples/blocking.rs\"\nrequired-features = [\"blocking\"]\n\n[[example]]\nname = \"json_dynamic\"\npath = \"examples/json_dynamic.rs\"\nrequired-features = [\"json\"]\n\n[[example]]\nname = \"json_typed\"\npath = \"examples/json_typed.rs\"\nrequired-features = [\"json\"]\n\n[[example]]\nname = \"tor_socks\"\npath = \"examples/tor_socks.rs\"\nrequired-features = [\"socks\"]\n\n[[example]]\nname = \"form\"\npath = \"examples/form.rs\"\nrequired-features = [\"form\"]\n\n[[example]]\nname = \"simple\"\npath = \"examples/simple.rs\"\n\n[[example]]\nname = \"h3_simple\"\npath = \"examples/h3_simple.rs\"\nrequired-features = [\"http3\", \"rustls\"]\n\n[[example]]\nname = \"connect_via_lower_priority_tokio_runtime\"\npath = \"examples/connect_via_lower_priority_tokio_runtime.rs\"\n\n[[test]]\nname = \"blocking\"\npath = \"tests/blocking.rs\"\nrequired-features = [\"blocking\"]\n\n[[test]]\nname = \"cookie\"\npath = \"tests/cookie.rs\"\nrequired-features = [\"cookies\"]\n\n[[test]]\nname = \"gzip\"\npath = \"tests/gzip.rs\"\nrequired-features = [\"gzip\", \"stream\"]\n\n[[test]]\nname = \"brotli\"\npath = \"tests/brotli.rs\"\nrequired-features = [\"brotli\", \"stream\"]\n\n[[test]]\nname = \"zstd\"\npath = \"tests/zstd.rs\"\nrequired-features = [\"zstd\", \"stream\"]\n\n[[test]]\nname = \"deflate\"\npath = \"tests/deflate.rs\"\nrequired-features = [\"deflate\", \"stream\"]\n\n[[test]]\nname = \"multipart\"\npath = \"tests/multipart.rs\"\nrequired-features = [\"multipart\"]\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright 2016 Sean McArthur\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2016-2026 Sean McArthur\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# reqwest\n\n[![crates.io](https://img.shields.io/crates/v/reqwest.svg)](https://crates.io/crates/reqwest)\n[![Documentation](https://docs.rs/reqwest/badge.svg)](https://docs.rs/reqwest)\n[![MIT/Apache-2 licensed](https://img.shields.io/crates/l/reqwest.svg)](./LICENSE-APACHE)\n[![CI](https://github.com/seanmonstar/reqwest/actions/workflows/ci.yml/badge.svg)](https://github.com/seanmonstar/reqwest/actions/workflows/ci.yml)\n\nAn ergonomic, batteries-included HTTP Client for Rust.\n\n- Async and blocking `Client`s\n- Plain bodies, JSON, urlencoded, multipart\n- Customizable redirect policy\n- HTTP Proxies\n- HTTPS via rustls (or optionally, system-native TLS)\n- Cookie Store\n- WASM\n\n\n## Example\n\nThis asynchronous example uses [Tokio](https://tokio.rs) and enables some\noptional features, so your `Cargo.toml` could look like this:\n\n```toml\n[dependencies]\nreqwest = { version = \"0.13\", features = [\"json\"] }\ntokio = { version = \"1\", features = [\"full\"] }\n```\n\nAnd then the code:\n\n```rust,no_run\nuse std::collections::HashMap;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let resp = reqwest::get(\"https://httpbin.org/ip\")\n        .await?\n        .json::<HashMap<String, String>>()\n        .await?;\n    println!(\"{resp:#?}\");\n    Ok(())\n}\n```\n\n## Commercial Support\n\nFor private advice, support, reviews, access to the maintainer, and the like, reach out for [commercial support][sponsor].\n\n## Requirements\n\nBy default, Reqwest uses [rustls](https://github.com/rustls/rustls), but when the `native-tls` feature is enabled\nit will use the operating system TLS framework if available, meaning Windows and macOS.\nOn Linux, it will use the available OpenSSL (see https://docs.rs/openssl for supported versions and more details)\nor fail to build if not found. Alternatively you can enable the `native-tls-vendored` feature to compile a copy of OpenSSL.\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://apache.org/licenses/LICENSE-2.0)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\n## Sponsors\n\nSupport this project by becoming a [sponsor][].\n\n[sponsor]: https://seanmonstar.com/sponsor\n"
  },
  {
    "path": "examples/blocking.rs",
    "content": "//! `cargo run --example blocking --features=blocking`\n#![deny(warnings)]\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    env_logger::init();\n\n    // Some simple CLI args requirements...\n    let url = match std::env::args().nth(1) {\n        Some(url) => url,\n        None => {\n            println!(\"No CLI URL provided, using default.\");\n            \"https://hyper.rs\".into()\n        }\n    };\n\n    eprintln!(\"Fetching {url:?}...\");\n\n    // reqwest::blocking::get() is a convenience function.\n    //\n    // In most cases, you should create/build a reqwest::Client and reuse\n    // it for all requests.\n    let mut res = reqwest::blocking::get(url)?;\n\n    eprintln!(\"Response: {:?} {}\", res.version(), res.status());\n    eprintln!(\"Headers: {:#?}\\n\", res.headers());\n\n    // copy the response body directly to stdout\n    res.copy_to(&mut std::io::stdout())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/connect_via_lower_priority_tokio_runtime.rs",
    "content": "#![deny(warnings)]\n// This example demonstrates how to delegate the connect calls, which contain TLS handshakes,\n// to a secondary tokio runtime of lower OS thread priority using a custom tower layer.\n// This helps to ensure that long-running futures during handshake crypto operations don't block other I/O futures.\n//\n// This does introduce overhead of additional threads, channels, extra vtables, etc,\n// so it is best suited to services with large numbers of incoming connections or that\n// are otherwise very sensitive to any blocking futures.  Or, you might want fewer threads\n// and/or to use the current_thread runtime.\n//\n// This is using the `tokio` runtime and certain other dependencies:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n// `num_cpus = \"1.0\"`\n// `libc = \"0\"`\n// `pin-project-lite = \"0.2\"`\n// `tower = { version = \"0.5\", default-features = false}`\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    background_threadpool::init_background_runtime();\n    tokio::time::sleep(std::time::Duration::from_millis(10)).await;\n\n    let client = reqwest::Client::builder()\n        .connector_layer(background_threadpool::BackgroundProcessorLayer::new())\n        .build()\n        .expect(\"should be able to build reqwest client\");\n\n    let url = if let Some(url) = std::env::args().nth(1) {\n        url\n    } else {\n        println!(\"No CLI URL provided, using default.\");\n        \"https://hyper.rs\".into()\n    };\n\n    eprintln!(\"Fetching {url:?}...\");\n\n    let res = client.get(url).send().await?;\n\n    eprintln!(\"Response: {:?} {}\", res.version(), res.status());\n    eprintln!(\"Headers: {:#?}\\n\", res.headers());\n\n    let body = res.text().await?;\n\n    println!(\"{body}\");\n\n    Ok(())\n}\n\n// separating out for convenience to avoid a million #[cfg(not(target_arch = \"wasm32\"))]\n#[cfg(not(target_arch = \"wasm32\"))]\nmod background_threadpool {\n    use std::{\n        future::Future,\n        pin::Pin,\n        sync::OnceLock,\n        task::{Context, Poll},\n    };\n\n    use futures_util::TryFutureExt;\n    use pin_project_lite::pin_project;\n    use tokio::{runtime::Handle, select, sync::mpsc::error::TrySendError};\n    use tower::{BoxError, Layer, Service};\n\n    static CPU_HEAVY_THREAD_POOL: OnceLock<\n        tokio::sync::mpsc::Sender<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>,\n    > = OnceLock::new();\n\n    pub(crate) fn init_background_runtime() {\n        std::thread::Builder::new()\n            .name(\"cpu-heavy-background-threadpool\".to_string())\n            .spawn(move || {\n                let rt = tokio::runtime::Builder::new_multi_thread()\n                    .thread_name(\"cpu-heavy-background-pool-thread\")\n                    .worker_threads(num_cpus::get() as usize)\n                    // ref: https://github.com/tokio-rs/tokio/issues/4941\n                    // consider uncommenting if seeing heavy task contention\n                    // .disable_lifo_slot()\n                    .on_thread_start(move || {\n                        #[cfg(target_os = \"linux\")]\n                        unsafe {\n                            // Increase thread pool thread niceness, so they are lower priority\n                            // than the foreground executor and don't interfere with I/O tasks\n                            {\n                                *libc::__errno_location() = 0;\n                                if libc::nice(10) == -1 && *libc::__errno_location() != 0 {\n                                    let error = std::io::Error::last_os_error();\n                                    log::error!(\"failed to set threadpool niceness: {}\", error);\n                                }\n                            }\n                        }\n                    })\n                    .enable_all()\n                    .build()\n                    .unwrap_or_else(|e| panic!(\"cpu heavy runtime failed_to_initialize: {}\", e));\n                rt.block_on(async {\n                    log::debug!(\"starting background cpu-heavy work\");\n                    process_cpu_work().await;\n                });\n            })\n            .unwrap_or_else(|e| panic!(\"cpu heavy thread failed_to_initialize: {}\", e));\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    async fn process_cpu_work() {\n        // we only use this channel for routing work, it should move pretty quick, it can be small\n        let (tx, mut rx) = tokio::sync::mpsc::channel(10);\n        // share the handle to the background channel globally\n        CPU_HEAVY_THREAD_POOL.set(tx).unwrap();\n\n        while let Some(work) = rx.recv().await {\n            tokio::task::spawn(work);\n        }\n    }\n\n    // retrieve the sender to the background channel, and send the future over to it for execution\n    fn send_to_background_runtime(future: impl Future<Output = ()> + Send + 'static) {\n        let tx = CPU_HEAVY_THREAD_POOL.get().expect(\n            \"start up the secondary tokio runtime before sending to `CPU_HEAVY_THREAD_POOL`\",\n        );\n\n        match tx.try_send(Box::pin(future)) {\n            Ok(_) => (),\n            Err(TrySendError::Closed(_)) => {\n                panic!(\"background cpu heavy runtime channel is closed\")\n            }\n            Err(TrySendError::Full(msg)) => {\n                log::warn!(\n                    \"background cpu heavy runtime channel is full, task spawning loop delayed\"\n                );\n                let tx = tx.clone();\n                Handle::current().spawn(async move {\n                    tx.send(msg)\n                        .await\n                        .expect(\"background cpu heavy runtime channel is closed\")\n                });\n            }\n        }\n    }\n\n    // This tower layer injects futures with a oneshot channel, and then sends them to the background runtime for processing.\n    // We don't use the Buffer service because that is intended to process sequentially on a single task, whereas we want to\n    // spawn a new task per call.\n    #[derive(Copy, Clone)]\n    pub struct BackgroundProcessorLayer {}\n    impl BackgroundProcessorLayer {\n        pub fn new() -> Self {\n            Self {}\n        }\n    }\n    impl<S> Layer<S> for BackgroundProcessorLayer {\n        type Service = BackgroundProcessor<S>;\n        fn layer(&self, service: S) -> Self::Service {\n            BackgroundProcessor::new(service)\n        }\n    }\n\n    impl std::fmt::Debug for BackgroundProcessorLayer {\n        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n            f.debug_struct(\"BackgroundProcessorLayer\").finish()\n        }\n    }\n\n    // This tower service injects futures with a oneshot channel, and then sends them to the background runtime for processing.\n    #[derive(Debug, Clone)]\n    pub struct BackgroundProcessor<S> {\n        inner: S,\n    }\n\n    impl<S> BackgroundProcessor<S> {\n        pub fn new(inner: S) -> Self {\n            BackgroundProcessor { inner }\n        }\n    }\n\n    impl<S, Request> Service<Request> for BackgroundProcessor<S>\n    where\n        S: Service<Request>,\n        S::Response: Send + 'static,\n        S::Error: Into<BoxError> + Send,\n        S::Future: Send + 'static,\n    {\n        type Response = S::Response;\n\n        type Error = BoxError;\n\n        type Future = BackgroundResponseFuture<S::Response>;\n\n        fn poll_ready(\n            &mut self,\n            cx: &mut std::task::Context<'_>,\n        ) -> std::task::Poll<Result<(), Self::Error>> {\n            match self.inner.poll_ready(cx) {\n                Poll::Pending => Poll::Pending,\n                Poll::Ready(r) => Poll::Ready(r.map_err(Into::into)),\n            }\n        }\n\n        fn call(&mut self, req: Request) -> Self::Future {\n            let response = self.inner.call(req);\n\n            // wrap our inner service's future with a future that writes to this oneshot channel\n            let (mut tx, rx) = tokio::sync::oneshot::channel();\n            let future = async move {\n                select!(\n                    _ = tx.closed() => {\n                        // receiver already dropped, don't need to do anything\n                    }\n                    result = response.map_err(|err| Into::<BoxError>::into(err)) => {\n                        // if this fails, the receiver already dropped, so we don't need to do anything\n                        let _ = tx.send(result);\n                    }\n                )\n            };\n            // send the wrapped future to the background\n            send_to_background_runtime(future);\n\n            BackgroundResponseFuture::new(rx)\n        }\n    }\n\n    // `BackgroundProcessor` response future\n    pin_project! {\n        #[derive(Debug)]\n        pub struct BackgroundResponseFuture<S> {\n            #[pin]\n            rx: tokio::sync::oneshot::Receiver<Result<S, BoxError>>,\n        }\n    }\n\n    impl<S> BackgroundResponseFuture<S> {\n        pub(crate) fn new(rx: tokio::sync::oneshot::Receiver<Result<S, BoxError>>) -> Self {\n            BackgroundResponseFuture { rx }\n        }\n    }\n\n    impl<S> Future for BackgroundResponseFuture<S>\n    where\n        S: Send + 'static,\n    {\n        type Output = Result<S, BoxError>;\n\n        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n            let this = self.project();\n\n            // now poll on the receiver end of the oneshot to get the result\n            match this.rx.poll(cx) {\n                Poll::Ready(v) => match v {\n                    Ok(v) => Poll::Ready(v.map_err(Into::into)),\n                    Err(err) => Poll::Ready(Err(Box::new(err) as BoxError)),\n                },\n                Poll::Pending => Poll::Pending,\n            }\n        }\n    }\n}\n\n// The [cfg(not(target_arch = \"wasm32\"))] above prevent building the tokio::main function\n// for wasm32 target, because tokio isn't compatible with wasm32.\n// If you aren't building for wasm32, you don't need that line.\n// The two lines below avoid the \"'main' function not found\" error when building for wasm32 target.\n#[cfg(any(target_arch = \"wasm32\"))]\nfn main() {}\n"
  },
  {
    "path": "examples/form.rs",
    "content": "// Short example of a POST request with form data.\n//\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::main]\nasync fn main() {\n    let response = reqwest::Client::new()\n        .post(\"http://www.baidu.com\")\n        .form(&[(\"one\", \"1\")])\n        .send()\n        .await\n        .expect(\"send\");\n    println!(\"Response status {}\", response.status());\n}\n\n// The [cfg(not(target_arch = \"wasm32\"))] above prevent building the tokio::main function\n// for wasm32 target, because tokio isn't compatible with wasm32.\n// If you aren't building for wasm32, you don't need that line.\n// The two lines below avoid the \"'main' function not found\" error when building for wasm32 target.\n#[cfg(target_arch = \"wasm32\")]\nfn main() {}\n"
  },
  {
    "path": "examples/h3_simple.rs",
    "content": "#![deny(warnings)]\n\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[cfg(feature = \"http3\")]\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    let client = reqwest::Client::builder().http3_prior_knowledge().build()?;\n\n    // Some simple CLI args requirements...\n    let url = match std::env::args().nth(1) {\n        Some(url) => url,\n        None => {\n            println!(\"No CLI URL provided, using default.\");\n            \"https://hyper.rs\".into()\n        }\n    };\n\n    eprintln!(\"Fetching {url:?}...\");\n\n    let res = client\n        .get(url)\n        .version(http::Version::HTTP_3)\n        .send()\n        .await?;\n\n    eprintln!(\"Response: {:?} {}\", res.version(), res.status());\n    eprintln!(\"Headers: {:#?}\\n\", res.headers());\n\n    let body = res.text().await?;\n\n    println!(\"{body}\");\n\n    Ok(())\n}\n\n// The [cfg(not(target_arch = \"wasm32\"))] above prevent building the tokio::main function\n// for wasm32 target, because tokio isn't compatible with wasm32.\n// If you aren't building for wasm32, you don't need that line.\n// The two lines below avoid the \"'main' function not found\" error when building for wasm32 target.\n#[cfg(any(target_arch = \"wasm32\", not(feature = \"http3\")))]\nfn main() {}\n"
  },
  {
    "path": "examples/json_dynamic.rs",
    "content": "//! This example illustrates the way to send and receive arbitrary JSON.\n//!\n//! This is useful for some ad-hoc experiments and situations when you don't\n//! really care about the structure of the JSON and just need to display it or\n//! process it at runtime.\n\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    let echo_json: serde_json::Value = reqwest::Client::new()\n        .post(\"https://jsonplaceholder.typicode.com/posts\")\n        .json(&serde_json::json!({\n            \"title\": \"Reqwest.rs\",\n            \"body\": \"https://docs.rs/reqwest\",\n            \"userId\": 1\n        }))\n        .send()\n        .await?\n        .json()\n        .await?;\n\n    println!(\"{echo_json:#?}\");\n    // Object(\n    //     {\n    //         \"body\": String(\n    //             \"https://docs.rs/reqwest\"\n    //         ),\n    //         \"id\": Number(\n    //             101\n    //         ),\n    //         \"title\": String(\n    //             \"Reqwest.rs\"\n    //         ),\n    //         \"userId\": Number(\n    //             1\n    //         )\n    //     }\n    // )\n    Ok(())\n}\n"
  },
  {
    "path": "examples/json_typed.rs",
    "content": "//! This example illustrates the way to send and receive statically typed JSON.\n//!\n//! In contrast to the arbitrary JSON example, this brings up the full power of\n//! Rust compile-time type system guaranties though it requires a little bit\n//! more code.\n\n// These require the `serde` dependency.\nuse serde::{Deserialize, Serialize};\n\n#[derive(Debug, Serialize, Deserialize)]\nstruct Post {\n    id: Option<i32>,\n    title: String,\n    body: String,\n    #[serde(rename = \"userId\")]\n    user_id: i32,\n}\n\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    let new_post = Post {\n        id: None,\n        title: \"Reqwest.rs\".into(),\n        body: \"https://docs.rs/reqwest\".into(),\n        user_id: 1,\n    };\n    let new_post: Post = reqwest::Client::new()\n        .post(\"https://jsonplaceholder.typicode.com/posts\")\n        .json(&new_post)\n        .send()\n        .await?\n        .json()\n        .await?;\n\n    println!(\"{new_post:#?}\");\n    // Post {\n    //     id: Some(\n    //         101\n    //     ),\n    //     title: \"Reqwest.rs\",\n    //     body: \"https://docs.rs/reqwest\",\n    //     user_id: 1\n    // }\n    Ok(())\n}\n"
  },
  {
    "path": "examples/simple.rs",
    "content": "#![deny(warnings)]\n\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    // Some simple CLI args requirements...\n    let url = if let Some(url) = std::env::args().nth(1) {\n        url\n    } else {\n        println!(\"No CLI URL provided, using default.\");\n        \"https://hyper.rs\".into()\n    };\n\n    eprintln!(\"Fetching {url:?}...\");\n\n    // reqwest::get() is a convenience function.\n    //\n    // In most cases, you should create/build a reqwest::Client and reuse\n    // it for all requests.\n    let res = reqwest::get(url).await?;\n\n    eprintln!(\"Response: {:?} {}\", res.version(), res.status());\n    eprintln!(\"Headers: {:#?}\\n\", res.headers());\n\n    let body = res.text().await?;\n\n    println!(\"{body}\");\n\n    Ok(())\n}\n\n// The [cfg(not(target_arch = \"wasm32\"))] above prevent building the tokio::main function\n// for wasm32 target, because tokio isn't compatible with wasm32.\n// If you aren't building for wasm32, you don't need that line.\n// The two lines below avoid the \"'main' function not found\" error when building for wasm32 target.\n#[cfg(target_arch = \"wasm32\")]\nfn main() {}\n"
  },
  {
    "path": "examples/tor_socks.rs",
    "content": "#![deny(warnings)]\n\n// This is using the `tokio` runtime. You'll need the following dependency:\n//\n// `tokio = { version = \"1\", features = [\"full\"] }`\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n    // Make sure you are running tor and this is your socks port\n    let proxy = reqwest::Proxy::all(\"socks5h://127.0.0.1:9050\").expect(\"tor proxy should be there\");\n    let client = reqwest::Client::builder()\n        .proxy(proxy)\n        .build()\n        .expect(\"should be able to build reqwest client\");\n\n    let res = client.get(\"https://check.torproject.org\").send().await?;\n    println!(\"Status: {}\", res.status());\n\n    let text = res.text().await?;\n    let is_tor = text.contains(\"Congratulations. This browser is configured to use Tor.\");\n    println!(\"Is Tor: {is_tor}\");\n    assert!(is_tor);\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/wasm_github_fetch/.gitignore",
    "content": "node_modules\npkg\ntarget\nCargo.lock\n*.swp\n"
  },
  {
    "path": "examples/wasm_github_fetch/Cargo.toml",
    "content": "[package]\nname = \"wasm\"\nversion = \"0.1.0\"\nauthors = [\"John Gallagher <john.willis.gallagher@gmail.com>\"]\nedition = \"2021\"\n\n# Config mostly pulled from: https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/Cargo.toml\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nreqwest = {path = \"../../\"}\nserde = { version = \"1.0.101\", features = [\"derive\"] }\nserde_derive = \"^1.0.59\"\nwasm-bindgen-futures = \"0.4.1\"\nserde_json = \"1.0.41\"\nwasm-bindgen = { version = \"0.2.51\", features = [\"serde-serialize\"]  }\n"
  },
  {
    "path": "examples/wasm_github_fetch/README.md",
    "content": "## Example usage of Reqwest from WASM\n\nInstall wasm-pack with\n\n    npm install\n\nThen you can build the example locally with:\n\n\n    npm run serve\n\nand then visiting http://localhost:8080 in a browser should run the example!\n\n\nThis example is loosely based off of [this example](https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/src/lib.rs), an example usage of `fetch` from `wasm-bindgen`."
  },
  {
    "path": "examples/wasm_github_fetch/index.js",
    "content": "const rust = import('./pkg');\n\nrust\n    .then(m => {\n        return m.run().then((data) => {\n            console.log(data);\n\n            console.log(\"The latest commit to the wasm-bindgen %s branch is:\", data.name);\n            console.log(\"%s, authored by %s <%s>\", data.commit.sha, data.commit.commit.author.name, data.commit.commit.author.email);\n        })\n    })\n    .catch(console.error);"
  },
  {
    "path": "examples/wasm_github_fetch/osv-scanner.toml",
    "content": "[[PackageOverrides]]\necosystem = \"npm\"\nignore = true\n"
  },
  {
    "path": "examples/wasm_github_fetch/package.json",
    "content": "{\n    \"scripts\": {\n        \"build\": \"webpack\",\n        \"serve\": \"webpack-dev-server\"\n    },\n    \"devDependencies\": {\n        \"@wasm-tool/wasm-pack-plugin\": \"1.0.1\",\n        \"text-encoding\": \"^0.7.0\",\n        \"html-webpack-plugin\": \"^3.2.0\",\n        \"webpack\": \"^4.29.4\",\n        \"webpack-cli\": \"^3.1.1\",\n        \"webpack-dev-server\": \"^3.1.0\"\n    }\n}\n"
  },
  {
    "path": "examples/wasm_github_fetch/src/lib.rs",
    "content": "use serde::{Deserialize, Serialize};\nuse wasm_bindgen::prelude::*;\n\n// NOTE: This test is a clone of https://github.com/rustwasm/wasm-bindgen/blob/master/examples/fetch/src/lib.rs\n// but uses Reqwest instead of the web_sys fetch api directly\n\n/// A struct to hold some data from the GitHub Branch API.\n///\n/// Note how we don't have to define every member -- serde will ignore extra\n/// data when deserializing\n#[derive(Debug, Serialize, Deserialize)]\npub struct Branch {\n    pub name: String,\n    pub commit: Commit,\n}\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Commit {\n    pub sha: String,\n    pub commit: CommitDetails,\n}\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct CommitDetails {\n    pub author: Signature,\n    pub committer: Signature,\n}\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Signature {\n    pub name: String,\n    pub email: String,\n}\n\n#[wasm_bindgen]\npub async fn run() -> Result<JsValue, JsValue> {\n    let res = reqwest::Client::new()\n        .get(\"https://api.github.com/repos/rustwasm/wasm-bindgen/branches/master\")\n        .header(\"Accept\", \"application/vnd.github.v3+json\")\n        .send()\n        .await?;\n\n    let text = res.text().await?;\n    let branch_info: Branch = serde_json::from_str(&text).unwrap();\n\n    Ok(JsValue::from_serde(&branch_info).unwrap())\n}\n"
  },
  {
    "path": "examples/wasm_github_fetch/webpack.config.js",
    "content": "const path = require('path');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst webpack = require('webpack');\nconst WasmPackPlugin = require(\"@wasm-tool/wasm-pack-plugin\");\n\nmodule.exports = {\n    entry: './index.js',\n    output: {\n        path: path.resolve(__dirname, 'dist'),\n        filename: 'index.js',\n    },\n    plugins: [\n        new HtmlWebpackPlugin(),\n        new WasmPackPlugin({\n            crateDirectory: path.resolve(__dirname, \".\")\n        }),\n        // Have this example work in Edge which doesn't ship `TextEncoder` or\n        // `TextDecoder` at this time.\n        new webpack.ProvidePlugin({\n            TextDecoder: ['text-encoding', 'TextDecoder'],\n            TextEncoder: ['text-encoding', 'TextEncoder']\n        })\n    ],\n    mode: 'development'\n};"
  },
  {
    "path": "src/async_impl/body.rs",
    "content": "use std::fmt;\nuse std::future::Future;\nuse std::pin::Pin;\nuse std::task::{ready, Context, Poll};\nuse std::time::Duration;\n\nuse bytes::Bytes;\nuse http_body::Body as HttpBody;\nuse http_body_util::combinators::BoxBody;\nuse pin_project_lite::pin_project;\n#[cfg(feature = \"stream\")]\nuse tokio::fs::File;\nuse tokio::time::Sleep;\n#[cfg(feature = \"stream\")]\nuse tokio_util::io::ReaderStream;\n\n/// An asynchronous request body.\npub struct Body {\n    inner: Inner,\n}\n\nenum Inner {\n    Reusable(Bytes),\n    Streaming(BoxBody<Bytes, Box<dyn std::error::Error + Send + Sync>>),\n}\n\npin_project! {\n    /// A body with a total timeout.\n    ///\n    /// The timeout does not reset upon each chunk, but rather requires the whole\n    /// body be streamed before the deadline is reached.\n    pub(crate) struct TotalTimeoutBody<B> {\n        #[pin]\n        inner: B,\n        timeout: Pin<Box<Sleep>>,\n    }\n}\n\npin_project! {\n    pub(crate) struct ReadTimeoutBody<B> {\n        #[pin]\n        inner: B,\n        #[pin]\n        sleep: Option<Sleep>,\n        timeout: Duration,\n    }\n}\n\nimpl Body {\n    /// Returns a reference to the internal data of the `Body`.\n    ///\n    /// `None` is returned, if the underlying data is a stream.\n    pub fn as_bytes(&self) -> Option<&[u8]> {\n        match &self.inner {\n            Inner::Reusable(bytes) => Some(bytes.as_ref()),\n            Inner::Streaming(..) => None,\n        }\n    }\n\n    /// Wrap a futures `Stream` in a box inside `Body`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use reqwest::Body;\n    /// # use futures_util;\n    /// # fn main() {\n    /// let chunks: Vec<Result<_, ::std::io::Error>> = vec![\n    ///     Ok(\"hello\"),\n    ///     Ok(\" \"),\n    ///     Ok(\"world\"),\n    /// ];\n    ///\n    /// let stream = futures_util::stream::iter(chunks);\n    ///\n    /// let body = Body::wrap_stream(stream);\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `stream` feature to be enabled.\n    #[cfg(feature = \"stream\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"stream\")))]\n    pub fn wrap_stream<S>(stream: S) -> Body\n    where\n        S: futures_core::stream::TryStream + Send + 'static,\n        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n        Bytes: From<S::Ok>,\n    {\n        Body::stream(stream)\n    }\n\n    #[cfg(any(feature = \"stream\", feature = \"multipart\", feature = \"blocking\"))]\n    pub(crate) fn stream<S>(stream: S) -> Body\n    where\n        S: futures_core::stream::TryStream + Send + 'static,\n        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n        Bytes: From<S::Ok>,\n    {\n        use futures_util::TryStreamExt;\n        use http_body::Frame;\n        use http_body_util::StreamBody;\n\n        let body = http_body_util::BodyExt::boxed(StreamBody::new(sync_wrapper::SyncStream::new(\n            stream\n                .map_ok(|d| Frame::data(Bytes::from(d)))\n                .map_err(Into::into),\n        )));\n        Body {\n            inner: Inner::Streaming(body),\n        }\n    }\n\n    pub(crate) fn empty() -> Body {\n        Body::reusable(Bytes::new())\n    }\n\n    pub(crate) fn reusable(chunk: Bytes) -> Body {\n        Body {\n            inner: Inner::Reusable(chunk),\n        }\n    }\n\n    /// Wrap a [`HttpBody`] in a box inside `Body`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use reqwest::Body;\n    /// # use futures_util;\n    /// # fn main() {\n    /// let content = \"hello,world!\".to_string();\n    ///\n    /// let body = Body::wrap(content);\n    /// # }\n    /// ```\n    pub fn wrap<B>(inner: B) -> Body\n    where\n        B: HttpBody + Send + Sync + 'static,\n        B::Data: Into<Bytes>,\n        B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n    {\n        use http_body_util::BodyExt;\n\n        let boxed = IntoBytesBody { inner }.map_err(Into::into).boxed();\n\n        Body {\n            inner: Inner::Streaming(boxed),\n        }\n    }\n\n    pub(crate) fn try_clone(&self) -> Option<Body> {\n        match self.inner {\n            Inner::Reusable(ref chunk) => Some(Body::reusable(chunk.clone())),\n            Inner::Streaming { .. } => None,\n        }\n    }\n\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn content_length(&self) -> Option<u64> {\n        match self.inner {\n            Inner::Reusable(ref bytes) => Some(bytes.len() as u64),\n            Inner::Streaming(ref body) => body.size_hint().exact(),\n        }\n    }\n}\n\nimpl Default for Body {\n    #[inline]\n    fn default() -> Body {\n        Body::empty()\n    }\n}\n\n/*\nimpl From<hyper::Body> for Body {\n    #[inline]\n    fn from(body: hyper::Body) -> Body {\n        Self {\n            inner: Inner::Streaming {\n                body: Box::pin(WrapHyper(body)),\n            },\n        }\n    }\n}\n*/\n\nimpl From<Bytes> for Body {\n    #[inline]\n    fn from(bytes: Bytes) -> Body {\n        Body::reusable(bytes)\n    }\n}\n\nimpl From<Vec<u8>> for Body {\n    #[inline]\n    fn from(vec: Vec<u8>) -> Body {\n        Body::reusable(vec.into())\n    }\n}\n\nimpl From<&'static [u8]> for Body {\n    #[inline]\n    fn from(s: &'static [u8]) -> Body {\n        Body::reusable(Bytes::from_static(s))\n    }\n}\n\nimpl From<String> for Body {\n    #[inline]\n    fn from(s: String) -> Body {\n        Body::reusable(s.into())\n    }\n}\n\nimpl From<&'static str> for Body {\n    #[inline]\n    fn from(s: &'static str) -> Body {\n        s.as_bytes().into()\n    }\n}\n\n#[cfg(feature = \"stream\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"stream\")))]\nimpl From<File> for Body {\n    #[inline]\n    fn from(file: File) -> Body {\n        Body::wrap_stream(ReaderStream::new(file))\n    }\n}\n\nimpl fmt::Debug for Body {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Body\").finish()\n    }\n}\n\nimpl HttpBody for Body {\n    type Data = Bytes;\n    type Error = crate::Error;\n\n    fn poll_frame(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        match self.inner {\n            Inner::Reusable(ref mut bytes) => {\n                let out = bytes.split_off(0);\n                if out.is_empty() {\n                    Poll::Ready(None)\n                } else {\n                    Poll::Ready(Some(Ok(hyper::body::Frame::data(out))))\n                }\n            }\n            Inner::Streaming(ref mut body) => Poll::Ready(\n                ready!(Pin::new(body).poll_frame(cx))\n                    .map(|opt_chunk| opt_chunk.map_err(crate::error::body)),\n            ),\n        }\n    }\n\n    fn size_hint(&self) -> http_body::SizeHint {\n        match self.inner {\n            Inner::Reusable(ref bytes) => http_body::SizeHint::with_exact(bytes.len() as u64),\n            Inner::Streaming(ref body) => body.size_hint(),\n        }\n    }\n\n    fn is_end_stream(&self) -> bool {\n        match self.inner {\n            Inner::Reusable(ref bytes) => bytes.is_empty(),\n            Inner::Streaming(ref body) => body.is_end_stream(),\n        }\n    }\n}\n\n// ===== impl TotalTimeoutBody =====\n\npub(crate) fn total_timeout<B>(body: B, timeout: Pin<Box<Sleep>>) -> TotalTimeoutBody<B> {\n    TotalTimeoutBody {\n        inner: body,\n        timeout,\n    }\n}\n\npub(crate) fn with_read_timeout<B>(body: B, timeout: Duration) -> ReadTimeoutBody<B> {\n    ReadTimeoutBody {\n        inner: body,\n        sleep: None,\n        timeout,\n    }\n}\n\nimpl<B> hyper::body::Body for TotalTimeoutBody<B>\nwhere\n    B: hyper::body::Body,\n    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    type Data = B::Data;\n    type Error = crate::Error;\n\n    fn poll_frame(\n        self: Pin<&mut Self>,\n        cx: &mut Context,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        let this = self.project();\n        if let Poll::Ready(()) = this.timeout.as_mut().poll(cx) {\n            return Poll::Ready(Some(Err(crate::error::body(crate::error::TimedOut))));\n        }\n        Poll::Ready(\n            ready!(this.inner.poll_frame(cx))\n                .map(|opt_chunk| opt_chunk.map_err(crate::error::body)),\n        )\n    }\n\n    #[inline]\n    fn size_hint(&self) -> http_body::SizeHint {\n        self.inner.size_hint()\n    }\n\n    #[inline]\n    fn is_end_stream(&self) -> bool {\n        self.inner.is_end_stream()\n    }\n}\n\nimpl<B> hyper::body::Body for ReadTimeoutBody<B>\nwhere\n    B: hyper::body::Body,\n    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    type Data = B::Data;\n    type Error = crate::Error;\n\n    fn poll_frame(\n        self: Pin<&mut Self>,\n        cx: &mut Context,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        let mut this = self.project();\n\n        // Start the `Sleep` if not active.\n        let sleep_pinned = if let Some(some) = this.sleep.as_mut().as_pin_mut() {\n            some\n        } else {\n            this.sleep.set(Some(tokio::time::sleep(*this.timeout)));\n            this.sleep.as_mut().as_pin_mut().unwrap()\n        };\n\n        // Error if the timeout has expired.\n        if let Poll::Ready(()) = sleep_pinned.poll(cx) {\n            return Poll::Ready(Some(Err(crate::error::body(crate::error::TimedOut))));\n        }\n\n        let item = ready!(this.inner.poll_frame(cx))\n            .map(|opt_chunk| opt_chunk.map_err(crate::error::body));\n        // a ready frame means timeout is reset\n        this.sleep.set(None);\n        Poll::Ready(item)\n    }\n\n    #[inline]\n    fn size_hint(&self) -> http_body::SizeHint {\n        self.inner.size_hint()\n    }\n\n    #[inline]\n    fn is_end_stream(&self) -> bool {\n        self.inner.is_end_stream()\n    }\n}\n\npub(crate) type ResponseBody =\n    http_body_util::combinators::BoxBody<Bytes, Box<dyn std::error::Error + Send + Sync>>;\n\npub(crate) fn boxed<B>(body: B) -> ResponseBody\nwhere\n    B: hyper::body::Body<Data = Bytes> + Send + Sync + 'static,\n    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    use http_body_util::BodyExt;\n\n    body.map_err(box_err).boxed()\n}\n\npub(crate) fn response<B>(\n    body: B,\n    deadline: Option<Pin<Box<Sleep>>>,\n    read_timeout: Option<Duration>,\n) -> ResponseBody\nwhere\n    B: hyper::body::Body<Data = Bytes> + Send + Sync + 'static,\n    B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    use http_body_util::BodyExt;\n\n    match (deadline, read_timeout) {\n        (Some(total), Some(read)) => {\n            let body = with_read_timeout(body, read).map_err(box_err);\n            total_timeout(body, total).map_err(box_err).boxed()\n        }\n        (Some(total), None) => total_timeout(body, total).map_err(box_err).boxed(),\n        (None, Some(read)) => with_read_timeout(body, read).map_err(box_err).boxed(),\n        (None, None) => body.map_err(box_err).boxed(),\n    }\n}\n\nfn box_err<E>(err: E) -> Box<dyn std::error::Error + Send + Sync>\nwhere\n    E: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    err.into()\n}\n\n// ===== impl IntoBytesBody =====\n\npin_project! {\n    struct IntoBytesBody<B> {\n        #[pin]\n        inner: B,\n    }\n}\n\n// We can't use `map_frame()` because that loses the hint data (for good reason).\n// But we aren't transforming the data.\nimpl<B> hyper::body::Body for IntoBytesBody<B>\nwhere\n    B: hyper::body::Body,\n    B::Data: Into<Bytes>,\n{\n    type Data = Bytes;\n    type Error = B::Error;\n\n    fn poll_frame(\n        self: Pin<&mut Self>,\n        cx: &mut Context,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        match ready!(self.project().inner.poll_frame(cx)) {\n            Some(Ok(f)) => Poll::Ready(Some(Ok(f.map_data(Into::into)))),\n            Some(Err(e)) => Poll::Ready(Some(Err(e))),\n            None => Poll::Ready(None),\n        }\n    }\n\n    #[inline]\n    fn size_hint(&self) -> http_body::SizeHint {\n        self.inner.size_hint()\n    }\n\n    #[inline]\n    fn is_end_stream(&self) -> bool {\n        self.inner.is_end_stream()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use http_body::Body as _;\n\n    use super::Body;\n\n    #[test]\n    fn test_as_bytes() {\n        let test_data = b\"Test body\";\n        let body = Body::from(&test_data[..]);\n        assert_eq!(body.as_bytes(), Some(&test_data[..]));\n    }\n\n    #[test]\n    fn body_exact_length() {\n        let empty_body = Body::empty();\n        assert!(empty_body.is_end_stream());\n        assert_eq!(empty_body.size_hint().exact(), Some(0));\n\n        let bytes_body = Body::reusable(\"abc\".into());\n        assert!(!bytes_body.is_end_stream());\n        assert_eq!(bytes_body.size_hint().exact(), Some(3));\n\n        // can delegate even when wrapped\n        let stream_body = Body::wrap(empty_body);\n        assert!(stream_body.is_end_stream());\n        assert_eq!(stream_body.size_hint().exact(), Some(0));\n    }\n}\n"
  },
  {
    "path": "src/async_impl/client.rs",
    "content": "#[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\nuse std::any::Any;\nuse std::future::Future;\nuse std::net::IpAddr;\nuse std::pin::Pin;\nuse std::sync::Arc;\nuse std::task::{ready, Context, Poll};\nuse std::time::Duration;\nuse std::{collections::HashMap, convert::TryInto, net::SocketAddr};\nuse std::{fmt, str};\n\nuse super::request::{Request, RequestBuilder};\nuse super::response::Response;\nuse super::Body;\n#[cfg(feature = \"http3\")]\nuse crate::async_impl::h3_client::connect::{H3ClientConfig, H3Connector};\n#[cfg(feature = \"http3\")]\nuse crate::async_impl::h3_client::H3Client;\nuse crate::config::{RequestConfig, TotalTimeout};\n#[cfg(unix)]\nuse crate::connect::uds::UnixSocketProvider;\n#[cfg(target_os = \"windows\")]\nuse crate::connect::windows_named_pipe::WindowsNamedPipeProvider;\nuse crate::connect::{\n    sealed::{Conn, Unnameable},\n    BoxedConnectorLayer, BoxedConnectorService, Connector, ConnectorBuilder,\n};\n#[cfg(feature = \"cookies\")]\nuse crate::cookie;\n#[cfg(feature = \"cookies\")]\nuse crate::cookie::service::CookieService;\n#[cfg(feature = \"hickory-dns\")]\nuse crate::dns::hickory::HickoryDnsResolver;\nuse crate::dns::{gai::GaiResolver, DnsResolverWithOverrides, DynResolver, Resolve};\nuse crate::error::{self, BoxError};\nuse crate::into_url::try_uri;\nuse crate::proxy::Matcher as ProxyMatcher;\nuse crate::redirect::{self, TowerRedirectPolicy};\n#[cfg(feature = \"__rustls\")]\nuse crate::tls::CertificateRevocationList;\n#[cfg(feature = \"__tls\")]\nuse crate::tls::{self, TlsBackend};\n#[cfg(feature = \"__tls\")]\nuse crate::Certificate;\n#[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\nuse crate::Identity;\nuse crate::{IntoUrl, Method, Proxy, Url};\n\nuse http::header::{Entry, HeaderMap, HeaderValue, ACCEPT, PROXY_AUTHORIZATION, USER_AGENT};\nuse http::uri::Scheme;\nuse http::Uri;\nuse hyper_util::client::legacy::connect::HttpConnector;\n#[cfg(feature = \"__native-tls\")]\nuse native_tls_crate::TlsConnector;\nuse pin_project_lite::pin_project;\n#[cfg(feature = \"http3\")]\nuse quinn::TransportConfig;\n#[cfg(feature = \"http3\")]\nuse quinn::VarInt;\nuse tokio::time::Sleep;\nuse tower::util::BoxCloneSyncServiceLayer;\nuse tower::{Layer, Service};\n#[cfg(any(\n    feature = \"gzip\",\n    feature = \"brotli\",\n    feature = \"zstd\",\n    feature = \"deflate\"\n))]\nuse tower_http::decompression::Decompression;\nuse tower_http::follow_redirect::FollowRedirect;\n\n/// An asynchronous `Client` to make Requests with.\n///\n/// The Client has various configuration values to tweak, but the defaults\n/// are set to what is usually the most commonly desired value. To configure a\n/// `Client`, use `Client::builder()`.\n///\n/// The `Client` holds a connection pool internally to improve performance\n/// by reusing connections and avoiding setup overhead, so it is advised that\n/// you create one and **reuse** it.\n///\n/// You do **not** have to wrap the `Client` in an [`Rc`] or [`Arc`] to **reuse** it,\n/// because it already uses an [`Arc`] internally.\n///\n/// # Connection Pooling\n///\n/// The connection pool can be configured using [`ClientBuilder`] methods\n/// with the `pool_` prefix, such as [`ClientBuilder::pool_idle_timeout`]\n/// and [`ClientBuilder::pool_max_idle_per_host`].\n///\n/// [`Rc`]: std::rc::Rc\n#[derive(Clone)]\npub struct Client {\n    inner: Arc<ClientRef>,\n}\n\n/// A `ClientBuilder` can be used to create a `Client` with custom configuration.\n#[must_use]\npub struct ClientBuilder {\n    config: Config,\n}\n\nenum HttpVersionPref {\n    Http1,\n    #[cfg(feature = \"http2\")]\n    Http2,\n    #[cfg(feature = \"http3\")]\n    Http3,\n    All,\n}\n\n#[derive(Clone, Copy, Debug)]\nstruct Accepts {\n    #[cfg(feature = \"gzip\")]\n    gzip: bool,\n    #[cfg(feature = \"brotli\")]\n    brotli: bool,\n    #[cfg(feature = \"zstd\")]\n    zstd: bool,\n    #[cfg(feature = \"deflate\")]\n    deflate: bool,\n}\n\nimpl Default for Accepts {\n    fn default() -> Accepts {\n        Accepts {\n            #[cfg(feature = \"gzip\")]\n            gzip: true,\n            #[cfg(feature = \"brotli\")]\n            brotli: true,\n            #[cfg(feature = \"zstd\")]\n            zstd: true,\n            #[cfg(feature = \"deflate\")]\n            deflate: true,\n        }\n    }\n}\n\n#[derive(Clone)]\nstruct HyperService {\n    hyper: HyperClient,\n}\n\nimpl Service<hyper::Request<crate::async_impl::body::Body>> for HyperService {\n    type Error = crate::Error;\n    type Response = http::Response<hyper::body::Incoming>;\n    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + Sync>>;\n\n    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.hyper.poll_ready(cx).map_err(crate::error::request)\n    }\n\n    fn call(&mut self, req: hyper::Request<crate::async_impl::body::Body>) -> Self::Future {\n        let clone = self.hyper.clone();\n        let mut inner = std::mem::replace(&mut self.hyper, clone);\n        Box::pin(async move { inner.call(req).await.map_err(crate::error::request) })\n    }\n}\n\nstruct Config {\n    // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder`\n    accepts: Accepts,\n    headers: HeaderMap,\n    #[cfg(feature = \"__tls\")]\n    hostname_verification: bool,\n    #[cfg(feature = \"__tls\")]\n    certs_verification: bool,\n    #[cfg(feature = \"__tls\")]\n    tls_sni: bool,\n    connect_timeout: Option<Duration>,\n    connection_verbose: bool,\n    pool_idle_timeout: Option<Duration>,\n    pool_max_idle_per_host: usize,\n    tcp_keepalive: Option<Duration>,\n    tcp_keepalive_interval: Option<Duration>,\n    tcp_keepalive_retries: Option<u32>,\n    #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n    tcp_user_timeout: Option<Duration>,\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\n    identity: Option<Identity>,\n    proxies: Vec<ProxyMatcher>,\n    auto_sys_proxy: bool,\n    redirect_policy: redirect::Policy,\n    retry_policy: crate::retry::Builder,\n    referer: bool,\n    read_timeout: Option<Duration>,\n    timeout: Option<Duration>,\n    #[cfg(feature = \"__tls\")]\n    root_certs: Vec<Certificate>,\n    #[cfg(feature = \"__tls\")]\n    tls_certs_only: bool,\n    #[cfg(feature = \"__rustls\")]\n    crls: Vec<CertificateRevocationList>,\n    #[cfg(feature = \"__tls\")]\n    min_tls_version: Option<tls::Version>,\n    #[cfg(feature = \"__tls\")]\n    max_tls_version: Option<tls::Version>,\n    #[cfg(feature = \"__tls\")]\n    tls_info: bool,\n    #[cfg(feature = \"__tls\")]\n    tls: TlsBackend,\n    connector_layers: Vec<BoxedConnectorLayer>,\n    http_version_pref: HttpVersionPref,\n    http09_responses: bool,\n    http1_title_case_headers: bool,\n    http1_allow_obsolete_multiline_headers_in_responses: bool,\n    http1_ignore_invalid_headers_in_responses: bool,\n    http1_allow_spaces_after_header_name_in_responses: bool,\n    #[cfg(feature = \"http2\")]\n    http2_initial_stream_window_size: Option<u32>,\n    #[cfg(feature = \"http2\")]\n    http2_initial_connection_window_size: Option<u32>,\n    #[cfg(feature = \"http2\")]\n    http2_adaptive_window: bool,\n    #[cfg(feature = \"http2\")]\n    http2_max_frame_size: Option<u32>,\n    #[cfg(feature = \"http2\")]\n    http2_max_header_list_size: Option<u32>,\n    #[cfg(feature = \"http2\")]\n    http2_keep_alive_interval: Option<Duration>,\n    #[cfg(feature = \"http2\")]\n    http2_keep_alive_timeout: Option<Duration>,\n    #[cfg(feature = \"http2\")]\n    http2_keep_alive_while_idle: bool,\n    local_address: Option<IpAddr>,\n    #[cfg(any(\n        target_os = \"android\",\n        target_os = \"fuchsia\",\n        target_os = \"illumos\",\n        target_os = \"ios\",\n        target_os = \"linux\",\n        target_os = \"macos\",\n        target_os = \"solaris\",\n        target_os = \"tvos\",\n        target_os = \"visionos\",\n        target_os = \"watchos\",\n    ))]\n    interface: Option<String>,\n    nodelay: bool,\n    #[cfg(feature = \"cookies\")]\n    cookie_store: Option<Arc<dyn cookie::CookieStore>>,\n    hickory_dns: bool,\n    error: Option<crate::Error>,\n    https_only: bool,\n    #[cfg(feature = \"http3\")]\n    tls_enable_early_data: bool,\n    #[cfg(feature = \"http3\")]\n    quic_max_idle_timeout: Option<Duration>,\n    #[cfg(feature = \"http3\")]\n    quic_stream_receive_window: Option<VarInt>,\n    #[cfg(feature = \"http3\")]\n    quic_receive_window: Option<VarInt>,\n    #[cfg(feature = \"http3\")]\n    quic_send_window: Option<u64>,\n    #[cfg(feature = \"http3\")]\n    quic_congestion_bbr: bool,\n    #[cfg(feature = \"http3\")]\n    h3_max_field_section_size: Option<u64>,\n    #[cfg(feature = \"http3\")]\n    h3_send_grease: Option<bool>,\n    dns_overrides: HashMap<String, Vec<SocketAddr>>,\n    dns_resolver: Option<Arc<dyn Resolve>>,\n\n    #[cfg(unix)]\n    unix_socket: Option<Arc<std::path::Path>>,\n    #[cfg(target_os = \"windows\")]\n    windows_named_pipe: Option<Arc<std::ffi::OsStr>>,\n}\n\nimpl Default for ClientBuilder {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl ClientBuilder {\n    /// Constructs a new `ClientBuilder`.\n    ///\n    /// This is the same as `Client::builder()`.\n    pub fn new() -> Self {\n        let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);\n        headers.insert(ACCEPT, HeaderValue::from_static(\"*/*\"));\n\n        ClientBuilder {\n            config: Config {\n                error: None,\n                accepts: Accepts::default(),\n                headers,\n                #[cfg(feature = \"__tls\")]\n                hostname_verification: true,\n                #[cfg(feature = \"__tls\")]\n                certs_verification: true,\n                #[cfg(feature = \"__tls\")]\n                tls_sni: true,\n                connect_timeout: None,\n                connection_verbose: false,\n                pool_idle_timeout: Some(Duration::from_secs(90)),\n                pool_max_idle_per_host: usize::MAX,\n                tcp_keepalive: Some(Duration::from_secs(15)),\n                tcp_keepalive_interval: Some(Duration::from_secs(15)),\n                tcp_keepalive_retries: Some(3),\n                #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n                tcp_user_timeout: Some(Duration::from_secs(30)),\n                proxies: Vec::new(),\n                auto_sys_proxy: true,\n                redirect_policy: redirect::Policy::default(),\n                retry_policy: crate::retry::Builder::default(),\n                referer: true,\n                read_timeout: None,\n                timeout: None,\n                #[cfg(feature = \"__tls\")]\n                root_certs: Vec::new(),\n                #[cfg(feature = \"__tls\")]\n                tls_certs_only: false,\n                #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\n                identity: None,\n                #[cfg(feature = \"__rustls\")]\n                crls: vec![],\n                #[cfg(feature = \"__tls\")]\n                min_tls_version: None,\n                #[cfg(feature = \"__tls\")]\n                max_tls_version: None,\n                #[cfg(feature = \"__tls\")]\n                tls_info: false,\n                #[cfg(feature = \"__tls\")]\n                tls: TlsBackend::default(),\n                connector_layers: Vec::new(),\n                http_version_pref: HttpVersionPref::All,\n                http09_responses: false,\n                http1_title_case_headers: false,\n                http1_allow_obsolete_multiline_headers_in_responses: false,\n                http1_ignore_invalid_headers_in_responses: false,\n                http1_allow_spaces_after_header_name_in_responses: false,\n                #[cfg(feature = \"http2\")]\n                http2_initial_stream_window_size: None,\n                #[cfg(feature = \"http2\")]\n                http2_initial_connection_window_size: None,\n                #[cfg(feature = \"http2\")]\n                http2_adaptive_window: false,\n                #[cfg(feature = \"http2\")]\n                http2_max_frame_size: None,\n                #[cfg(feature = \"http2\")]\n                http2_max_header_list_size: None,\n                #[cfg(feature = \"http2\")]\n                http2_keep_alive_interval: None,\n                #[cfg(feature = \"http2\")]\n                http2_keep_alive_timeout: None,\n                #[cfg(feature = \"http2\")]\n                http2_keep_alive_while_idle: false,\n                local_address: None,\n                #[cfg(any(\n                    target_os = \"android\",\n                    target_os = \"fuchsia\",\n                    target_os = \"illumos\",\n                    target_os = \"ios\",\n                    target_os = \"linux\",\n                    target_os = \"macos\",\n                    target_os = \"solaris\",\n                    target_os = \"tvos\",\n                    target_os = \"visionos\",\n                    target_os = \"watchos\",\n                ))]\n                interface: None,\n                nodelay: true,\n                hickory_dns: cfg!(feature = \"hickory-dns\"),\n                #[cfg(feature = \"cookies\")]\n                cookie_store: None,\n                https_only: false,\n                dns_overrides: HashMap::new(),\n                #[cfg(feature = \"http3\")]\n                tls_enable_early_data: false,\n                #[cfg(feature = \"http3\")]\n                quic_max_idle_timeout: None,\n                #[cfg(feature = \"http3\")]\n                quic_stream_receive_window: None,\n                #[cfg(feature = \"http3\")]\n                quic_receive_window: None,\n                #[cfg(feature = \"http3\")]\n                quic_send_window: None,\n                #[cfg(feature = \"http3\")]\n                quic_congestion_bbr: false,\n                #[cfg(feature = \"http3\")]\n                h3_max_field_section_size: None,\n                #[cfg(feature = \"http3\")]\n                h3_send_grease: None,\n                dns_resolver: None,\n                #[cfg(unix)]\n                unix_socket: None,\n                #[cfg(target_os = \"windows\")]\n                windows_named_pipe: None,\n            },\n        }\n    }\n}\n\nimpl ClientBuilder {\n    /// Returns a `Client` that uses this `ClientBuilder` configuration.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if a TLS backend cannot be initialized, or the resolver\n    /// cannot load the system configuration.\n    pub fn build(self) -> crate::Result<Client> {\n        let config = self.config;\n\n        if let Some(err) = config.error {\n            return Err(err);\n        }\n\n        let mut proxies = config.proxies;\n        if config.auto_sys_proxy {\n            proxies.push(ProxyMatcher::system());\n        }\n        let proxies = Arc::new(proxies);\n\n        #[allow(unused)]\n        #[cfg(feature = \"http3\")]\n        let mut h3_connector = None;\n\n        let resolver = {\n            let mut resolver: Arc<dyn Resolve> = match config.hickory_dns {\n                false => Arc::new(GaiResolver::new()),\n                #[cfg(feature = \"hickory-dns\")]\n                true => Arc::new(HickoryDnsResolver::default()),\n                #[cfg(not(feature = \"hickory-dns\"))]\n                true => unreachable!(\"hickory-dns shouldn't be enabled unless the feature is\"),\n            };\n            if let Some(dns_resolver) = config.dns_resolver {\n                resolver = dns_resolver;\n            }\n            if !config.dns_overrides.is_empty() {\n                resolver = Arc::new(DnsResolverWithOverrides::new(\n                    resolver,\n                    config.dns_overrides,\n                ));\n            }\n            DynResolver::new(resolver)\n        };\n\n        let mut connector_builder = {\n            #[cfg(feature = \"__tls\")]\n            fn user_agent(headers: &HeaderMap) -> Option<HeaderValue> {\n                headers.get(USER_AGENT).cloned()\n            }\n\n            let mut http = HttpConnector::new_with_resolver(resolver.clone());\n            http.set_connect_timeout(config.connect_timeout);\n\n            #[cfg(all(feature = \"http3\", feature = \"__rustls\"))]\n            let build_h3_connector =\n                |resolver,\n                 tls,\n                 quic_max_idle_timeout: Option<Duration>,\n                 quic_stream_receive_window,\n                 quic_receive_window,\n                 quic_send_window,\n                 quic_congestion_bbr,\n                 h3_max_field_section_size,\n                 h3_send_grease,\n                 local_address,\n                 http_version_pref: &HttpVersionPref| {\n                    let mut transport_config = TransportConfig::default();\n\n                    if let Some(max_idle_timeout) = quic_max_idle_timeout {\n                        transport_config.max_idle_timeout(Some(\n                            max_idle_timeout.try_into().map_err(error::builder)?,\n                        ));\n                    }\n\n                    if let Some(stream_receive_window) = quic_stream_receive_window {\n                        transport_config.stream_receive_window(stream_receive_window);\n                    }\n\n                    if let Some(receive_window) = quic_receive_window {\n                        transport_config.receive_window(receive_window);\n                    }\n\n                    if let Some(send_window) = quic_send_window {\n                        transport_config.send_window(send_window);\n                    }\n\n                    if quic_congestion_bbr {\n                        let factory = Arc::new(quinn::congestion::BbrConfig::default());\n                        transport_config.congestion_controller_factory(factory);\n                    }\n\n                    let mut h3_client_config = H3ClientConfig::default();\n\n                    if let Some(max_field_section_size) = h3_max_field_section_size {\n                        h3_client_config.max_field_section_size = Some(max_field_section_size);\n                    }\n\n                    if let Some(send_grease) = h3_send_grease {\n                        h3_client_config.send_grease = Some(send_grease);\n                    }\n\n                    let res = H3Connector::new(\n                        resolver,\n                        tls,\n                        local_address,\n                        transport_config,\n                        h3_client_config,\n                    );\n\n                    match res {\n                        Ok(connector) => Ok(Some(connector)),\n                        Err(err) => {\n                            if let HttpVersionPref::Http3 = http_version_pref {\n                                Err(error::builder(err))\n                            } else {\n                                Ok(None)\n                            }\n                        }\n                    }\n                };\n\n            #[cfg(feature = \"__tls\")]\n            match config.tls {\n                #[cfg(feature = \"__native-tls\")]\n                TlsBackend::NativeTls => {\n                    let mut tls = TlsConnector::builder();\n\n                    #[cfg(all(feature = \"__native-tls-alpn\", not(feature = \"http3\")))]\n                    {\n                        match config.http_version_pref {\n                            HttpVersionPref::Http1 => {\n                                tls.request_alpns(&[\"http/1.1\"]);\n                            }\n                            #[cfg(feature = \"http2\")]\n                            HttpVersionPref::Http2 => {\n                                tls.request_alpns(&[\"h2\"]);\n                            }\n                            HttpVersionPref::All => {\n                                tls.request_alpns(&[\n                                    #[cfg(feature = \"http2\")]\n                                    \"h2\",\n                                    \"http/1.1\",\n                                ]);\n                            }\n                        }\n                    }\n\n                    tls.danger_accept_invalid_hostnames(!config.hostname_verification);\n\n                    tls.danger_accept_invalid_certs(!config.certs_verification);\n\n                    tls.use_sni(config.tls_sni);\n\n                    tls.disable_built_in_roots(config.tls_certs_only);\n\n                    for cert in config.root_certs {\n                        cert.add_to_native_tls(&mut tls);\n                    }\n\n                    #[cfg(feature = \"__native-tls\")]\n                    {\n                        if let Some(id) = config.identity {\n                            id.add_to_native_tls(&mut tls)?;\n                        }\n                    }\n                    #[cfg(all(feature = \"__rustls\", not(feature = \"__native-tls\")))]\n                    {\n                        // Default backend + rustls Identity doesn't work.\n                        if let Some(_id) = config.identity {\n                            return Err(crate::error::builder(\"incompatible TLS identity type\"));\n                        }\n                    }\n\n                    if let Some(min_tls_version) = config.min_tls_version {\n                        let protocol = min_tls_version.to_native_tls().ok_or_else(|| {\n                            // TLS v1.3. This would be entirely reasonable,\n                            // native-tls just doesn't support it.\n                            // https://github.com/sfackler/rust-native-tls/issues/140\n                            crate::error::builder(\"invalid minimum TLS version for backend\")\n                        })?;\n                        tls.min_protocol_version(Some(protocol));\n                    }\n\n                    if let Some(max_tls_version) = config.max_tls_version {\n                        let protocol = max_tls_version.to_native_tls().ok_or_else(|| {\n                            // TLS v1.3.\n                            // We could arguably do max_protocol_version(None), given\n                            // that 1.4 does not exist yet, but that'd get messy in the\n                            // future.\n                            crate::error::builder(\"invalid maximum TLS version for backend\")\n                        })?;\n                        tls.max_protocol_version(Some(protocol));\n                    }\n\n                    ConnectorBuilder::new_native_tls(\n                        http,\n                        tls,\n                        proxies.clone(),\n                        user_agent(&config.headers),\n                        config.local_address,\n                        #[cfg(any(\n                            target_os = \"android\",\n                            target_os = \"fuchsia\",\n                            target_os = \"illumos\",\n                            target_os = \"ios\",\n                            target_os = \"linux\",\n                            target_os = \"macos\",\n                            target_os = \"solaris\",\n                            target_os = \"tvos\",\n                            target_os = \"visionos\",\n                            target_os = \"watchos\",\n                        ))]\n                        config.interface.as_deref(),\n                        config.nodelay,\n                        config.tls_info,\n                    )?\n                }\n                #[cfg(feature = \"__native-tls\")]\n                TlsBackend::BuiltNativeTls(conn) => ConnectorBuilder::from_built_native_tls(\n                    http,\n                    conn,\n                    proxies.clone(),\n                    user_agent(&config.headers),\n                    config.local_address,\n                    #[cfg(any(\n                        target_os = \"android\",\n                        target_os = \"fuchsia\",\n                        target_os = \"illumos\",\n                        target_os = \"ios\",\n                        target_os = \"linux\",\n                        target_os = \"macos\",\n                        target_os = \"solaris\",\n                        target_os = \"tvos\",\n                        target_os = \"visionos\",\n                        target_os = \"watchos\",\n                    ))]\n                    config.interface.as_deref(),\n                    config.nodelay,\n                    config.tls_info,\n                ),\n                #[cfg(feature = \"__rustls\")]\n                TlsBackend::BuiltRustls(conn) => {\n                    #[cfg(feature = \"http3\")]\n                    {\n                        let mut h3_tls = conn.clone();\n                        h3_tls.alpn_protocols = vec![\"h3\".into()];\n\n                        h3_connector = build_h3_connector(\n                            resolver.clone(),\n                            h3_tls,\n                            config.quic_max_idle_timeout,\n                            config.quic_stream_receive_window,\n                            config.quic_receive_window,\n                            config.quic_send_window,\n                            config.quic_congestion_bbr,\n                            config.h3_max_field_section_size,\n                            config.h3_send_grease,\n                            config.local_address,\n                            &config.http_version_pref,\n                        )?;\n                    }\n\n                    ConnectorBuilder::new_rustls_tls(\n                        http,\n                        conn,\n                        proxies.clone(),\n                        user_agent(&config.headers),\n                        config.local_address,\n                        #[cfg(any(\n                            target_os = \"android\",\n                            target_os = \"fuchsia\",\n                            target_os = \"illumos\",\n                            target_os = \"ios\",\n                            target_os = \"linux\",\n                            target_os = \"macos\",\n                            target_os = \"solaris\",\n                            target_os = \"tvos\",\n                            target_os = \"visionos\",\n                            target_os = \"watchos\",\n                        ))]\n                        config.interface.as_deref(),\n                        config.nodelay,\n                        config.tls_info,\n                    )\n                }\n                #[cfg(feature = \"__rustls\")]\n                TlsBackend::Rustls => {\n                    use crate::tls::{IgnoreHostname, NoVerifier};\n\n                    // Set TLS versions.\n                    let mut versions = rustls::ALL_VERSIONS.to_vec();\n\n                    if let Some(min_tls_version) = config.min_tls_version {\n                        versions.retain(|&supported_version| {\n                            match tls::Version::from_rustls(supported_version.version) {\n                                Some(version) => version >= min_tls_version,\n                                // Assume it's so new we don't know about it, allow it\n                                // (as of writing this is unreachable)\n                                None => true,\n                            }\n                        });\n                    }\n\n                    if let Some(max_tls_version) = config.max_tls_version {\n                        versions.retain(|&supported_version| {\n                            match tls::Version::from_rustls(supported_version.version) {\n                                Some(version) => version <= max_tls_version,\n                                None => false,\n                            }\n                        });\n                    }\n\n                    if versions.is_empty() {\n                        return Err(crate::error::builder(\"empty supported tls versions\"));\n                    }\n\n                    // Allow user to have installed a runtime default.\n                    // If not, we ship with _our_ recommended default.\n                    let provider = rustls::crypto::CryptoProvider::get_default()\n                        .map(|arc| arc.clone())\n                        .unwrap_or_else(default_rustls_crypto_provider);\n\n                    // Build TLS config\n                    let signature_algorithms = provider.signature_verification_algorithms;\n                    let config_builder =\n                        rustls::ClientConfig::builder_with_provider(provider.clone())\n                            .with_protocol_versions(&versions)\n                            .map_err(|_| crate::error::builder(\"invalid TLS versions\"))?;\n\n                    let config_builder = if !config.certs_verification {\n                        config_builder\n                            .dangerous()\n                            .with_custom_certificate_verifier(Arc::new(NoVerifier))\n                    } else if !config.hostname_verification {\n                        if !config.tls_certs_only {\n                            // Should this just warn? Error for now...\n                            return Err(crate::error::builder(\n                                    \"disabling rustls hostname verification only allowed with tls_certs_only()\"\n                            ));\n                        }\n\n                        config_builder\n                            .dangerous()\n                            .with_custom_certificate_verifier(Arc::new(IgnoreHostname::new(\n                                crate::tls::rustls_store(config.root_certs)?,\n                                signature_algorithms,\n                            )))\n                    } else if !config.tls_certs_only {\n                        // Check for some misconfigurations and report them.\n                        if !config.crls.is_empty() {\n                            return Err(crate::error::builder(\n                                \"CRLs only allowed with tls_certs_only()\",\n                            ));\n                        }\n\n                        let verifier = if config.root_certs.is_empty() {\n                            rustls_platform_verifier::Verifier::new(provider.clone())\n                                .map_err(crate::error::builder)?\n                        } else {\n                            #[cfg(any(\n                                all(unix, not(target_os = \"android\")),\n                                target_os = \"windows\"\n                            ))]\n                            {\n                                rustls_platform_verifier::Verifier::new_with_extra_roots(\n                                    crate::tls::rustls_der(config.root_certs)?,\n                                    provider.clone(),\n                                )\n                                .map_err(crate::error::builder)?\n                            }\n\n                            #[cfg(not(any(\n                                all(unix, not(target_os = \"android\")),\n                                target_os = \"windows\"\n                            )))]\n                            return Err(crate::error::builder(\n                                \"rustls-platform-verifier could not load extra certs\",\n                            ));\n                        };\n\n                        config_builder\n                            .dangerous()\n                            .with_custom_certificate_verifier(Arc::new(verifier))\n                    } else {\n                        if config.crls.is_empty() {\n                            config_builder.with_root_certificates(crate::tls::rustls_store(\n                                config.root_certs,\n                            )?)\n                        } else {\n                            let crls = config\n                                .crls\n                                .iter()\n                                .map(|e| e.as_rustls_crl())\n                                .collect::<Vec<_>>();\n                            let verifier =\n                                rustls::client::WebPkiServerVerifier::builder_with_provider(\n                                    Arc::new(crate::tls::rustls_store(config.root_certs)?),\n                                    provider,\n                                )\n                                .with_crls(crls)\n                                .build()\n                                .map_err(|_| {\n                                    crate::error::builder(\"invalid TLS verification settings\")\n                                })?;\n                            config_builder.with_webpki_verifier(verifier)\n                        }\n                    };\n\n                    // Finalize TLS config\n                    let mut tls = if let Some(id) = config.identity {\n                        id.add_to_rustls(config_builder)?\n                    } else {\n                        config_builder.with_no_client_auth()\n                    };\n\n                    tls.enable_sni = config.tls_sni;\n\n                    // ALPN protocol\n                    match config.http_version_pref {\n                        HttpVersionPref::Http1 => {\n                            tls.alpn_protocols = vec![\"http/1.1\".into()];\n                        }\n                        #[cfg(feature = \"http2\")]\n                        HttpVersionPref::Http2 => {\n                            tls.alpn_protocols = vec![\"h2\".into()];\n                        }\n                        #[cfg(feature = \"http3\")]\n                        HttpVersionPref::Http3 => {\n                            // h3 ALPN is not valid over TCP\n                        }\n                        HttpVersionPref::All => {\n                            tls.alpn_protocols = vec![\n                                #[cfg(feature = \"http2\")]\n                                \"h2\".into(),\n                                \"http/1.1\".into(),\n                            ];\n                        }\n                    }\n\n                    #[cfg(feature = \"http3\")]\n                    {\n                        let mut h3_tls = tls.clone();\n                        h3_tls.enable_early_data = config.tls_enable_early_data;\n\n                        // h3 ALPN is required over QUIC for HTTP/3\n                        h3_tls.alpn_protocols = vec![\"h3\".into()];\n\n                        h3_connector = build_h3_connector(\n                            resolver.clone(),\n                            h3_tls,\n                            config.quic_max_idle_timeout,\n                            config.quic_stream_receive_window,\n                            config.quic_receive_window,\n                            config.quic_send_window,\n                            config.quic_congestion_bbr,\n                            config.h3_max_field_section_size,\n                            config.h3_send_grease,\n                            config.local_address,\n                            &config.http_version_pref,\n                        )?;\n                    }\n\n                    ConnectorBuilder::new_rustls_tls(\n                        http,\n                        tls,\n                        proxies.clone(),\n                        user_agent(&config.headers),\n                        config.local_address,\n                        #[cfg(any(\n                            target_os = \"android\",\n                            target_os = \"fuchsia\",\n                            target_os = \"illumos\",\n                            target_os = \"ios\",\n                            target_os = \"linux\",\n                            target_os = \"macos\",\n                            target_os = \"solaris\",\n                            target_os = \"tvos\",\n                            target_os = \"visionos\",\n                            target_os = \"watchos\",\n                        ))]\n                        config.interface.as_deref(),\n                        config.nodelay,\n                        config.tls_info,\n                    )\n                }\n                #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n                TlsBackend::UnknownPreconfigured => {\n                    return Err(crate::error::builder(\n                        \"Unknown TLS backend passed to `use_preconfigured_tls`\",\n                    ));\n                }\n            }\n\n            #[cfg(not(feature = \"__tls\"))]\n            ConnectorBuilder::new(\n                http,\n                proxies.clone(),\n                config.local_address,\n                #[cfg(any(\n                    target_os = \"android\",\n                    target_os = \"fuchsia\",\n                    target_os = \"illumos\",\n                    target_os = \"ios\",\n                    target_os = \"linux\",\n                    target_os = \"macos\",\n                    target_os = \"solaris\",\n                    target_os = \"tvos\",\n                    target_os = \"visionos\",\n                    target_os = \"watchos\",\n                ))]\n                config.interface.as_deref(),\n                config.nodelay,\n            )\n        };\n\n        connector_builder.set_timeout(config.connect_timeout);\n        connector_builder.set_verbose(config.connection_verbose);\n        connector_builder.set_keepalive(config.tcp_keepalive);\n        connector_builder.set_keepalive_interval(config.tcp_keepalive_interval);\n        connector_builder.set_keepalive_retries(config.tcp_keepalive_retries);\n        #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n        connector_builder.set_tcp_user_timeout(config.tcp_user_timeout);\n\n        #[cfg(feature = \"socks\")]\n        connector_builder.set_socks_resolver(resolver);\n\n        // TODO: It'd be best to refactor this so the HttpConnector is never\n        // constructed at all. But there's a lot of code for all the different\n        // ways TLS can be configured...\n        #[cfg(unix)]\n        connector_builder.set_unix_socket(config.unix_socket);\n        #[cfg(target_os = \"windows\")]\n        connector_builder.set_windows_named_pipe(config.windows_named_pipe.clone());\n\n        let mut builder =\n            hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new());\n        #[cfg(feature = \"http2\")]\n        {\n            if matches!(config.http_version_pref, HttpVersionPref::Http2) {\n                builder.http2_only(true);\n            }\n\n            if let Some(http2_initial_stream_window_size) = config.http2_initial_stream_window_size\n            {\n                builder.http2_initial_stream_window_size(http2_initial_stream_window_size);\n            }\n            if let Some(http2_initial_connection_window_size) =\n                config.http2_initial_connection_window_size\n            {\n                builder.http2_initial_connection_window_size(http2_initial_connection_window_size);\n            }\n            if config.http2_adaptive_window {\n                builder.http2_adaptive_window(true);\n            }\n            if let Some(http2_max_frame_size) = config.http2_max_frame_size {\n                builder.http2_max_frame_size(http2_max_frame_size);\n            }\n            if let Some(http2_max_header_list_size) = config.http2_max_header_list_size {\n                builder.http2_max_header_list_size(http2_max_header_list_size);\n            }\n            if let Some(http2_keep_alive_interval) = config.http2_keep_alive_interval {\n                builder.http2_keep_alive_interval(http2_keep_alive_interval);\n            }\n            if let Some(http2_keep_alive_timeout) = config.http2_keep_alive_timeout {\n                builder.http2_keep_alive_timeout(http2_keep_alive_timeout);\n            }\n            if config.http2_keep_alive_while_idle {\n                builder.http2_keep_alive_while_idle(true);\n            }\n        }\n\n        builder.timer(hyper_util::rt::TokioTimer::new());\n        builder.pool_timer(hyper_util::rt::TokioTimer::new());\n        builder.pool_idle_timeout(config.pool_idle_timeout);\n        builder.pool_max_idle_per_host(config.pool_max_idle_per_host);\n\n        if config.http09_responses {\n            builder.http09_responses(true);\n        }\n\n        if config.http1_title_case_headers {\n            builder.http1_title_case_headers(true);\n        }\n\n        if config.http1_allow_obsolete_multiline_headers_in_responses {\n            builder.http1_allow_obsolete_multiline_headers_in_responses(true);\n        }\n\n        if config.http1_ignore_invalid_headers_in_responses {\n            builder.http1_ignore_invalid_headers_in_responses(true);\n        }\n\n        if config.http1_allow_spaces_after_header_name_in_responses {\n            builder.http1_allow_spaces_after_header_name_in_responses(true);\n        }\n\n        let proxies_maybe_http_auth = proxies.iter().any(|p| p.maybe_has_http_auth());\n        let proxies_maybe_http_custom_headers =\n            proxies.iter().any(|p| p.maybe_has_http_custom_headers());\n\n        let redirect_policy_desc = if config.redirect_policy.is_default() {\n            None\n        } else {\n            Some(format!(\"{:?}\", &config.redirect_policy))\n        };\n\n        let hyper_client = builder.build(connector_builder.build(config.connector_layers));\n        let hyper_service = HyperService {\n            hyper: hyper_client,\n        };\n\n        let redirect_policy = {\n            let mut p = TowerRedirectPolicy::new(config.redirect_policy);\n            p.with_referer(config.referer)\n                .with_https_only(config.https_only);\n            p\n        };\n\n        let retry_policy = config.retry_policy.into_policy();\n\n        let svc = tower::retry::Retry::new(retry_policy.clone(), hyper_service);\n\n        #[cfg(feature = \"cookies\")]\n        let svc = CookieService::new(svc, config.cookie_store.clone());\n        let hyper = FollowRedirect::with_policy(svc, redirect_policy.clone());\n        #[cfg(any(\n            feature = \"gzip\",\n            feature = \"brotli\",\n            feature = \"zstd\",\n            feature = \"deflate\"\n        ))]\n        let hyper = Decompression::new(hyper)\n            // set everything to NO, in case tower-http has it enabled but\n            // reqwest does not. then set to config value if cfg allows.\n            .no_gzip()\n            .no_deflate()\n            .no_br()\n            .no_zstd();\n        #[cfg(feature = \"gzip\")]\n        let hyper = hyper.gzip(config.accepts.gzip);\n        #[cfg(feature = \"brotli\")]\n        let hyper = hyper.br(config.accepts.brotli);\n        #[cfg(feature = \"zstd\")]\n        let hyper = hyper.zstd(config.accepts.zstd);\n        #[cfg(feature = \"deflate\")]\n        let hyper = hyper.deflate(config.accepts.deflate);\n\n        Ok(Client {\n            inner: Arc::new(ClientRef {\n                accepts: config.accepts,\n                #[cfg(feature = \"cookies\")]\n                cookie_store: config.cookie_store.clone(),\n                // Use match instead of map since config is partially moved,\n                // and it cannot be used in closure\n                #[cfg(feature = \"http3\")]\n                h3_client: match h3_connector {\n                    Some(h3_connector) => {\n                        let h3_service = H3Client::new(h3_connector, config.pool_idle_timeout);\n                        let svc = tower::retry::Retry::new(retry_policy, h3_service);\n                        #[cfg(feature = \"cookies\")]\n                        let svc = CookieService::new(svc, config.cookie_store);\n                        let svc = FollowRedirect::with_policy(svc, redirect_policy);\n                        #[cfg(any(\n                            feature = \"gzip\",\n                            feature = \"brotli\",\n                            feature = \"zstd\",\n                            feature = \"deflate\"\n                        ))]\n                        let svc = Decompression::new(svc)\n                            // set everything to NO, in case tower-http has it enabled but\n                            // reqwest does not. then set to config value if cfg allows.\n                            .no_gzip()\n                            .no_deflate()\n                            .no_br()\n                            .no_zstd();\n                        #[cfg(feature = \"gzip\")]\n                        let svc = svc.gzip(config.accepts.gzip);\n                        #[cfg(feature = \"brotli\")]\n                        let svc = svc.br(config.accepts.brotli);\n                        #[cfg(feature = \"zstd\")]\n                        let svc = svc.zstd(config.accepts.zstd);\n                        #[cfg(feature = \"deflate\")]\n                        let svc = svc.deflate(config.accepts.deflate);\n                        Some(svc)\n                    }\n                    None => None,\n                },\n                headers: config.headers,\n                referer: config.referer,\n                read_timeout: config.read_timeout,\n                total_timeout: RequestConfig::new(config.timeout),\n                hyper,\n                proxies,\n                proxies_maybe_http_auth,\n                proxies_maybe_http_custom_headers,\n                https_only: config.https_only,\n                redirect_policy_desc,\n            }),\n        })\n    }\n\n    // Higher-level options\n\n    /// Sets the `User-Agent` header to be used by this client.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # async fn doc() -> Result<(), reqwest::Error> {\n    /// // Name your user agent after your app?\n    /// static APP_USER_AGENT: &str = concat!(\n    ///     env!(\"CARGO_PKG_NAME\"),\n    ///     \"/\",\n    ///     env!(\"CARGO_PKG_VERSION\"),\n    /// );\n    ///\n    /// let client = reqwest::Client::builder()\n    ///     .user_agent(APP_USER_AGENT)\n    ///     .build()?;\n    /// let res = client.get(\"https://www.rust-lang.org\").send().await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn user_agent<V>(mut self, value: V) -> ClientBuilder\n    where\n        V: TryInto<HeaderValue>,\n        V::Error: Into<http::Error>,\n    {\n        match value.try_into() {\n            Ok(value) => {\n                self.config.headers.insert(USER_AGENT, value);\n            }\n            Err(e) => {\n                self.config.error = Some(crate::error::builder(e.into()));\n            }\n        };\n        self\n    }\n    /// Sets the default headers for every request.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use reqwest::header;\n    /// # async fn doc() -> Result<(), reqwest::Error> {\n    /// let mut headers = header::HeaderMap::new();\n    /// headers.insert(\"X-MY-HEADER\", header::HeaderValue::from_static(\"value\"));\n    ///\n    /// // Consider marking security-sensitive headers with `set_sensitive`.\n    /// let mut auth_value = header::HeaderValue::from_static(\"secret\");\n    /// auth_value.set_sensitive(true);\n    /// headers.insert(header::AUTHORIZATION, auth_value);\n    ///\n    /// // get a client builder\n    /// let client = reqwest::Client::builder()\n    ///     .default_headers(headers)\n    ///     .build()?;\n    /// let res = client.get(\"https://www.rust-lang.org\").send().await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn default_headers(mut self, headers: HeaderMap) -> ClientBuilder {\n        for (key, value) in headers.iter() {\n            self.config.headers.insert(key, value.clone());\n        }\n        self\n    }\n\n    /// Enable a persistent cookie store for the client.\n    ///\n    /// Cookies received in responses will be preserved and included in\n    /// additional requests.\n    ///\n    /// By default, no cookie store is used. Enabling the cookie store\n    /// with `cookie_store(true)` will set the store to a default implementation.\n    /// It is **not** necessary to call [cookie_store(true)](crate::ClientBuilder::cookie_store) if [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider)\n    /// is used; calling [cookie_store(true)](crate::ClientBuilder::cookie_store) _after_ [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) will result\n    /// in the provided `my_cookie_store` being **overridden** with a default implementation.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookie_store(mut self, enable: bool) -> ClientBuilder {\n        if enable {\n            self.cookie_provider(Arc::new(cookie::Jar::default()))\n        } else {\n            self.config.cookie_store = None;\n            self\n        }\n    }\n\n    /// Set the persistent cookie store for the client.\n    ///\n    /// Cookies received in responses will be passed to this store, and\n    /// additional requests will query this store for cookies.\n    ///\n    /// By default, no cookie store is used. It is **not** necessary to also call\n    /// [cookie_store(true)](crate::ClientBuilder::cookie_store) if [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) is used; calling\n    /// [cookie_store(true)](crate::ClientBuilder::cookie_store) _after_ [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) will result\n    /// in the provided `my_cookie_store` being **overridden** with a default implementation.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookie_provider<C: cookie::CookieStore + 'static>(\n        mut self,\n        cookie_store: Arc<C>,\n    ) -> ClientBuilder {\n        self.config.cookie_store = Some(cookie_store as _);\n        self\n    }\n\n    /// Enable auto gzip decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto gzip decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `gzip`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if its headers contain a `Content-Encoding` value of\n    ///   `gzip`, both `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `gzip` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `gzip` feature to be enabled\n    #[cfg(feature = \"gzip\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"gzip\")))]\n    pub fn gzip(mut self, enable: bool) -> ClientBuilder {\n        self.config.accepts.gzip = enable;\n        self\n    }\n\n    /// Enable auto brotli decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto brotli decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `br`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if its headers contain a `Content-Encoding` value of\n    ///   `br`, both `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `brotli` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `brotli` feature to be enabled\n    #[cfg(feature = \"brotli\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"brotli\")))]\n    pub fn brotli(mut self, enable: bool) -> ClientBuilder {\n        self.config.accepts.brotli = enable;\n        self\n    }\n\n    /// Enable auto zstd decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto zstd decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `zstd`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if its headers contain a `Content-Encoding` value of\n    ///   `zstd`, both `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `zstd` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `zstd` feature to be enabled\n    #[cfg(feature = \"zstd\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"zstd\")))]\n    pub fn zstd(mut self, enable: bool) -> ClientBuilder {\n        self.config.accepts.zstd = enable;\n        self\n    }\n\n    /// Enable auto deflate decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto deflate decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `deflate`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that\n    ///   equals to `deflate`, both values `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `deflate` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `deflate` feature to be enabled\n    #[cfg(feature = \"deflate\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"deflate\")))]\n    pub fn deflate(mut self, enable: bool) -> ClientBuilder {\n        self.config.accepts.deflate = enable;\n        self\n    }\n\n    /// Disable auto response body gzip decompression.\n    ///\n    /// This method exists even if the optional `gzip` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use gzip decompression\n    /// even if another dependency were to enable the optional `gzip` feature.\n    pub fn no_gzip(self) -> ClientBuilder {\n        #[cfg(feature = \"gzip\")]\n        {\n            self.gzip(false)\n        }\n\n        #[cfg(not(feature = \"gzip\"))]\n        {\n            self\n        }\n    }\n\n    /// Disable auto response body brotli decompression.\n    ///\n    /// This method exists even if the optional `brotli` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use brotli decompression\n    /// even if another dependency were to enable the optional `brotli` feature.\n    pub fn no_brotli(self) -> ClientBuilder {\n        #[cfg(feature = \"brotli\")]\n        {\n            self.brotli(false)\n        }\n\n        #[cfg(not(feature = \"brotli\"))]\n        {\n            self\n        }\n    }\n\n    /// Disable auto response body zstd decompression.\n    ///\n    /// This method exists even if the optional `zstd` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use zstd decompression\n    /// even if another dependency were to enable the optional `zstd` feature.\n    pub fn no_zstd(self) -> ClientBuilder {\n        #[cfg(feature = \"zstd\")]\n        {\n            self.zstd(false)\n        }\n\n        #[cfg(not(feature = \"zstd\"))]\n        {\n            self\n        }\n    }\n\n    /// Disable auto response body deflate decompression.\n    ///\n    /// This method exists even if the optional `deflate` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use deflate decompression\n    /// even if another dependency were to enable the optional `deflate` feature.\n    pub fn no_deflate(self) -> ClientBuilder {\n        #[cfg(feature = \"deflate\")]\n        {\n            self.deflate(false)\n        }\n\n        #[cfg(not(feature = \"deflate\"))]\n        {\n            self\n        }\n    }\n\n    // Redirect options\n\n    /// Set a `RedirectPolicy` for this client.\n    ///\n    /// Default will follow redirects up to a maximum of 10.\n    pub fn redirect(mut self, policy: redirect::Policy) -> ClientBuilder {\n        self.config.redirect_policy = policy;\n        self\n    }\n\n    /// Enable or disable automatic setting of the `Referer` header.\n    ///\n    /// Default is `true`.\n    pub fn referer(mut self, enable: bool) -> ClientBuilder {\n        self.config.referer = enable;\n        self\n    }\n\n    // Retry options\n\n    /// Set a request retry policy.\n    ///\n    /// Default behavior is to retry protocol NACKs.\n    // XXX: accept an `impl retry::IntoPolicy` instead?\n    pub fn retry(mut self, policy: crate::retry::Builder) -> ClientBuilder {\n        self.config.retry_policy = policy;\n        self\n    }\n\n    // Proxy options\n\n    /// Add a `Proxy` to the list of proxies the `Client` will use.\n    ///\n    /// # Note\n    ///\n    /// Adding a proxy will disable the automatic usage of the \"system\" proxy.\n    pub fn proxy(mut self, proxy: Proxy) -> ClientBuilder {\n        self.config.proxies.push(proxy.into_matcher());\n        self.config.auto_sys_proxy = false;\n        self\n    }\n\n    /// Clear all `Proxies`, so `Client` will use no proxy anymore.\n    ///\n    /// # Note\n    /// To add a proxy exclusion list, use [crate::proxy::Proxy::no_proxy()]\n    /// on all desired proxies instead.\n    ///\n    /// This also disables the automatic usage of the \"system\" proxy.\n    pub fn no_proxy(mut self) -> ClientBuilder {\n        self.config.proxies.clear();\n        self.config.auto_sys_proxy = false;\n        self\n    }\n\n    // Timeout options\n\n    /// Enables a total request timeout.\n    ///\n    /// The timeout is applied from when the request starts connecting until the\n    /// response body has finished. Also considered a total deadline.\n    ///\n    /// Default is no timeout.\n    pub fn timeout(mut self, timeout: Duration) -> ClientBuilder {\n        self.config.timeout = Some(timeout);\n        self\n    }\n\n    /// Enables a read timeout.\n    ///\n    /// The timeout applies to each read operation, and resets after a\n    /// successful read. This is more appropriate for detecting stalled\n    /// connections when the size isn't known beforehand.\n    ///\n    /// Default is no timeout.\n    pub fn read_timeout(mut self, timeout: Duration) -> ClientBuilder {\n        self.config.read_timeout = Some(timeout);\n        self\n    }\n\n    /// Set a timeout for only the connect phase of a `Client`.\n    ///\n    /// Default is `None`.\n    ///\n    /// # Note\n    ///\n    /// This **requires** the futures be executed in a tokio runtime with\n    /// a tokio timer enabled.\n    pub fn connect_timeout(mut self, timeout: Duration) -> ClientBuilder {\n        self.config.connect_timeout = Some(timeout);\n        self\n    }\n\n    /// Set whether connections should emit verbose logs.\n    ///\n    /// Enabling this option will emit [log][] messages at the `TRACE` level\n    /// for read and write operations on connections.\n    ///\n    /// [log]: https://crates.io/crates/log\n    pub fn connection_verbose(mut self, verbose: bool) -> ClientBuilder {\n        self.config.connection_verbose = verbose;\n        self\n    }\n\n    // HTTP options\n\n    /// Set an optional timeout for idle sockets being kept-alive.\n    ///\n    /// Pass `None` to disable timeout.\n    ///\n    /// Default is 90 seconds.\n    pub fn pool_idle_timeout<D>(mut self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.config.pool_idle_timeout = val.into();\n        self\n    }\n\n    /// Sets the maximum idle connection per host allowed in the pool.\n    ///\n    /// Default is `usize::MAX` (no limit).\n    pub fn pool_max_idle_per_host(mut self, max: usize) -> ClientBuilder {\n        self.config.pool_max_idle_per_host = max;\n        self\n    }\n\n    /// Send headers as title case instead of lowercase.\n    pub fn http1_title_case_headers(mut self) -> ClientBuilder {\n        self.config.http1_title_case_headers = true;\n        self\n    }\n\n    /// Set whether HTTP/1 connections will accept obsolete line folding for\n    /// header values.\n    ///\n    /// Newline codepoints (`\\r` and `\\n`) will be transformed to spaces when\n    /// parsing.\n    pub fn http1_allow_obsolete_multiline_headers_in_responses(\n        mut self,\n        value: bool,\n    ) -> ClientBuilder {\n        self.config\n            .http1_allow_obsolete_multiline_headers_in_responses = value;\n        self\n    }\n\n    /// Sets whether invalid header lines should be silently ignored in HTTP/1 responses.\n    pub fn http1_ignore_invalid_headers_in_responses(mut self, value: bool) -> ClientBuilder {\n        self.config.http1_ignore_invalid_headers_in_responses = value;\n        self\n    }\n\n    /// Set whether HTTP/1 connections will accept spaces between header\n    /// names and the colon that follow them in responses.\n    ///\n    /// Newline codepoints (`\\r` and `\\n`) will be transformed to spaces when\n    /// parsing.\n    pub fn http1_allow_spaces_after_header_name_in_responses(\n        mut self,\n        value: bool,\n    ) -> ClientBuilder {\n        self.config\n            .http1_allow_spaces_after_header_name_in_responses = value;\n        self\n    }\n\n    /// Only use HTTP/1.\n    pub fn http1_only(mut self) -> ClientBuilder {\n        self.config.http_version_pref = HttpVersionPref::Http1;\n        self\n    }\n\n    /// Allow HTTP/0.9 responses\n    pub fn http09_responses(mut self) -> ClientBuilder {\n        self.config.http09_responses = true;\n        self\n    }\n\n    /// Only use HTTP/2.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_prior_knowledge(mut self) -> ClientBuilder {\n        self.config.http_version_pref = HttpVersionPref::Http2;\n        self\n    }\n\n    /// Only use HTTP/3.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_prior_knowledge(mut self) -> ClientBuilder {\n        self.config.http_version_pref = HttpVersionPref::Http3;\n        self\n    }\n\n    /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.\n    ///\n    /// Default is currently 65,535 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_initial_stream_window_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {\n        self.config.http2_initial_stream_window_size = sz.into();\n        self\n    }\n\n    /// Sets the max connection-level flow control for HTTP2\n    ///\n    /// Default is currently 65,535 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_initial_connection_window_size(\n        mut self,\n        sz: impl Into<Option<u32>>,\n    ) -> ClientBuilder {\n        self.config.http2_initial_connection_window_size = sz.into();\n        self\n    }\n\n    /// Sets whether to use an adaptive flow control.\n    ///\n    /// Enabling this will override the limits set in `http2_initial_stream_window_size` and\n    /// `http2_initial_connection_window_size`.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_adaptive_window(mut self, enabled: bool) -> ClientBuilder {\n        self.config.http2_adaptive_window = enabled;\n        self\n    }\n\n    /// Sets the maximum frame size to use for HTTP2.\n    ///\n    /// Default is currently 16,384 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_max_frame_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {\n        self.config.http2_max_frame_size = sz.into();\n        self\n    }\n\n    /// Sets the maximum size of received header frames for HTTP2.\n    ///\n    /// Default is currently 16KB, but can change.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_max_header_list_size(mut self, max_header_size_bytes: u32) -> ClientBuilder {\n        self.config.http2_max_header_list_size = Some(max_header_size_bytes);\n        self\n    }\n\n    /// Sets an interval for HTTP2 Ping frames should be sent to keep a connection alive.\n    ///\n    /// Pass `None` to disable HTTP2 keep-alive.\n    /// Default is currently disabled.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_keep_alive_interval(\n        mut self,\n        interval: impl Into<Option<Duration>>,\n    ) -> ClientBuilder {\n        self.config.http2_keep_alive_interval = interval.into();\n        self\n    }\n\n    /// Sets a timeout for receiving an acknowledgement of the keep-alive ping.\n    ///\n    /// If the ping is not acknowledged within the timeout, the connection will be closed.\n    /// Does nothing if `http2_keep_alive_interval` is disabled.\n    /// Default is currently disabled.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_keep_alive_timeout(mut self, timeout: Duration) -> ClientBuilder {\n        self.config.http2_keep_alive_timeout = Some(timeout);\n        self\n    }\n\n    /// Sets whether HTTP2 keep-alive should apply while the connection is idle.\n    ///\n    /// If disabled, keep-alive pings are only sent while there are open request/responses streams.\n    /// If enabled, pings are also sent when no streams are active.\n    /// Does nothing if `http2_keep_alive_interval` is disabled.\n    /// Default is `false`.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_keep_alive_while_idle(mut self, enabled: bool) -> ClientBuilder {\n        self.config.http2_keep_alive_while_idle = enabled;\n        self\n    }\n\n    // TCP options\n\n    /// Set whether sockets have `TCP_NODELAY` enabled.\n    ///\n    /// Default is `true`.\n    pub fn tcp_nodelay(mut self, enabled: bool) -> ClientBuilder {\n        self.config.nodelay = enabled;\n        self\n    }\n\n    /// Bind to a local IP Address.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # fn doc() -> Result<(), reqwest::Error> {\n    /// use std::net::IpAddr;\n    /// let local_addr = IpAddr::from([12, 4, 1, 8]);\n    /// let client = reqwest::Client::builder()\n    ///     .local_address(local_addr)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn local_address<T>(mut self, addr: T) -> ClientBuilder\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        self.config.local_address = addr.into();\n        self\n    }\n\n    /// Bind connections only on the specified network interface.\n    ///\n    /// This option is only available on the following operating systems:\n    ///\n    /// - Android\n    /// - Fuchsia\n    /// - Linux,\n    /// - macOS and macOS-like systems (iOS, tvOS, watchOS and visionOS)\n    /// - Solaris and illumos\n    ///\n    /// On Android, Linux, and Fuchsia, this uses the\n    /// [`SO_BINDTODEVICE`][man-7-socket] socket option. On macOS and macOS-like\n    /// systems, Solaris, and illumos, this instead uses the [`IP_BOUND_IF` and\n    /// `IPV6_BOUND_IF`][man-7p-ip] socket options (as appropriate).\n    ///\n    /// Note that connections will fail if the provided interface name is not a\n    /// network interface that currently exists when a connection is established.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # fn doc() -> Result<(), reqwest::Error> {\n    /// let interface = \"lo\";\n    /// let client = reqwest::Client::builder()\n    ///     .interface(interface)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// [man-7-socket]: https://man7.org/linux/man-pages/man7/socket.7.html\n    /// [man-7p-ip]: https://docs.oracle.com/cd/E86824_01/html/E54777/ip-7p.html\n    #[cfg(any(\n        target_os = \"android\",\n        target_os = \"fuchsia\",\n        target_os = \"illumos\",\n        target_os = \"ios\",\n        target_os = \"linux\",\n        target_os = \"macos\",\n        target_os = \"solaris\",\n        target_os = \"tvos\",\n        target_os = \"visionos\",\n        target_os = \"watchos\",\n    ))]\n    pub fn interface(mut self, interface: &str) -> ClientBuilder {\n        self.config.interface = Some(interface.to_string());\n        self\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive<D>(mut self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.config.tcp_keepalive = val.into();\n        self\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied interval.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive_interval<D>(mut self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.config.tcp_keepalive_interval = val.into();\n        self\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied retry count.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive_retries<C>(mut self, retries: C) -> ClientBuilder\n    where\n        C: Into<Option<u32>>,\n    {\n        self.config.tcp_keepalive_retries = retries.into();\n        self\n    }\n\n    /// Set that all sockets have `TCP_USER_TIMEOUT` set with the supplied duration.\n    ///\n    /// This option controls how long transmitted data may remain unacknowledged before\n    /// the connection is force-closed.\n    ///\n    /// If `None`, the option will not be set.\n    #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n    pub fn tcp_user_timeout<D>(mut self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.config.tcp_user_timeout = val.into();\n        self\n    }\n\n    // Alt Transports\n\n    /// Set that all connections will use this Unix socket.\n    ///\n    /// If a request URI uses the `https` scheme, TLS will still be used over\n    /// the Unix socket.\n    ///\n    /// # Note\n    ///\n    /// This option is not compatible with any of the TCP or Proxy options.\n    /// Setting this will ignore all those options previously set.\n    ///\n    /// Likewise, DNS resolution will not be done on the domain name.\n    #[cfg(unix)]\n    pub fn unix_socket(mut self, path: impl UnixSocketProvider) -> ClientBuilder {\n        self.config.unix_socket = Some(path.reqwest_uds_path(crate::connect::uds::Internal).into());\n        self\n    }\n\n    /// Set that all connections will use this Windows named pipe.\n    ///\n    /// If a request URI uses the `https` scheme, TLS will still be used over\n    /// the Windows named pipe.\n    ///\n    /// # Note\n    ///\n    /// This option is not compatible with any of the TCP or Proxy options.\n    /// Setting this will ignore all those options previously set.\n    ///\n    /// Likewise, DNS resolution will not be done on the domain name.\n    #[cfg(target_os = \"windows\")]\n    pub fn windows_named_pipe(mut self, pipe: impl WindowsNamedPipeProvider) -> ClientBuilder {\n        self.config.windows_named_pipe = Some(\n            pipe.reqwest_windows_named_pipe_path(crate::connect::windows_named_pipe::Internal)\n                .into(),\n        );\n        self\n    }\n\n    // TLS options\n\n    /// Add custom certificate roots.\n    ///\n    /// This can be used to connect to a server that has a self-signed\n    /// certificate for example.\n    ///\n    /// This optional attempts to merge with any native or built-in roots.\n    ///\n    /// # Errors\n    ///\n    /// If the selected TLS backend or verifier does not support merging\n    /// certificates, the builder will return an error.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_certs_merge(\n        mut self,\n        certs: impl IntoIterator<Item = Certificate>,\n    ) -> ClientBuilder {\n        self.config.root_certs.extend(certs);\n        self\n    }\n\n    /// Use only the provided certificate roots.\n    ///\n    /// This can be used to connect to a server that has a self-signed\n    /// certificate for example.\n    ///\n    /// This option disables any native or built-in roots, and **only** uses\n    /// the roots provided to this method.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_certs_only(mut self, certs: impl IntoIterator<Item = Certificate>) -> ClientBuilder {\n        self.config.root_certs.extend(certs);\n        self.config.tls_certs_only = true;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_certs_merge()`] or\n    /// [`ClientBuilder::tls_certs_only()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {\n        self.config.root_certs.push(cert);\n        self\n    }\n\n    /// Add multiple certificate revocation lists.\n    ///\n    /// # Errors\n    ///\n    /// This only works if also using only provided root certificates. This\n    /// cannot work with the native verifier.\n    ///\n    /// If CRLs are added but `tls_certs_only()` is not called, the builder\n    /// will return an error.\n    ///\n    /// # Optional\n    ///\n    /// This requires the `rustls(-...)` Cargo feature enabled.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn tls_crls_only(\n        mut self,\n        crls: impl IntoIterator<Item = CertificateRevocationList>,\n    ) -> ClientBuilder {\n        self.config.crls.extend(crls);\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn add_crl(mut self, crl: CertificateRevocationList) -> ClientBuilder {\n        self.config.crls.push(crl);\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn add_crls(\n        mut self,\n        crls: impl IntoIterator<Item = CertificateRevocationList>,\n    ) -> ClientBuilder {\n        self.config.crls.extend(crls);\n        self\n    }\n\n    /// Sets the identity to be used for client certificate authentication.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `native-tls` or `rustls(-...)` feature to be\n    /// enabled.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\n    #[cfg_attr(docsrs, doc(cfg(any(feature = \"native-tls\", feature = \"rustls\"))))]\n    pub fn identity(mut self, identity: Identity) -> ClientBuilder {\n        self.config.identity = Some(identity);\n        self\n    }\n\n    /// Controls the use of hostname verification.\n    ///\n    /// Defaults to `false`.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before you use this method. If\n    /// hostname verification is not used, any valid certificate for any\n    /// site will be trusted for use from any other. This introduces a\n    /// significant vulnerability to man-in-the-middle attacks.\n    ///\n    /// # Errors\n    ///\n    /// Depending on the TLS backend and verifier, this might not work with\n    /// native certificates, only those added with [`ClientBuilder::tls_certs_only()`].\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_danger_accept_invalid_hostnames(\n        mut self,\n        accept_invalid_hostname: bool,\n    ) -> ClientBuilder {\n        self.config.hostname_verification = !accept_invalid_hostname;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_hostnames()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder {\n        self.tls_danger_accept_invalid_hostnames(accept_invalid_hostname)\n    }\n\n    /// Controls the use of certificate validation.\n    ///\n    /// Defaults to `false`.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before using this method. If\n    /// invalid certificates are trusted, *any* certificate for *any* site\n    /// will be trusted for use. This includes expired certificates. This\n    /// introduces significant vulnerabilities, and should only be used\n    /// as a last resort.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {\n        self.config.certs_verification = !accept_invalid_certs;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_certs()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {\n        self.tls_danger_accept_invalid_certs(accept_invalid_certs)\n    }\n\n    /// Controls the use of TLS server name indication.\n    ///\n    /// Defaults to `true`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_sni(mut self, tls_sni: bool) -> ClientBuilder {\n        self.config.tls_sni = tls_sni;\n        self\n    }\n\n    /// Set the minimum required TLS version for connections.\n    ///\n    /// By default, the TLS backend's own default is used.\n    ///\n    /// # Errors\n    ///\n    /// A value of `tls::Version::TLS_1_3` will cause an error with the\n    /// `native-tls` backend. This does not mean the version\n    /// isn't supported, just that it can't be set as a minimum due to\n    /// technical limitations.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_version_min(mut self, version: tls::Version) -> ClientBuilder {\n        self.config.min_tls_version = Some(version);\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_version_min()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn min_tls_version(self, version: tls::Version) -> ClientBuilder {\n        self.tls_version_min(version)\n    }\n\n    /// Set the maximum allowed TLS version for connections.\n    ///\n    /// By default, there's no maximum.\n    ///\n    /// # Errors\n    ///\n    /// A value of `tls::Version::TLS_1_3` will cause an error with the\n    /// `native-tls` backend. This does not mean the version\n    /// isn't supported, just that it can't be set as a maximum due to\n    /// technical limitations.\n    ///\n    /// Cannot set a maximum outside the protocol versions supported by\n    /// `rustls` with the `rustls` backend.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_version_max(mut self, version: tls::Version) -> ClientBuilder {\n        self.config.max_tls_version = Some(version);\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_version_max()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn max_tls_version(self, version: tls::Version) -> ClientBuilder {\n        self.tls_version_max(version)\n    }\n\n    /// Force using the native TLS backend.\n    ///\n    /// Since multiple TLS backends can be optionally enabled, this option will\n    /// force the `native-tls` backend to be used for this `Client`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `native-tls` feature to be enabled.\n    #[cfg(feature = \"__native-tls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"native-tls\")))]\n    pub fn tls_backend_native(mut self) -> ClientBuilder {\n        self.config.tls = TlsBackend::NativeTls;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_native()`] instead.\n    #[cfg(feature = \"__native-tls\")]\n    pub fn use_native_tls(self) -> ClientBuilder {\n        self.tls_backend_native()\n    }\n\n    /// Force using the Rustls TLS backend.\n    ///\n    /// Since multiple TLS backends can be optionally enabled, this option will\n    /// force the `rustls` backend to be used for this `Client`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `rustls(-...)` feature to be enabled.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn tls_backend_rustls(mut self) -> ClientBuilder {\n        self.config.tls = TlsBackend::Rustls;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_rustls()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn use_rustls_tls(self) -> ClientBuilder {\n        self.tls_backend_rustls()\n    }\n\n    /// Use a preconfigured TLS backend.\n    ///\n    /// If the passed `Any` argument is not a TLS backend that reqwest\n    /// understands, the `ClientBuilder` will error when calling `build`.\n    ///\n    /// # Advanced\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// There is no semver stability on the internals of this method. Use at\n    /// your own risk.\n    ///\n    /// </div>\n    ///\n    /// This is an advanced option, and can be somewhat brittle. Usage requires\n    /// keeping the preconfigured TLS argument version in sync with reqwest,\n    /// since version mismatches will result in an \"unknown\" TLS backend.\n    ///\n    /// If possible, it's preferable to use the methods on `ClientBuilder`\n    /// to configure reqwest's TLS.\n    ///\n    /// # Optional\n    ///\n    /// This requires one of the optional features `native-tls` or\n    /// `rustls(-...)` to be enabled.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n    #[cfg_attr(docsrs, doc(cfg(any(feature = \"native-tls\", feature = \"rustls\"))))]\n    pub fn tls_backend_preconfigured(mut self, tls: impl Any) -> ClientBuilder {\n        let mut tls = Some(tls);\n        #[cfg(feature = \"__native-tls\")]\n        {\n            if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<TlsConnector>>() {\n                let tls = conn.take().expect(\"is definitely Some\");\n                let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);\n                self.config.tls = tls;\n                return self;\n            }\n        }\n        #[cfg(feature = \"__rustls\")]\n        {\n            if let Some(conn) =\n                (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>()\n            {\n                let tls = conn.take().expect(\"is definitely Some\");\n                let tls = crate::tls::TlsBackend::BuiltRustls(tls);\n                self.config.tls = tls;\n                return self;\n            }\n        }\n\n        // Otherwise, we don't recognize the TLS backend!\n        self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured;\n        self\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_preconfigured()`] instead.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n    pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {\n        self.tls_backend_preconfigured(tls)\n    }\n\n    /// Add TLS information as `TlsInfo` extension to responses.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_info(mut self, tls_info: bool) -> ClientBuilder {\n        self.config.tls_info = tls_info;\n        self\n    }\n\n    /// Restrict the Client to be used with HTTPS only requests.\n    ///\n    /// Defaults to false.\n    pub fn https_only(mut self, enabled: bool) -> ClientBuilder {\n        self.config.https_only = enabled;\n        self\n    }\n\n    /// Enables the [hickory-dns](hickory_resolver) async resolver instead of a default threadpool\n    /// using `getaddrinfo`.\n    ///\n    /// If the `hickory-dns` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `hickory-dns` feature to be enabled\n    ///\n    /// # Warning\n    ///\n    /// The hickory resolver does not work exactly the same, or on all the platforms\n    /// that the default resolver does\n    #[cfg(feature = \"hickory-dns\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"hickory-dns\")))]\n    pub fn hickory_dns(mut self, enable: bool) -> ClientBuilder {\n        self.config.hickory_dns = enable;\n        self\n    }\n\n    /// Disables the hickory-dns async resolver.\n    ///\n    /// This method exists even if the optional `hickory-dns` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use the hickory-dns async resolver\n    /// even if another dependency were to enable the optional `hickory-dns` feature.\n    pub fn no_hickory_dns(self) -> ClientBuilder {\n        #[cfg(feature = \"hickory-dns\")]\n        {\n            self.hickory_dns(false)\n        }\n\n        #[cfg(not(feature = \"hickory-dns\"))]\n        {\n            self\n        }\n    }\n\n    /// Override DNS resolution for specific domains to a particular IP address.\n    ///\n    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).\n    /// Ports in the URL itself will always be used instead of the port in the overridden addr.\n    pub fn resolve(self, domain: &str, addr: SocketAddr) -> ClientBuilder {\n        self.resolve_to_addrs(domain, &[addr])\n    }\n\n    /// Override DNS resolution for specific domains to particular IP addresses.\n    ///\n    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).\n    /// Ports in the URL itself will always be used instead of the port in the overridden addr.\n    pub fn resolve_to_addrs(mut self, domain: &str, addrs: &[SocketAddr]) -> ClientBuilder {\n        self.config\n            .dns_overrides\n            .insert(domain.to_ascii_lowercase(), addrs.to_vec());\n        self\n    }\n\n    /// Override the DNS resolver implementation.\n    ///\n    /// Overrides for specific names passed to `resolve` and `resolve_to_addrs` will\n    /// still be applied on top of this resolver.\n    pub fn dns_resolver<R>(mut self, resolver: R) -> ClientBuilder\n    where\n        R: crate::dns::resolve::IntoResolve,\n    {\n        self.config.dns_resolver = Some(resolver.into_resolve());\n        self\n    }\n\n    /// Whether to send data on the first flight (\"early data\") in TLS 1.3 handshakes\n    /// for HTTP/3 connections.\n    ///\n    /// The default is false.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn tls_early_data(mut self, enabled: bool) -> ClientBuilder {\n        self.config.tls_enable_early_data = enabled;\n        self\n    }\n\n    /// Maximum duration of inactivity to accept before timing out the QUIC connection.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_max_idle_timeout(mut self, value: Duration) -> ClientBuilder {\n        self.config.quic_max_idle_timeout = Some(value);\n        self\n    }\n\n    /// Maximum number of bytes the peer may transmit without acknowledgement on any one stream\n    /// before becoming blocked.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is over 2^62.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_stream_receive_window(mut self, value: u64) -> ClientBuilder {\n        self.config.quic_stream_receive_window = Some(value.try_into().unwrap());\n        self\n    }\n\n    /// Maximum number of bytes the peer may transmit across all streams of a connection before\n    /// becoming blocked.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is over 2^62.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_conn_receive_window(mut self, value: u64) -> ClientBuilder {\n        self.config.quic_receive_window = Some(value.try_into().unwrap());\n        self\n    }\n\n    /// Maximum number of bytes to transmit to a peer without acknowledgment\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_send_window(mut self, value: u64) -> ClientBuilder {\n        self.config.quic_send_window = Some(value);\n        self\n    }\n\n    /// Override the default congestion control algorithm to use [BBR]\n    ///\n    /// The current default congestion control algorithm is [CUBIC]. This method overrides the\n    /// default.\n    ///\n    /// [BBR]: https://datatracker.ietf.org/doc/html/draft-ietf-ccwg-bbr\n    /// [CUBIC]: https://datatracker.ietf.org/doc/html/rfc8312\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_congestion_bbr(mut self) -> ClientBuilder {\n        self.config.quic_congestion_bbr = true;\n        self\n    }\n\n    /// Set the maximum HTTP/3 header size this client is willing to accept.\n    ///\n    /// See [header size constraints] section of the specification for details.\n    ///\n    /// [header size constraints]: https://www.rfc-editor.org/rfc/rfc9114.html#name-header-size-constraints\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.max_field_section_size\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_max_field_section_size(mut self, value: u64) -> ClientBuilder {\n        self.config.h3_max_field_section_size = Some(value.try_into().unwrap());\n        self\n    }\n\n    /// Enable whether to send HTTP/3 protocol grease on the connections.\n    ///\n    /// HTTP/3 uses the concept of \"grease\"\n    ///\n    /// to prevent potential interoperability issues in the future.\n    /// In HTTP/3, the concept of grease is used to ensure that the protocol can evolve\n    /// and accommodate future changes without breaking existing implementations.\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.send_grease\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_send_grease(mut self, enabled: bool) -> ClientBuilder {\n        self.config.h3_send_grease = Some(enabled);\n        self\n    }\n\n    /// Adds a new Tower [`Layer`](https://docs.rs/tower/latest/tower/trait.Layer.html) to the\n    /// base connector [`Service`](https://docs.rs/tower/latest/tower/trait.Service.html) which\n    /// is responsible for connection establishment.\n    ///\n    /// Each subsequent invocation of this function will wrap previous layers.\n    ///\n    /// If configured, the `connect_timeout` will be the outermost layer.\n    ///\n    /// Example usage:\n    /// ```\n    /// use std::time::Duration;\n    ///\n    /// # #[cfg(not(feature = \"rustls-no-provider\"))]\n    /// let client = reqwest::Client::builder()\n    ///                      // resolved to outermost layer, meaning while we are waiting on concurrency limit\n    ///                      .connect_timeout(Duration::from_millis(200))\n    ///                      // underneath the concurrency check, so only after concurrency limit lets us through\n    ///                      .connector_layer(tower::timeout::TimeoutLayer::new(Duration::from_millis(50)))\n    ///                      .connector_layer(tower::limit::concurrency::ConcurrencyLimitLayer::new(2))\n    ///                      .build()\n    ///                      .unwrap();\n    /// ```\n    ///\n    pub fn connector_layer<L>(mut self, layer: L) -> ClientBuilder\n    where\n        L: Layer<BoxedConnectorService> + Clone + Send + Sync + 'static,\n        L::Service:\n            Service<Unnameable, Response = Conn, Error = BoxError> + Clone + Send + Sync + 'static,\n        <L::Service as Service<Unnameable>>::Future: Send + 'static,\n    {\n        let layer = BoxCloneSyncServiceLayer::new(layer);\n\n        self.config.connector_layers.push(layer);\n\n        self\n    }\n}\n\ntype HyperClient = hyper_util::client::legacy::Client<Connector, super::Body>;\n\nimpl Default for Client {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nfn default_rustls_crypto_provider() -> Arc<rustls::crypto::CryptoProvider> {\n    #[cfg(not(feature = \"__rustls-aws-lc-rs\"))]\n    panic!(\"No provider set\");\n\n    #[cfg(feature = \"__rustls-aws-lc-rs\")]\n    Arc::new(rustls::crypto::aws_lc_rs::default_provider())\n}\n\nimpl Client {\n    /// Constructs a new `Client`.\n    ///\n    /// # Panics\n    ///\n    /// This method panics if a TLS backend cannot be initialized, or the resolver\n    /// cannot load the system configuration.\n    ///\n    /// Use `Client::builder()` if you wish to handle the failure as an `Error`\n    /// instead of panicking.\n    pub fn new() -> Client {\n        ClientBuilder::new().build().expect(\"Client::new()\")\n    }\n\n    /// Creates a `ClientBuilder` to configure a `Client`.\n    ///\n    /// This is the same as `ClientBuilder::new()`.\n    pub fn builder() -> ClientBuilder {\n        ClientBuilder::new()\n    }\n\n    /// Convenience method to make a `GET` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::GET, url)\n    }\n\n    /// Convenience method to make a `POST` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::POST, url)\n    }\n\n    /// Convenience method to make a `PUT` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PUT, url)\n    }\n\n    /// Convenience method to make a `PATCH` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PATCH, url)\n    }\n\n    /// Convenience method to make a `DELETE` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::DELETE, url)\n    }\n\n    /// Convenience method to make a `HEAD` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::HEAD, url)\n    }\n\n    /// Start building a `Request` with the `Method` and `Url`.\n    ///\n    /// Returns a `RequestBuilder`, which will allow setting headers and\n    /// the request body before sending.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the supplied `Url` cannot be parsed.\n    pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {\n        let req = url.into_url().map(move |url| Request::new(method, url));\n        RequestBuilder::new(self.clone(), req)\n    }\n\n    /// Executes a `Request`.\n    ///\n    /// A `Request` can be built manually with `Request::new()` or obtained\n    /// from a RequestBuilder with `RequestBuilder::build()`.\n    ///\n    /// You should prefer to use the `RequestBuilder` and\n    /// `RequestBuilder::send()`.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request,\n    /// redirect loop was detected or redirect limit was exhausted.\n    pub fn execute(\n        &self,\n        request: Request,\n    ) -> impl Future<Output = Result<Response, crate::Error>> {\n        self.execute_request(request)\n    }\n\n    pub(super) fn execute_request(&self, req: Request) -> Pending {\n        let (method, url, mut headers, body, version, extensions) = req.pieces();\n        if url.scheme() != \"http\" && url.scheme() != \"https\" {\n            return Pending::new_err(error::url_bad_scheme(url));\n        }\n\n        // check if we're in https_only mode and check the scheme of the current URL\n        if self.inner.https_only && url.scheme() != \"https\" {\n            return Pending::new_err(error::url_bad_scheme(url));\n        }\n\n        // insert default headers in the request headers\n        // without overwriting already appended headers.\n        for (key, value) in &self.inner.headers {\n            if let Entry::Vacant(entry) = headers.entry(key) {\n                entry.insert(value.clone());\n            }\n        }\n\n        let uri = match try_uri(&url) {\n            Ok(uri) => uri,\n            _ => return Pending::new_err(error::url_invalid_uri(url)),\n        };\n\n        let body = body.unwrap_or_else(Body::empty);\n\n        self.proxy_auth(&uri, &mut headers);\n        self.proxy_custom_headers(&uri, &mut headers);\n\n        let builder = hyper::Request::builder()\n            .method(method.clone())\n            .uri(uri)\n            .version(version);\n\n        let in_flight = match version {\n            #[cfg(feature = \"http3\")]\n            http::Version::HTTP_3 if self.inner.h3_client.is_some() => {\n                let mut req = builder.body(body).expect(\"valid request parts\");\n                *req.headers_mut() = headers.clone();\n                let mut h3 = self.inner.h3_client.as_ref().unwrap().clone();\n                ResponseFuture::H3(h3.call(req))\n            }\n            _ => {\n                let mut req = builder.body(body).expect(\"valid request parts\");\n                *req.headers_mut() = headers.clone();\n                let mut hyper = self.inner.hyper.clone();\n                ResponseFuture::Default(hyper.call(req))\n            }\n        };\n\n        let total_timeout = self\n            .inner\n            .total_timeout\n            .fetch(&extensions)\n            .copied()\n            .map(tokio::time::sleep)\n            .map(Box::pin);\n\n        let read_timeout_fut = self\n            .inner\n            .read_timeout\n            .map(tokio::time::sleep)\n            .map(Box::pin);\n\n        Pending {\n            inner: PendingInner::Request(Box::pin(PendingRequest {\n                method,\n                url,\n                headers,\n\n                client: self.inner.clone(),\n\n                in_flight,\n                total_timeout,\n                read_timeout_fut,\n                read_timeout: self.inner.read_timeout,\n            })),\n        }\n    }\n\n    fn proxy_auth(&self, dst: &Uri, headers: &mut HeaderMap) {\n        if !self.inner.proxies_maybe_http_auth {\n            return;\n        }\n\n        // Only set the header here if the destination scheme is 'http',\n        // since otherwise, the header will be included in the CONNECT tunnel\n        // request instead.\n        if dst.scheme() != Some(&Scheme::HTTP) {\n            return;\n        }\n\n        if headers.contains_key(PROXY_AUTHORIZATION) {\n            return;\n        }\n\n        for proxy in self.inner.proxies.iter() {\n            if let Some(header) = proxy.http_non_tunnel_basic_auth(dst) {\n                headers.insert(PROXY_AUTHORIZATION, header);\n                break;\n            }\n        }\n    }\n\n    fn proxy_custom_headers(&self, dst: &Uri, headers: &mut HeaderMap) {\n        if !self.inner.proxies_maybe_http_custom_headers {\n            return;\n        }\n\n        if dst.scheme() != Some(&Scheme::HTTP) {\n            return;\n        }\n\n        for proxy in self.inner.proxies.iter() {\n            if let Some(iter) = proxy.http_non_tunnel_custom_headers(dst) {\n                iter.iter().for_each(|(key, value)| {\n                    headers.insert(key, value.clone());\n                });\n                break;\n            }\n        }\n    }\n}\n\nimpl fmt::Debug for Client {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"Client\");\n        self.inner.fmt_fields(&mut builder);\n        builder.finish()\n    }\n}\n\nimpl tower_service::Service<Request> for Client {\n    type Response = Response;\n    type Error = crate::Error;\n    type Future = Pending;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        self.execute_request(req)\n    }\n}\n\nimpl tower_service::Service<Request> for &'_ Client {\n    type Response = Response;\n    type Error = crate::Error;\n    type Future = Pending;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        self.execute_request(req)\n    }\n}\n\nimpl fmt::Debug for ClientBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"ClientBuilder\");\n        self.config.fmt_fields(&mut builder);\n        builder.finish()\n    }\n}\n\nimpl Config {\n    fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {\n        // Instead of deriving Debug, only print fields when their output\n        // would provide relevant or interesting data.\n\n        #[cfg(feature = \"cookies\")]\n        {\n            if let Some(_) = self.cookie_store {\n                f.field(\"cookie_store\", &true);\n            }\n        }\n\n        f.field(\"accepts\", &self.accepts);\n\n        if !self.proxies.is_empty() {\n            f.field(\"proxies\", &self.proxies);\n        }\n\n        if !self.redirect_policy.is_default() {\n            f.field(\"redirect_policy\", &self.redirect_policy);\n        }\n\n        if self.referer {\n            f.field(\"referer\", &true);\n        }\n\n        f.field(\"default_headers\", &self.headers);\n\n        if self.http1_title_case_headers {\n            f.field(\"http1_title_case_headers\", &true);\n        }\n\n        if self.http1_allow_obsolete_multiline_headers_in_responses {\n            f.field(\"http1_allow_obsolete_multiline_headers_in_responses\", &true);\n        }\n\n        if self.http1_ignore_invalid_headers_in_responses {\n            f.field(\"http1_ignore_invalid_headers_in_responses\", &true);\n        }\n\n        if self.http1_allow_spaces_after_header_name_in_responses {\n            f.field(\"http1_allow_spaces_after_header_name_in_responses\", &true);\n        }\n\n        if matches!(self.http_version_pref, HttpVersionPref::Http1) {\n            f.field(\"http1_only\", &true);\n        }\n\n        #[cfg(feature = \"http2\")]\n        if matches!(self.http_version_pref, HttpVersionPref::Http2) {\n            f.field(\"http2_prior_knowledge\", &true);\n        }\n\n        if let Some(ref d) = self.connect_timeout {\n            f.field(\"connect_timeout\", d);\n        }\n\n        if let Some(ref d) = self.timeout {\n            f.field(\"timeout\", d);\n        }\n\n        if let Some(ref v) = self.local_address {\n            f.field(\"local_address\", v);\n        }\n\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        if let Some(ref v) = self.interface {\n            f.field(\"interface\", v);\n        }\n\n        if self.nodelay {\n            f.field(\"tcp_nodelay\", &true);\n        }\n\n        #[cfg(feature = \"__tls\")]\n        {\n            if !self.hostname_verification {\n                f.field(\"tls_danger_accept_invalid_hostnames\", &true);\n            }\n        }\n\n        #[cfg(feature = \"__tls\")]\n        {\n            if !self.certs_verification {\n                f.field(\"tls_danger_accept_invalid_certs\", &true);\n            }\n\n            if let Some(ref min_tls_version) = self.min_tls_version {\n                f.field(\"tls_version_min\", min_tls_version);\n            }\n\n            if let Some(ref max_tls_version) = self.max_tls_version {\n                f.field(\"tls_version_max\", max_tls_version);\n            }\n\n            f.field(\"tls_sni\", &self.tls_sni);\n\n            f.field(\"tls_info\", &self.tls_info);\n        }\n\n        #[cfg(all(feature = \"default-tls\", feature = \"__rustls\"))]\n        {\n            f.field(\"tls_backend\", &self.tls);\n        }\n\n        if !self.dns_overrides.is_empty() {\n            f.field(\"dns_overrides\", &self.dns_overrides);\n        }\n\n        #[cfg(feature = \"http3\")]\n        {\n            if self.tls_enable_early_data {\n                f.field(\"tls_enable_early_data\", &true);\n            }\n        }\n\n        #[cfg(unix)]\n        if let Some(ref p) = self.unix_socket {\n            f.field(\"unix_socket\", p);\n        }\n    }\n}\n\n#[cfg(not(feature = \"cookies\"))]\ntype MaybeCookieService<T> = T;\n\n#[cfg(feature = \"cookies\")]\ntype MaybeCookieService<T> = CookieService<T>;\n\n#[cfg(not(any(\n    feature = \"gzip\",\n    feature = \"brotli\",\n    feature = \"zstd\",\n    feature = \"deflate\"\n)))]\ntype MaybeDecompression<T> = T;\n\n#[cfg(any(\n    feature = \"gzip\",\n    feature = \"brotli\",\n    feature = \"zstd\",\n    feature = \"deflate\"\n))]\ntype MaybeDecompression<T> = Decompression<T>;\n\ntype LayeredService<T> = MaybeDecompression<\n    FollowRedirect<\n        MaybeCookieService<tower::retry::Retry<crate::retry::Policy, T>>,\n        TowerRedirectPolicy,\n    >,\n>;\ntype LayeredFuture<T> = <LayeredService<T> as Service<http::Request<Body>>>::Future;\n\nstruct ClientRef {\n    accepts: Accepts,\n    #[cfg(feature = \"cookies\")]\n    cookie_store: Option<Arc<dyn cookie::CookieStore>>,\n    headers: HeaderMap,\n    hyper: LayeredService<HyperService>,\n    #[cfg(feature = \"http3\")]\n    h3_client: Option<LayeredService<H3Client>>,\n    referer: bool,\n    total_timeout: RequestConfig<TotalTimeout>,\n    read_timeout: Option<Duration>,\n    proxies: Arc<Vec<ProxyMatcher>>,\n    proxies_maybe_http_auth: bool,\n    proxies_maybe_http_custom_headers: bool,\n    https_only: bool,\n    redirect_policy_desc: Option<String>,\n}\n\nimpl ClientRef {\n    fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {\n        // Instead of deriving Debug, only print fields when their output\n        // would provide relevant or interesting data.\n\n        #[cfg(feature = \"cookies\")]\n        {\n            if let Some(_) = self.cookie_store {\n                f.field(\"cookie_store\", &true);\n            }\n        }\n\n        f.field(\"accepts\", &self.accepts);\n\n        if !self.proxies.is_empty() {\n            f.field(\"proxies\", &self.proxies);\n        }\n\n        if let Some(s) = &self.redirect_policy_desc {\n            f.field(\"redirect_policy\", s);\n        }\n\n        if self.referer {\n            f.field(\"referer\", &true);\n        }\n\n        f.field(\"default_headers\", &self.headers);\n\n        self.total_timeout.fmt_as_field(f);\n\n        if let Some(ref d) = self.read_timeout {\n            f.field(\"read_timeout\", d);\n        }\n    }\n}\n\npin_project! {\n    pub struct Pending {\n        #[pin]\n        inner: PendingInner,\n    }\n}\n\nenum PendingInner {\n    Request(Pin<Box<PendingRequest>>),\n    Error(Option<crate::Error>),\n}\n\npin_project! {\n    struct PendingRequest {\n        method: Method,\n        url: Url,\n        headers: HeaderMap,\n\n        client: Arc<ClientRef>,\n\n        #[pin]\n        in_flight: ResponseFuture,\n        #[pin]\n        total_timeout: Option<Pin<Box<Sleep>>>,\n        #[pin]\n        read_timeout_fut: Option<Pin<Box<Sleep>>>,\n        read_timeout: Option<Duration>,\n    }\n}\n\nenum ResponseFuture {\n    Default(LayeredFuture<HyperService>),\n    #[cfg(feature = \"http3\")]\n    H3(LayeredFuture<H3Client>),\n}\n\nimpl PendingRequest {\n    fn in_flight(self: Pin<&mut Self>) -> Pin<&mut ResponseFuture> {\n        self.project().in_flight\n    }\n\n    fn total_timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>> {\n        self.project().total_timeout\n    }\n\n    fn read_timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>> {\n        self.project().read_timeout_fut\n    }\n}\n\nimpl Pending {\n    pub(super) fn new_err(err: crate::Error) -> Pending {\n        Pending {\n            inner: PendingInner::Error(Some(err)),\n        }\n    }\n\n    fn inner(self: Pin<&mut Self>) -> Pin<&mut PendingInner> {\n        self.project().inner\n    }\n}\n\nimpl Future for Pending {\n    type Output = Result<Response, crate::Error>;\n\n    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        let inner = self.inner();\n        match inner.get_mut() {\n            PendingInner::Request(ref mut req) => Pin::new(req).poll(cx),\n            PendingInner::Error(ref mut err) => Poll::Ready(Err(err\n                .take()\n                .expect(\"Pending error polled more than once\"))),\n        }\n    }\n}\n\nimpl Future for PendingRequest {\n    type Output = Result<Response, crate::Error>;\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        if let Some(delay) = self.as_mut().total_timeout().as_mut().as_pin_mut() {\n            if let Poll::Ready(()) = delay.poll(cx) {\n                return Poll::Ready(Err(\n                    crate::error::request(crate::error::TimedOut).with_url(self.url.clone())\n                ));\n            }\n        }\n\n        if let Some(delay) = self.as_mut().read_timeout().as_mut().as_pin_mut() {\n            if let Poll::Ready(()) = delay.poll(cx) {\n                return Poll::Ready(Err(\n                    crate::error::request(crate::error::TimedOut).with_url(self.url.clone())\n                ));\n            }\n        }\n\n        let res = match self.as_mut().in_flight().get_mut() {\n            ResponseFuture::Default(r) => match ready!(Pin::new(r).poll(cx)) {\n                Err(e) => {\n                    return Poll::Ready(Err(e.if_no_url(|| self.url.clone())));\n                }\n                Ok(res) => res.map(super::body::boxed),\n            },\n            #[cfg(feature = \"http3\")]\n            ResponseFuture::H3(r) => match ready!(Pin::new(r).poll(cx)) {\n                Err(e) => {\n                    return Poll::Ready(Err(crate::error::request(e).with_url(self.url.clone())));\n                }\n                Ok(res) => res.map(super::body::boxed),\n            },\n        };\n\n        if let Some(url) = &res\n            .extensions()\n            .get::<tower_http::follow_redirect::RequestUri>()\n        {\n            self.url = match Url::parse(&url.0.to_string()) {\n                Ok(url) => url,\n                Err(e) => return Poll::Ready(Err(crate::error::decode(e))),\n            }\n        };\n\n        let res = Response::new(\n            res,\n            self.url.clone(),\n            self.total_timeout.take(),\n            self.read_timeout,\n        );\n        Poll::Ready(Ok(res))\n    }\n}\n\nimpl fmt::Debug for Pending {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self.inner {\n            PendingInner::Request(ref req) => f\n                .debug_struct(\"Pending\")\n                .field(\"method\", &req.method)\n                .field(\"url\", &req.url)\n                .finish(),\n            PendingInner::Error(ref err) => f.debug_struct(\"Pending\").field(\"error\", err).finish(),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #![cfg(not(feature = \"rustls-no-provider\"))]\n\n    #[tokio::test]\n    async fn execute_request_rejects_invalid_urls() {\n        let url_str = \"hxxps://www.rust-lang.org/\";\n        let url = url::Url::parse(url_str).unwrap();\n        let result = crate::get(url.clone()).await;\n\n        assert!(result.is_err());\n        let err = result.err().unwrap();\n        assert!(err.is_builder());\n        assert_eq!(url_str, err.url().unwrap().as_str());\n    }\n\n    /// https://github.com/seanmonstar/reqwest/issues/668\n    #[tokio::test]\n    async fn execute_request_rejects_invalid_hostname() {\n        let url_str = \"https://{{hostname}}/\";\n        let url = url::Url::parse(url_str).unwrap();\n        let result = crate::get(url.clone()).await;\n\n        assert!(result.is_err());\n        let err = result.err().unwrap();\n        assert!(err.is_builder());\n        assert_eq!(url_str, err.url().unwrap().as_str());\n    }\n\n    #[test]\n    fn test_future_size() {\n        let s = std::mem::size_of::<super::Pending>();\n        assert!(s < 128, \"size_of::<Pending>() == {s}, too big\");\n    }\n}\n"
  },
  {
    "path": "src/async_impl/h3_client/connect.rs",
    "content": "use crate::async_impl::h3_client::dns::resolve;\nuse crate::dns::DynResolver;\nuse crate::error::BoxError;\nuse bytes::Bytes;\nuse h3::client::SendRequest;\nuse h3_quinn::{Connection, OpenStreams};\nuse http::Uri;\nuse hyper_util::client::legacy::connect::dns::Name;\nuse quinn::crypto::rustls::QuicClientConfig;\nuse quinn::{ClientConfig, Endpoint, TransportConfig};\nuse std::net::{IpAddr, SocketAddr};\nuse std::str::FromStr;\nuse std::sync::Arc;\n\ntype H3Connection = (\n    h3::client::Connection<Connection, Bytes>,\n    SendRequest<OpenStreams, Bytes>,\n);\n\n/// H3 Client Config\n#[derive(Clone)]\npub(crate) struct H3ClientConfig {\n    /// Set the maximum HTTP/3 header size this client is willing to accept.\n    ///\n    /// See [header size constraints] section of the specification for details.\n    ///\n    /// [header size constraints]: https://www.rfc-editor.org/rfc/rfc9114.html#name-header-size-constraints\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.max_field_section_size\n    pub(crate) max_field_section_size: Option<u64>,\n\n    /// Enable whether to send HTTP/3 protocol grease on the connections.\n    ///\n    /// Just like in HTTP/2, HTTP/3 also uses the concept of \"grease\"\n    ///\n    /// to prevent potential interoperability issues in the future.\n    /// In HTTP/3, the concept of grease is used to ensure that the protocol can evolve\n    /// and accommodate future changes without breaking existing implementations.\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.send_grease\n    pub(crate) send_grease: Option<bool>,\n}\n\nimpl Default for H3ClientConfig {\n    fn default() -> Self {\n        Self {\n            max_field_section_size: None,\n            send_grease: None,\n        }\n    }\n}\n\n#[derive(Clone)]\npub(crate) struct H3Connector {\n    resolver: DynResolver,\n    endpoint: Endpoint,\n    client_config: H3ClientConfig,\n}\n\nimpl H3Connector {\n    pub fn new(\n        resolver: DynResolver,\n        tls: rustls::ClientConfig,\n        local_addr: Option<IpAddr>,\n        transport_config: TransportConfig,\n        client_config: H3ClientConfig,\n    ) -> Result<H3Connector, BoxError> {\n        let quic_client_config = Arc::new(QuicClientConfig::try_from(tls)?);\n        let mut config = ClientConfig::new(quic_client_config);\n        // FIXME: Replace this when there is a setter.\n        config.transport_config(Arc::new(transport_config));\n\n        let socket_addr = match local_addr {\n            Some(ip) => SocketAddr::new(ip, 0),\n            None => \"[::]:0\".parse::<SocketAddr>().unwrap(),\n        };\n\n        let mut endpoint = Endpoint::client(socket_addr)?;\n        endpoint.set_default_client_config(config);\n\n        Ok(Self {\n            resolver,\n            endpoint,\n            client_config,\n        })\n    }\n\n    pub async fn connect(&mut self, dest: Uri) -> Result<H3Connection, BoxError> {\n        let host = dest\n            .host()\n            .ok_or(\"destination must have a host\")?\n            .trim_start_matches('[')\n            .trim_end_matches(']');\n        let port = dest.port_u16().unwrap_or(443);\n\n        let addrs = if let Some(addr) = IpAddr::from_str(host).ok() {\n            // If the host is already an IP address, skip resolving.\n            vec![SocketAddr::new(addr, port)]\n        } else {\n            let addrs = resolve(&mut self.resolver, Name::from_str(host)?).await?;\n            let addrs = addrs.map(|mut addr| {\n                addr.set_port(port);\n                addr\n            });\n            addrs.collect()\n        };\n\n        self.remote_connect(addrs, host).await\n    }\n\n    async fn remote_connect(\n        &mut self,\n        addrs: Vec<SocketAddr>,\n        server_name: &str,\n    ) -> Result<H3Connection, BoxError> {\n        let mut err = None;\n        for addr in addrs {\n            match self.endpoint.connect(addr, server_name)?.await {\n                Ok(new_conn) => {\n                    let quinn_conn = Connection::new(new_conn);\n                    let mut h3_client_builder = h3::client::builder();\n                    if let Some(max_field_section_size) = self.client_config.max_field_section_size\n                    {\n                        h3_client_builder.max_field_section_size(max_field_section_size);\n                    }\n                    if let Some(send_grease) = self.client_config.send_grease {\n                        h3_client_builder.send_grease(send_grease);\n                    }\n                    return Ok(h3_client_builder.build(quinn_conn).await?);\n                }\n                Err(e) => err = Some(e),\n            }\n        }\n\n        match err {\n            Some(e) => Err(Box::new(e) as BoxError),\n            None => Err(\"failed to establish connection for HTTP/3 request\".into()),\n        }\n    }\n}\n"
  },
  {
    "path": "src/async_impl/h3_client/dns.rs",
    "content": "use core::task;\nuse hyper_util::client::legacy::connect::dns::Name;\nuse std::future::Future;\nuse std::net::SocketAddr;\nuse std::task::Poll;\nuse tower_service::Service;\n\n// Trait from hyper to implement DNS resolution for HTTP/3 client.\npub trait Resolve {\n    type Addrs: Iterator<Item = SocketAddr>;\n    type Error: Into<Box<dyn std::error::Error + Send + Sync>>;\n    type Future: Future<Output = Result<Self::Addrs, Self::Error>>;\n\n    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;\n    fn resolve(&mut self, name: Name) -> Self::Future;\n}\n\nimpl<S> Resolve for S\nwhere\n    S: Service<Name>,\n    S::Response: Iterator<Item = SocketAddr>,\n    S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,\n{\n    type Addrs = S::Response;\n    type Error = S::Error;\n    type Future = S::Future;\n\n    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Service::poll_ready(self, cx)\n    }\n\n    fn resolve(&mut self, name: Name) -> Self::Future {\n        Service::call(self, name)\n    }\n}\n\npub(super) async fn resolve<R>(resolver: &mut R, name: Name) -> Result<R::Addrs, R::Error>\nwhere\n    R: Resolve,\n{\n    std::future::poll_fn(|cx| resolver.poll_ready(cx)).await?;\n    resolver.resolve(name).await\n}\n"
  },
  {
    "path": "src/async_impl/h3_client/mod.rs",
    "content": "#![cfg(feature = \"http3\")]\n\npub(crate) mod connect;\npub(crate) mod dns;\nmod pool;\n\nuse crate::async_impl::body::ResponseBody;\nuse crate::async_impl::h3_client::pool::{Key, Pool, PoolClient};\nuse crate::error::{BoxError, Error, Kind};\nuse crate::{error, Body};\nuse connect::H3Connector;\nuse http::{Request, Response};\nuse log::trace;\nuse std::future::{self, Future};\nuse std::pin::Pin;\nuse std::task::{Context, Poll};\nuse std::time::Duration;\nuse sync_wrapper::SyncWrapper;\nuse tower::Service;\n\n#[derive(Clone)]\npub(crate) struct H3Client {\n    pool: Pool,\n    connector: H3Connector,\n}\n\nimpl H3Client {\n    pub fn new(connector: H3Connector, pool_timeout: Option<Duration>) -> Self {\n        H3Client {\n            pool: Pool::new(pool_timeout),\n            connector,\n        }\n    }\n\n    async fn get_pooled_client(&mut self, key: Key) -> Result<PoolClient, BoxError> {\n        if let Some(client) = self.pool.try_pool(&key) {\n            trace!(\"getting client from pool with key {key:?}\");\n            return Ok(client);\n        }\n\n        trace!(\"did not find connection {key:?} in pool so connecting...\");\n\n        let dest = pool::domain_as_uri(key.clone());\n\n        let lock = match self.pool.connecting(&key) {\n            pool::Connecting::InProgress(waiter) => {\n                trace!(\"connecting to {key:?} is already in progress, subscribing...\");\n\n                match waiter.receive().await {\n                    Some(client) => return Ok(client),\n                    None => return Err(\"failed to establish connection for HTTP/3 request\".into()),\n                }\n            }\n            pool::Connecting::Acquired(lock) => lock,\n        };\n        trace!(\"connecting to {key:?}...\");\n        let (driver, tx) = self.connector.connect(dest).await?;\n        trace!(\"saving new pooled connection to {key:?}\");\n        Ok(self.pool.new_connection(lock, driver, tx))\n    }\n\n    async fn send_request(\n        mut self,\n        key: Key,\n        req: Request<Body>,\n    ) -> Result<Response<ResponseBody>, Error> {\n        let mut pooled = match self.get_pooled_client(key).await {\n            Ok(client) => client,\n            Err(e) => return Err(error::request(e)),\n        };\n        pooled\n            .send_request(req)\n            .await\n            .map_err(|e| Error::new(Kind::Request, Some(e)))\n    }\n\n    pub fn request(&self, mut req: Request<Body>) -> H3ResponseFuture {\n        let pool_key = match pool::extract_domain(req.uri_mut()) {\n            Ok(s) => s,\n            Err(e) => {\n                return H3ResponseFuture {\n                    inner: SyncWrapper::new(Box::pin(future::ready(Err(e)))),\n                }\n            }\n        };\n        H3ResponseFuture {\n            inner: SyncWrapper::new(Box::pin(self.clone().send_request(pool_key, req))),\n        }\n    }\n}\n\nimpl Service<Request<Body>> for H3Client {\n    type Response = Response<ResponseBody>;\n    type Error = Error;\n    type Future = H3ResponseFuture;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, req: Request<Body>) -> Self::Future {\n        self.request(req)\n    }\n}\n\npub(crate) struct H3ResponseFuture {\n    inner: SyncWrapper<Pin<Box<dyn Future<Output = Result<Response<ResponseBody>, Error>> + Send>>>,\n}\n\nimpl Future for H3ResponseFuture {\n    type Output = Result<Response<ResponseBody>, Error>;\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        self.inner.get_mut().as_mut().poll(cx)\n    }\n}\n"
  },
  {
    "path": "src/async_impl/h3_client/pool.rs",
    "content": "use bytes::Bytes;\nuse std::collections::HashMap;\nuse std::future;\nuse std::pin::Pin;\nuse std::sync::mpsc::{Receiver, TryRecvError};\nuse std::sync::{Arc, Mutex};\nuse std::task::{Context, Poll};\nuse std::time::Duration;\nuse tokio::sync::{oneshot, watch};\nuse tokio::time::Instant;\n\nuse crate::async_impl::body::ResponseBody;\nuse crate::error::{BoxError, Error, Kind};\nuse crate::Body;\nuse bytes::Buf;\nuse h3::client::SendRequest;\nuse h3_quinn::{Connection, OpenStreams};\nuse http::uri::{Authority, Scheme};\nuse http::{Request, Response, Uri};\nuse log::{error, trace};\n\npub(super) type Key = (Scheme, Authority);\n\n#[derive(Clone)]\npub struct Pool {\n    inner: Arc<Mutex<PoolInner>>,\n}\n\nstruct ConnectingLockInner {\n    key: Key,\n    pool: Arc<Mutex<PoolInner>>,\n}\n\n/// A lock that ensures only one HTTP/3 connection is established per host at a\n/// time. The lock is automatically released when dropped.\npub struct ConnectingLock(Option<ConnectingLockInner>);\n\n/// A waiter that allows subscribers to receive updates when a new connection is\n/// established or when the connection attempt fails. For example, when\n/// connection lock is dropped due to an error.\npub struct ConnectingWaiter {\n    receiver: watch::Receiver<Option<PoolClient>>,\n}\n\npub enum Connecting {\n    /// A connection attempt is already in progress.\n    /// You must subscribe to updates instead of initiating a new connection.\n    InProgress(ConnectingWaiter),\n    /// The connection lock has been acquired, allowing you to initiate a\n    /// new connection.\n    Acquired(ConnectingLock),\n}\n\nimpl ConnectingLock {\n    fn new(key: Key, pool: Arc<Mutex<PoolInner>>) -> Self {\n        Self(Some(ConnectingLockInner { key, pool }))\n    }\n\n    /// Forget the lock and return corresponding Key\n    fn forget(mut self) -> Key {\n        // Unwrap is safe because the Option can be None only after dropping the\n        // lock\n        self.0.take().unwrap().key\n    }\n}\n\nimpl Drop for ConnectingLock {\n    fn drop(&mut self) {\n        if let Some(ConnectingLockInner { key, pool }) = self.0.take() {\n            let mut pool = pool.lock().unwrap();\n            pool.connecting.remove(&key);\n            trace!(\"HTTP/3 connecting lock for {:?} is dropped\", key);\n        }\n    }\n}\n\nimpl ConnectingWaiter {\n    pub async fn receive(mut self) -> Option<PoolClient> {\n        match self.receiver.wait_for(Option::is_some).await {\n            // unwrap because we already checked that option is Some\n            Ok(ok) => Some(ok.as_ref().unwrap().to_owned()),\n            Err(_) => None,\n        }\n    }\n}\n\nimpl Pool {\n    pub fn new(timeout: Option<Duration>) -> Self {\n        Self {\n            inner: Arc::new(Mutex::new(PoolInner {\n                connecting: HashMap::new(),\n                idle_conns: HashMap::new(),\n                timeout,\n            })),\n        }\n    }\n\n    /// Acquire a connecting lock. This is to ensure that we have only one HTTP3\n    /// connection per host.\n    pub fn connecting(&self, key: &Key) -> Connecting {\n        let mut inner = self.inner.lock().unwrap();\n\n        if let Some(sender) = inner.connecting.get(key) {\n            Connecting::InProgress(ConnectingWaiter {\n                receiver: sender.subscribe(),\n            })\n        } else {\n            let (tx, _) = watch::channel(None);\n            inner.connecting.insert(key.clone(), tx);\n            Connecting::Acquired(ConnectingLock::new(key.clone(), Arc::clone(&self.inner)))\n        }\n    }\n\n    pub fn try_pool(&self, key: &Key) -> Option<PoolClient> {\n        let mut inner = self.inner.lock().unwrap();\n        let timeout = inner.timeout;\n        if let Some(conn) = inner.idle_conns.get(&key) {\n            // We check first if the connection still valid\n            // and if not, we remove it from the pool.\n            if conn.is_invalid() {\n                trace!(\"pooled HTTP/3 connection is invalid so removing it...\");\n                inner.idle_conns.remove(&key);\n                return None;\n            }\n\n            if let Some(duration) = timeout {\n                if Instant::now().saturating_duration_since(conn.idle_timeout) > duration {\n                    trace!(\"pooled connection expired\");\n                    inner.idle_conns.remove(&key);\n                    return None;\n                }\n            }\n        }\n\n        inner\n            .idle_conns\n            .get_mut(&key)\n            .and_then(|conn| Some(conn.pool()))\n    }\n\n    pub fn new_connection(\n        &mut self,\n        lock: ConnectingLock,\n        mut driver: h3::client::Connection<Connection, Bytes>,\n        tx: SendRequest<OpenStreams, Bytes>,\n    ) -> PoolClient {\n        let (close_tx, close_rx) = std::sync::mpsc::channel();\n        tokio::spawn(async move {\n            let e = future::poll_fn(|cx| driver.poll_close(cx)).await;\n            trace!(\"poll_close returned error {e:?}\");\n            close_tx.send(e).ok();\n        });\n\n        let mut inner = self.inner.lock().unwrap();\n\n        // We clean up \"connecting\" here so we don't have to acquire the lock again.\n        let key = lock.forget();\n        let Some(notifier) = inner.connecting.remove(&key) else {\n            unreachable!(\"there should be one connecting lock at a time\");\n        };\n        let client = PoolClient::new(tx);\n\n        // Send the client to all our awaiters\n        let pool_client = if let Err(watch::error::SendError(Some(unsent_client))) =\n            notifier.send(Some(client.clone()))\n        {\n            // If there are no awaiters, the client is returned to us. As a\n            // micro optimisation, let's reuse it and avoid cloning.\n            unsent_client\n        } else {\n            client.clone()\n        };\n\n        let conn = PoolConnection::new(pool_client, close_rx);\n        inner.insert(key, conn);\n\n        client\n    }\n}\n\nstruct PoolInner {\n    connecting: HashMap<Key, watch::Sender<Option<PoolClient>>>,\n    idle_conns: HashMap<Key, PoolConnection>,\n    timeout: Option<Duration>,\n}\n\nimpl PoolInner {\n    fn insert(&mut self, key: Key, conn: PoolConnection) {\n        if self.idle_conns.contains_key(&key) {\n            trace!(\"connection already exists for key {key:?}\");\n        }\n\n        self.idle_conns.insert(key, conn);\n    }\n}\n\n#[derive(Clone)]\npub struct PoolClient {\n    inner: SendRequest<OpenStreams, Bytes>,\n}\n\nimpl PoolClient {\n    pub fn new(tx: SendRequest<OpenStreams, Bytes>) -> Self {\n        Self { inner: tx }\n    }\n\n    pub async fn send_request(\n        &mut self,\n        req: Request<Body>,\n    ) -> Result<Response<ResponseBody>, BoxError> {\n        use hyper::body::Body as _;\n\n        let (head, mut req_body) = req.into_parts();\n        let mut req = Request::from_parts(head, ());\n\n        if let Some(n) = req_body.size_hint().exact() {\n            if n > 0 {\n                req.headers_mut()\n                    .insert(http::header::CONTENT_LENGTH, n.into());\n            }\n        }\n\n        let (mut send, mut recv) = self.inner.send_request(req).await?.split();\n\n        let (tx, mut rx) = oneshot::channel::<Result<(), BoxError>>();\n        tokio::spawn(async move {\n            let mut req_body = Pin::new(&mut req_body);\n            loop {\n                match std::future::poll_fn(|cx| req_body.as_mut().poll_frame(cx)).await {\n                    Some(Ok(frame)) => {\n                        if let Ok(b) = frame.into_data() {\n                            if let Err(e) = send.send_data(Bytes::copy_from_slice(&b)).await {\n                                if is_stop_sending(&e) {\n                                    let _ = tx.send(Ok(()));\n                                    return;\n                                }\n                                if let Err(e) = tx.send(Err(e.into())) {\n                                    error!(\"Failed to communicate send.send_data() error: {e:?}\");\n                                }\n                                return;\n                            }\n                        }\n                    }\n                    Some(Err(e)) => {\n                        if let Err(e) = tx.send(Err(e.into())) {\n                            error!(\"Failed to communicate req_body read error: {e:?}\");\n                        }\n                        return;\n                    }\n\n                    None => break,\n                }\n            }\n\n            if let Err(e) = send.finish().await {\n                if !is_stop_sending(&e) {\n                    if let Err(e) = tx.send(Err(e.into())) {\n                        error!(\"Failed to communicate send.finish read error: {e:?}\");\n                    }\n                    return;\n                }\n            }\n\n            let _ = tx.send(Ok(()));\n        });\n\n        tokio::select! {\n            Ok(Err(e)) = &mut rx => Err(e),\n            resp = recv.recv_response() => {\n                let resp = resp?;\n                let resp_body = crate::async_impl::body::boxed(Incoming::new(recv, resp.headers(), rx));\n                Ok(resp.map(|_| resp_body))\n            }\n        }\n    }\n}\n\npub struct PoolConnection {\n    // This receives errors from polling h3 driver.\n    close_rx: Receiver<h3::error::ConnectionError>,\n    client: PoolClient,\n    idle_timeout: Instant,\n}\n\nimpl PoolConnection {\n    pub fn new(client: PoolClient, close_rx: Receiver<h3::error::ConnectionError>) -> Self {\n        Self {\n            close_rx,\n            client,\n            idle_timeout: Instant::now(),\n        }\n    }\n\n    pub fn pool(&mut self) -> PoolClient {\n        self.idle_timeout = Instant::now();\n        self.client.clone()\n    }\n\n    pub fn is_invalid(&self) -> bool {\n        match self.close_rx.try_recv() {\n            Err(TryRecvError::Empty) => false,\n            Err(TryRecvError::Disconnected) => true,\n            Ok(_) => true,\n        }\n    }\n}\n\nstruct Incoming<S, B> {\n    inner: h3::client::RequestStream<S, B>,\n    content_length: Option<u64>,\n    send_rx: oneshot::Receiver<Result<(), BoxError>>,\n}\n\nimpl<S, B> Incoming<S, B> {\n    fn new(\n        stream: h3::client::RequestStream<S, B>,\n        headers: &http::header::HeaderMap,\n        send_rx: oneshot::Receiver<Result<(), BoxError>>,\n    ) -> Self {\n        Self {\n            inner: stream,\n            content_length: headers\n                .get(http::header::CONTENT_LENGTH)\n                .and_then(|h| h.to_str().ok())\n                .and_then(|v| v.parse().ok()),\n            send_rx,\n        }\n    }\n}\n\nimpl<S, B> http_body::Body for Incoming<S, B>\nwhere\n    S: h3::quic::RecvStream,\n{\n    type Data = Bytes;\n    type Error = crate::error::Error;\n\n    fn poll_frame(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        if let Ok(Err(e)) = self.send_rx.try_recv() {\n            return Poll::Ready(Some(Err(crate::error::body(e))));\n        }\n\n        match futures_core::ready!(self.inner.poll_recv_data(cx)) {\n            Ok(Some(mut b)) => Poll::Ready(Some(Ok(hyper::body::Frame::data(\n                b.copy_to_bytes(b.remaining()),\n            )))),\n            Ok(None) => Poll::Ready(None),\n            Err(e) => Poll::Ready(Some(Err(crate::error::body(e)))),\n        }\n    }\n\n    fn size_hint(&self) -> hyper::body::SizeHint {\n        if let Some(content_length) = self.content_length {\n            hyper::body::SizeHint::with_exact(content_length)\n        } else {\n            hyper::body::SizeHint::default()\n        }\n    }\n}\n\npub(crate) fn extract_domain(uri: &mut Uri) -> Result<Key, Error> {\n    let uri_clone = uri.clone();\n    match (uri_clone.scheme(), uri_clone.authority()) {\n        (Some(scheme), Some(auth)) => Ok((scheme.clone(), auth.clone())),\n        _ => Err(Error::new(Kind::Request, None::<Error>)),\n    }\n}\n\npub(crate) fn domain_as_uri((scheme, auth): Key) -> Uri {\n    http::uri::Builder::new()\n        .scheme(scheme)\n        .authority(auth)\n        .path_and_query(\"/\")\n        .build()\n        .expect(\"domain is valid Uri\")\n}\n\n/// Indicates the remote requested the peer to stop sending data without error.\nfn is_stop_sending(e: &h3::error::StreamError) -> bool {\n    matches!(\n        e,\n        h3::error::StreamError::RemoteTerminate {\n            code: h3::error::Code::H3_NO_ERROR,\n            ..\n        }\n    )\n}\n"
  },
  {
    "path": "src/async_impl/mod.rs",
    "content": "pub use self::body::Body;\npub use self::client::{Client, ClientBuilder};\npub use self::request::{Request, RequestBuilder};\npub use self::response::Response;\npub use self::upgrade::Upgraded;\n\npub mod body;\npub mod client;\npub mod h3_client;\n#[cfg(feature = \"multipart\")]\npub mod multipart;\npub(crate) mod request;\nmod response;\nmod upgrade;\n"
  },
  {
    "path": "src/async_impl/multipart.rs",
    "content": "//! multipart/form-data\nuse std::borrow::Cow;\nuse std::fmt;\nuse std::pin::Pin;\n\n#[cfg(feature = \"stream\")]\nuse std::io;\n#[cfg(feature = \"stream\")]\nuse std::path::Path;\n\nuse bytes::Bytes;\nuse mime_guess::Mime;\nuse percent_encoding::{self, AsciiSet, NON_ALPHANUMERIC};\n#[cfg(feature = \"stream\")]\nuse tokio::fs::File;\n\nuse futures_core::Stream;\nuse futures_util::{future, stream, StreamExt};\nuse http_body_util::BodyExt;\n\nuse super::Body;\nuse crate::header::HeaderMap;\n\n/// An async multipart/form-data request.\npub struct Form {\n    inner: FormParts<Part>,\n}\n\n/// A field in a multipart form.\npub struct Part {\n    meta: PartMetadata,\n    value: Body,\n    body_length: Option<u64>,\n}\n\npub(crate) struct FormParts<P> {\n    pub(crate) boundary: String,\n    pub(crate) computed_headers: Vec<Vec<u8>>,\n    pub(crate) fields: Vec<(Cow<'static, str>, P)>,\n    pub(crate) percent_encoding: PercentEncoding,\n}\n\npub(crate) struct PartMetadata {\n    mime: Option<Mime>,\n    file_name: Option<Cow<'static, str>>,\n    pub(crate) headers: HeaderMap,\n}\n\npub(crate) trait PartProps {\n    fn value_len(&self) -> Option<u64>;\n    fn metadata(&self) -> &PartMetadata;\n}\n\n// ===== impl Form =====\n\nimpl Default for Form {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl Form {\n    /// Creates a new async Form without any content.\n    pub fn new() -> Form {\n        Form {\n            inner: FormParts::new(),\n        }\n    }\n\n    /// Get the boundary that this form will use.\n    #[inline]\n    pub fn boundary(&self) -> &str {\n        self.inner.boundary()\n    }\n\n    /// Add a data field with supplied name and value.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// let form = reqwest::multipart::Form::new()\n    ///     .text(\"username\", \"seanmonstar\")\n    ///     .text(\"password\", \"secret\");\n    /// ```\n    pub fn text<T, U>(self, name: T, value: U) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n        U: Into<Cow<'static, str>>,\n    {\n        self.part(name, Part::text(value))\n    }\n\n    /// Adds a file field.\n    ///\n    /// The path will be used to try to guess the filename and mime.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// # async fn run() -> std::io::Result<()> {\n    /// let form = reqwest::multipart::Form::new()\n    ///     .file(\"key\", \"/path/to/file\").await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Errors\n    ///\n    /// Errors when the file cannot be opened.\n    #[cfg(feature = \"stream\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"stream\")))]\n    pub async fn file<T, U>(self, name: T, path: U) -> io::Result<Form>\n    where\n        T: Into<Cow<'static, str>>,\n        U: AsRef<Path>,\n    {\n        Ok(self.part(name, Part::file(path).await?))\n    }\n\n    /// Adds a customized Part.\n    pub fn part<T>(self, name: T, part: Part) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.part(name, part))\n    }\n\n    /// Configure this `Form` to percent-encode using the `path-segment` rules.\n    pub fn percent_encode_path_segment(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_path_segment())\n    }\n\n    /// Configure this `Form` to percent-encode using the `attr-char` rules.\n    pub fn percent_encode_attr_chars(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_attr_chars())\n    }\n\n    /// Configure this `Form` to skip percent-encoding\n    pub fn percent_encode_noop(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_noop())\n    }\n\n    /// Consume this instance and transform into an instance of Body for use in a request.\n    pub(crate) fn stream(self) -> Body {\n        if self.inner.fields.is_empty() {\n            return Body::empty();\n        }\n\n        Body::stream(self.into_stream())\n    }\n\n    /// Produce a stream of the bytes in this `Form`, consuming it.\n    pub fn into_stream(mut self) -> impl Stream<Item = Result<Bytes, crate::Error>> + Send + Sync {\n        if self.inner.fields.is_empty() {\n            let empty_stream: Pin<\n                Box<dyn Stream<Item = Result<Bytes, crate::Error>> + Send + Sync>,\n            > = Box::pin(futures_util::stream::empty());\n            return empty_stream;\n        }\n\n        // create initial part to init reduce chain\n        let (name, part) = self.inner.fields.remove(0);\n        let start = Box::pin(self.part_stream(name, part))\n            as Pin<Box<dyn Stream<Item = crate::Result<Bytes>> + Send + Sync>>;\n\n        let fields = self.inner.take_fields();\n        // for each field, chain an additional stream\n        let stream = fields.into_iter().fold(start, |memo, (name, part)| {\n            let part_stream = self.part_stream(name, part);\n            Box::pin(memo.chain(part_stream))\n                as Pin<Box<dyn Stream<Item = crate::Result<Bytes>> + Send + Sync>>\n        });\n        // append special ending boundary\n        let last = stream::once(future::ready(Ok(\n            format!(\"--{}--\\r\\n\", self.boundary()).into()\n        )));\n        Box::pin(stream.chain(last))\n    }\n\n    /// Generate a hyper::Body stream for a single Part instance of a Form request.\n    pub(crate) fn part_stream<T>(\n        &mut self,\n        name: T,\n        part: Part,\n    ) -> impl Stream<Item = Result<Bytes, crate::Error>>\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        // start with boundary\n        let boundary = stream::once(future::ready(Ok(\n            format!(\"--{}\\r\\n\", self.boundary()).into()\n        )));\n        // append headers\n        let header = stream::once(future::ready(Ok({\n            let mut h = self\n                .inner\n                .percent_encoding\n                .encode_headers(&name.into(), &part.meta);\n            h.extend_from_slice(b\"\\r\\n\\r\\n\");\n            h.into()\n        })));\n        // then append form data followed by terminating CRLF\n        boundary\n            .chain(header)\n            .chain(part.value.into_data_stream())\n            .chain(stream::once(future::ready(Ok(\"\\r\\n\".into()))))\n    }\n\n    pub(crate) fn compute_length(&mut self) -> Option<u64> {\n        self.inner.compute_length()\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(FormParts<Part>) -> FormParts<Part>,\n    {\n        Form {\n            inner: func(self.inner),\n        }\n    }\n}\n\nimpl fmt::Debug for Form {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.inner.fmt_fields(\"Form\", f)\n    }\n}\n\n// ===== impl Part =====\n\nimpl Part {\n    /// Makes a text parameter.\n    pub fn text<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(string) => Body::from(string),\n        };\n        Part::new(body, None)\n    }\n\n    /// Makes a new parameter from arbitrary bytes.\n    pub fn bytes<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, [u8]>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(vec) => Body::from(vec),\n        };\n        Part::new(body, None)\n    }\n\n    /// Makes a new parameter from an arbitrary stream.\n    pub fn stream<T: Into<Body>>(value: T) -> Part {\n        Part::new(value.into(), None)\n    }\n\n    /// Makes a new parameter from an arbitrary stream with a known length. This is particularly\n    /// useful when adding something like file contents as a stream, where you can know the content\n    /// length beforehand.\n    pub fn stream_with_length<T: Into<Body>>(value: T, length: u64) -> Part {\n        Part::new(value.into(), Some(length))\n    }\n\n    /// Makes a file parameter.\n    ///\n    /// # Errors\n    ///\n    /// Errors when the file cannot be opened.\n    #[cfg(feature = \"stream\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"stream\")))]\n    pub async fn file<T: AsRef<Path>>(path: T) -> io::Result<Part> {\n        let path = path.as_ref();\n        let file_name = path\n            .file_name()\n            .map(|filename| filename.to_string_lossy().into_owned());\n        let ext = path.extension().and_then(|ext| ext.to_str()).unwrap_or(\"\");\n        let mime = mime_guess::from_ext(ext).first_or_octet_stream();\n        let file = File::open(path).await?;\n        let len = file.metadata().await.map(|m| m.len()).ok();\n        let field = match len {\n            Some(len) => Part::stream_with_length(file, len),\n            None => Part::stream(file),\n        }\n        .mime(mime);\n\n        Ok(if let Some(file_name) = file_name {\n            field.file_name(file_name)\n        } else {\n            field\n        })\n    }\n\n    fn new(value: Body, body_length: Option<u64>) -> Part {\n        Part {\n            meta: PartMetadata::new(),\n            value,\n            body_length,\n        }\n    }\n\n    /// Tries to set the mime of this part.\n    pub fn mime_str(self, mime: &str) -> crate::Result<Part> {\n        Ok(self.mime(mime.parse().map_err(crate::error::builder)?))\n    }\n\n    // Re-export when mime 0.4 is available, with split MediaType/MediaRange.\n    fn mime(self, mime: Mime) -> Part {\n        self.with_inner(move |inner| inner.mime(mime))\n    }\n\n    /// Sets the filename, builder style.\n    pub fn file_name<T>(self, filename: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.file_name(filename))\n    }\n\n    /// Sets custom headers for the part.\n    pub fn headers(self, headers: HeaderMap) -> Part {\n        self.with_inner(move |inner| inner.headers(headers))\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(PartMetadata) -> PartMetadata,\n    {\n        Part {\n            meta: func(self.meta),\n            ..self\n        }\n    }\n}\n\nimpl fmt::Debug for Part {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut dbg = f.debug_struct(\"Part\");\n        dbg.field(\"value\", &self.value);\n        self.meta.fmt_fields(&mut dbg);\n        dbg.finish()\n    }\n}\n\nimpl PartProps for Part {\n    fn value_len(&self) -> Option<u64> {\n        if self.body_length.is_some() {\n            self.body_length\n        } else {\n            self.value.content_length()\n        }\n    }\n\n    fn metadata(&self) -> &PartMetadata {\n        &self.meta\n    }\n}\n\n// ===== impl FormParts =====\n\nimpl<P: PartProps> FormParts<P> {\n    pub(crate) fn new() -> Self {\n        FormParts {\n            boundary: gen_boundary(),\n            computed_headers: Vec::new(),\n            fields: Vec::new(),\n            percent_encoding: PercentEncoding::PathSegment,\n        }\n    }\n\n    pub(crate) fn boundary(&self) -> &str {\n        &self.boundary\n    }\n\n    /// Adds a customized Part.\n    pub(crate) fn part<T>(mut self, name: T, part: P) -> Self\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.fields.push((name.into(), part));\n        self\n    }\n\n    /// Configure this `Form` to percent-encode using the `path-segment` rules.\n    pub(crate) fn percent_encode_path_segment(mut self) -> Self {\n        self.percent_encoding = PercentEncoding::PathSegment;\n        self\n    }\n\n    /// Configure this `Form` to percent-encode using the `attr-char` rules.\n    pub(crate) fn percent_encode_attr_chars(mut self) -> Self {\n        self.percent_encoding = PercentEncoding::AttrChar;\n        self\n    }\n\n    /// Configure this `Form` to skip percent-encoding\n    pub(crate) fn percent_encode_noop(mut self) -> Self {\n        self.percent_encoding = PercentEncoding::NoOp;\n        self\n    }\n\n    // If predictable, computes the length the request will have\n    // The length should be predictable if only String and file fields have been added,\n    // but not if a generic reader has been added;\n    pub(crate) fn compute_length(&mut self) -> Option<u64> {\n        let mut length = 0u64;\n        for &(ref name, ref field) in self.fields.iter() {\n            match field.value_len() {\n                Some(value_length) => {\n                    // We are constructing the header just to get its length. To not have to\n                    // construct it again when the request is sent we cache these headers.\n                    let header = self.percent_encoding.encode_headers(name, field.metadata());\n                    let header_length = header.len();\n                    self.computed_headers.push(header);\n                    // The additions mimic the format string out of which the field is constructed\n                    // in Reader. Not the cleanest solution because if that format string is\n                    // ever changed then this formula needs to be changed too which is not an\n                    // obvious dependency in the code.\n                    length += 2\n                        + self.boundary().len() as u64\n                        + 2\n                        + header_length as u64\n                        + 4\n                        + value_length\n                        + 2\n                }\n                _ => return None,\n            }\n        }\n        // If there is at least one field there is a special boundary for the very last field.\n        if !self.fields.is_empty() {\n            length += 2 + self.boundary().len() as u64 + 4\n        }\n        Some(length)\n    }\n\n    /// Take the fields vector of this instance, replacing with an empty vector.\n    fn take_fields(&mut self) -> Vec<(Cow<'static, str>, P)> {\n        std::mem::replace(&mut self.fields, Vec::new())\n    }\n}\n\nimpl<P: fmt::Debug> FormParts<P> {\n    pub(crate) fn fmt_fields(&self, ty_name: &'static str, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(ty_name)\n            .field(\"boundary\", &self.boundary)\n            .field(\"parts\", &self.fields)\n            .finish()\n    }\n}\n\n// ===== impl PartMetadata =====\n\nimpl PartMetadata {\n    pub(crate) fn new() -> Self {\n        PartMetadata {\n            mime: None,\n            file_name: None,\n            headers: HeaderMap::default(),\n        }\n    }\n\n    pub(crate) fn mime(mut self, mime: Mime) -> Self {\n        self.mime = Some(mime);\n        self\n    }\n\n    pub(crate) fn file_name<T>(mut self, filename: T) -> Self\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.file_name = Some(filename.into());\n        self\n    }\n\n    pub(crate) fn headers<T>(mut self, headers: T) -> Self\n    where\n        T: Into<HeaderMap>,\n    {\n        self.headers = headers.into();\n        self\n    }\n}\n\nimpl PartMetadata {\n    pub(crate) fn fmt_fields<'f, 'fa, 'fb>(\n        &self,\n        debug_struct: &'f mut fmt::DebugStruct<'fa, 'fb>,\n    ) -> &'f mut fmt::DebugStruct<'fa, 'fb> {\n        debug_struct\n            .field(\"mime\", &self.mime)\n            .field(\"file_name\", &self.file_name)\n            .field(\"headers\", &self.headers)\n    }\n}\n\n// https://url.spec.whatwg.org/#fragment-percent-encode-set\nconst FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS\n    .add(b' ')\n    .add(b'\"')\n    .add(b'<')\n    .add(b'>')\n    .add(b'`');\n\n// https://url.spec.whatwg.org/#path-percent-encode-set\nconst PATH_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'#').add(b'?').add(b'{').add(b'}');\n\nconst PATH_SEGMENT_ENCODE_SET: &AsciiSet = &PATH_ENCODE_SET.add(b'/').add(b'%');\n\n// https://tools.ietf.org/html/rfc8187#section-3.2.1\nconst ATTR_CHAR_ENCODE_SET: &AsciiSet = &NON_ALPHANUMERIC\n    .remove(b'!')\n    .remove(b'#')\n    .remove(b'$')\n    .remove(b'&')\n    .remove(b'+')\n    .remove(b'-')\n    .remove(b'.')\n    .remove(b'^')\n    .remove(b'_')\n    .remove(b'`')\n    .remove(b'|')\n    .remove(b'~');\n\npub(crate) enum PercentEncoding {\n    PathSegment,\n    AttrChar,\n    NoOp,\n}\n\nimpl PercentEncoding {\n    pub(crate) fn encode_headers(&self, name: &str, field: &PartMetadata) -> Vec<u8> {\n        let mut buf = Vec::new();\n        buf.extend_from_slice(b\"Content-Disposition: form-data; \");\n\n        match self.percent_encode(name) {\n            Cow::Borrowed(value) => {\n                // nothing has been percent encoded\n                buf.extend_from_slice(b\"name=\\\"\");\n                buf.extend_from_slice(value.as_bytes());\n                buf.extend_from_slice(b\"\\\"\");\n            }\n            Cow::Owned(value) => {\n                // something has been percent encoded\n                buf.extend_from_slice(b\"name*=utf-8''\");\n                buf.extend_from_slice(value.as_bytes());\n            }\n        }\n\n        // According to RFC7578 Section 4.2, `filename*=` syntax is invalid.\n        // See https://github.com/seanmonstar/reqwest/issues/419.\n        if let Some(filename) = &field.file_name {\n            buf.extend_from_slice(b\"; filename=\\\"\");\n            let legal_filename = filename\n                .replace('\\\\', \"\\\\\\\\\")\n                .replace('\"', \"\\\\\\\"\")\n                .replace('\\r', \"\\\\\\r\")\n                .replace('\\n', \"\\\\\\n\");\n            buf.extend_from_slice(legal_filename.as_bytes());\n            buf.extend_from_slice(b\"\\\"\");\n        }\n\n        if let Some(mime) = &field.mime {\n            buf.extend_from_slice(b\"\\r\\nContent-Type: \");\n            buf.extend_from_slice(mime.as_ref().as_bytes());\n        }\n\n        for (k, v) in field.headers.iter() {\n            buf.extend_from_slice(b\"\\r\\n\");\n            buf.extend_from_slice(k.as_str().as_bytes());\n            buf.extend_from_slice(b\": \");\n            buf.extend_from_slice(v.as_bytes());\n        }\n        buf\n    }\n\n    fn percent_encode<'a>(&self, value: &'a str) -> Cow<'a, str> {\n        use percent_encoding::utf8_percent_encode as percent_encode;\n\n        match self {\n            Self::PathSegment => percent_encode(value, PATH_SEGMENT_ENCODE_SET).into(),\n            Self::AttrChar => percent_encode(value, ATTR_CHAR_ENCODE_SET).into(),\n            Self::NoOp => value.into(),\n        }\n    }\n}\n\nfn gen_boundary() -> String {\n    use crate::util::fast_random as random;\n\n    let a = random();\n    let b = random();\n    let c = random();\n    let d = random();\n\n    format!(\"{a:016x}-{b:016x}-{c:016x}-{d:016x}\")\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use futures_util::stream;\n    use futures_util::TryStreamExt;\n    use std::future;\n    use tokio::{self, runtime};\n\n    #[test]\n    fn form_empty() {\n        let form = Form::new();\n\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let body = form.stream().into_data_stream();\n        let s = body.map_ok(|try_c| try_c.to_vec()).try_concat();\n\n        let out = rt.block_on(s);\n        assert!(out.unwrap().is_empty());\n    }\n\n    #[test]\n    fn stream_to_end() {\n        let mut form = Form::new()\n            .part(\n                \"reader1\",\n                Part::stream(Body::stream(stream::once(future::ready::<\n                    Result<String, crate::Error>,\n                >(Ok(\n                    \"part1\".to_owned()\n                ))))),\n            )\n            .part(\"key1\", Part::text(\"value1\"))\n            .part(\n                \"key2\",\n                Part::text(\"value2\").mime(mime_guess::mime::IMAGE_BMP),\n            )\n            .part(\n                \"reader2\",\n                Part::stream(Body::stream(stream::once(future::ready::<\n                    Result<String, crate::Error>,\n                >(Ok(\n                    \"part2\".to_owned()\n                ))))),\n            )\n            .part(\"key3\", Part::text(\"value3\").file_name(\"filename\"));\n        form.inner.boundary = \"boundary\".to_string();\n        let expected = \"--boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"reader1\\\"\\r\\n\\r\\n\\\n             part1\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key1\\\"\\r\\n\\r\\n\\\n             value1\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key2\\\"\\r\\n\\\n             Content-Type: image/bmp\\r\\n\\r\\n\\\n             value2\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"reader2\\\"\\r\\n\\r\\n\\\n             part2\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key3\\\"; filename=\\\"filename\\\"\\r\\n\\r\\n\\\n             value3\\r\\n--boundary--\\r\\n\";\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let body = form.stream().into_data_stream();\n        let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();\n\n        let out = rt.block_on(s).unwrap();\n        // These prints are for debug purposes in case the test fails\n        println!(\n            \"START REAL\\n{}\\nEND REAL\",\n            std::str::from_utf8(&out).unwrap()\n        );\n        println!(\"START EXPECTED\\n{expected}\\nEND EXPECTED\");\n        assert_eq!(std::str::from_utf8(&out).unwrap(), expected);\n    }\n\n    #[test]\n    fn stream_to_end_with_header() {\n        let mut part = Part::text(\"value2\").mime(mime_guess::mime::IMAGE_BMP);\n        let mut headers = HeaderMap::new();\n        headers.insert(\"Hdr3\", \"/a/b/c\".parse().unwrap());\n        part = part.headers(headers);\n        let mut form = Form::new().part(\"key2\", part);\n        form.inner.boundary = \"boundary\".to_string();\n        let expected = \"--boundary\\r\\n\\\n                        Content-Disposition: form-data; name=\\\"key2\\\"\\r\\n\\\n                        Content-Type: image/bmp\\r\\n\\\n                        hdr3: /a/b/c\\r\\n\\\n                        \\r\\n\\\n                        value2\\r\\n\\\n                        --boundary--\\r\\n\";\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let body = form.stream().into_data_stream();\n        let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();\n\n        let out = rt.block_on(s).unwrap();\n        // These prints are for debug purposes in case the test fails\n        println!(\n            \"START REAL\\n{}\\nEND REAL\",\n            std::str::from_utf8(&out).unwrap()\n        );\n        println!(\"START EXPECTED\\n{expected}\\nEND EXPECTED\");\n        assert_eq!(std::str::from_utf8(&out).unwrap(), expected);\n    }\n\n    #[test]\n    fn correct_content_length() {\n        // Setup an arbitrary data stream\n        let stream_data = b\"just some stream data\";\n        let stream_len = stream_data.len();\n        let stream_data = stream_data\n            .chunks(3)\n            .map(|c| Ok::<_, std::io::Error>(Bytes::from(c)));\n        let the_stream = futures_util::stream::iter(stream_data);\n\n        let bytes_data = b\"some bytes data\".to_vec();\n        let bytes_len = bytes_data.len();\n\n        let stream_part = Part::stream_with_length(Body::stream(the_stream), stream_len as u64);\n        let body_part = Part::bytes(bytes_data);\n\n        // A simple check to make sure we get the configured body length\n        assert_eq!(stream_part.value_len().unwrap(), stream_len as u64);\n\n        // Make sure it delegates to the underlying body if length is not specified\n        assert_eq!(body_part.value_len().unwrap(), bytes_len as u64);\n    }\n\n    #[test]\n    fn header_percent_encoding() {\n        let name = \"start%'\\\"\\r\\nßend\";\n        let field = Part::text(\"\");\n\n        assert_eq!(\n            PercentEncoding::PathSegment.encode_headers(name, &field.meta),\n            &b\"Content-Disposition: form-data; name*=utf-8''start%25'%22%0D%0A%C3%9Fend\"[..]\n        );\n\n        assert_eq!(\n            PercentEncoding::AttrChar.encode_headers(name, &field.meta),\n            &b\"Content-Disposition: form-data; name*=utf-8''start%25%27%22%0D%0A%C3%9Fend\"[..]\n        );\n    }\n}\n"
  },
  {
    "path": "src/async_impl/request.rs",
    "content": "use std::convert::TryFrom;\nuse std::fmt;\nuse std::future::Future;\nuse std::time::Duration;\n\n#[cfg(any(feature = \"query\", feature = \"form\", feature = \"json\"))]\nuse serde::Serialize;\n#[cfg(feature = \"json\")]\nuse serde_json;\n\nuse super::body::Body;\nuse super::client::{Client, Pending};\n#[cfg(feature = \"multipart\")]\nuse super::multipart;\nuse super::response::Response;\nuse crate::config::{RequestConfig, TotalTimeout};\n#[cfg(feature = \"multipart\")]\nuse crate::header::CONTENT_LENGTH;\n#[cfg(any(feature = \"multipart\", feature = \"form\", feature = \"json\"))]\nuse crate::header::CONTENT_TYPE;\nuse crate::header::{HeaderMap, HeaderName, HeaderValue};\nuse crate::{Method, Url};\nuse http::{request::Parts, Extensions, Request as HttpRequest, Version};\n\n/// A request which can be executed with `Client::execute()`.\npub struct Request {\n    method: Method,\n    url: Url,\n    headers: HeaderMap,\n    body: Option<Body>,\n    version: Version,\n    extensions: Extensions,\n}\n\n/// A builder to construct the properties of a `Request`.\n///\n/// To construct a `RequestBuilder`, refer to the `Client` documentation.\n#[must_use = \"RequestBuilder does nothing until you 'send' it\"]\npub struct RequestBuilder {\n    client: Client,\n    request: crate::Result<Request>,\n}\n\nimpl Request {\n    /// Constructs a new request.\n    #[inline]\n    pub fn new(method: Method, url: Url) -> Self {\n        Request {\n            method,\n            url,\n            headers: HeaderMap::new(),\n            body: None,\n            version: Version::default(),\n            extensions: Extensions::new(),\n        }\n    }\n\n    /// Get the method.\n    #[inline]\n    pub fn method(&self) -> &Method {\n        &self.method\n    }\n\n    /// Get a mutable reference to the method.\n    #[inline]\n    pub fn method_mut(&mut self) -> &mut Method {\n        &mut self.method\n    }\n\n    /// Get the url.\n    #[inline]\n    pub fn url(&self) -> &Url {\n        &self.url\n    }\n\n    /// Get a mutable reference to the url.\n    #[inline]\n    pub fn url_mut(&mut self) -> &mut Url {\n        &mut self.url\n    }\n\n    /// Get the headers.\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        &self.headers\n    }\n\n    /// Get a mutable reference to the headers.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        &mut self.headers\n    }\n\n    /// Get the body.\n    #[inline]\n    pub fn body(&self) -> Option<&Body> {\n        self.body.as_ref()\n    }\n\n    /// Get a mutable reference to the body.\n    #[inline]\n    pub fn body_mut(&mut self) -> &mut Option<Body> {\n        &mut self.body\n    }\n\n    /// Get the extensions.\n    #[inline]\n    pub(crate) fn extensions(&self) -> &Extensions {\n        &self.extensions\n    }\n\n    /// Get a mutable reference to the extensions.\n    #[inline]\n    pub(crate) fn extensions_mut(&mut self) -> &mut Extensions {\n        &mut self.extensions\n    }\n\n    /// Get the timeout.\n    #[inline]\n    pub fn timeout(&self) -> Option<&Duration> {\n        RequestConfig::<TotalTimeout>::get(&self.extensions)\n    }\n\n    /// Get a mutable reference to the timeout.\n    #[inline]\n    pub fn timeout_mut(&mut self) -> &mut Option<Duration> {\n        RequestConfig::<TotalTimeout>::get_mut(&mut self.extensions)\n    }\n\n    /// Get the http version.\n    #[inline]\n    pub fn version(&self) -> Version {\n        self.version\n    }\n\n    /// Get a mutable reference to the http version.\n    #[inline]\n    pub fn version_mut(&mut self) -> &mut Version {\n        &mut self.version\n    }\n\n    /// Attempt to clone the request.\n    ///\n    /// `None` is returned if the request can not be cloned, i.e. if the body is a stream.\n    pub fn try_clone(&self) -> Option<Request> {\n        let body = match self.body.as_ref() {\n            Some(body) => Some(body.try_clone()?),\n            None => None,\n        };\n        let mut req = Request::new(self.method().clone(), self.url().clone());\n        *req.timeout_mut() = self.timeout().copied();\n        *req.headers_mut() = self.headers().clone();\n        *req.version_mut() = self.version();\n        *req.extensions_mut() = self.extensions().clone();\n        req.body = body;\n        Some(req)\n    }\n\n    pub(super) fn pieces(self) -> (Method, Url, HeaderMap, Option<Body>, Version, Extensions) {\n        (\n            self.method,\n            self.url,\n            self.headers,\n            self.body,\n            self.version,\n            self.extensions,\n        )\n    }\n}\n\nimpl RequestBuilder {\n    pub(super) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder {\n        let mut builder = RequestBuilder { client, request };\n\n        let auth = builder\n            .request\n            .as_mut()\n            .ok()\n            .and_then(|req| extract_authority(&mut req.url));\n\n        if let Some((username, password)) = auth {\n            builder.basic_auth(username, password)\n        } else {\n            builder\n        }\n    }\n\n    /// Assemble a builder starting from an existing `Client` and a `Request`.\n    pub fn from_parts(client: Client, request: Request) -> RequestBuilder {\n        RequestBuilder {\n            client,\n            request: crate::Result::Ok(request),\n        }\n    }\n\n    /// Add a `Header` to this Request.\n    pub fn header<K, V>(self, key: K, value: V) -> RequestBuilder\n    where\n        HeaderName: TryFrom<K>,\n        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,\n        HeaderValue: TryFrom<V>,\n        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,\n    {\n        self.header_sensitive(key, value, false)\n    }\n\n    /// Add a `Header` to this Request with ability to define if `header_value` is sensitive.\n    fn header_sensitive<K, V>(mut self, key: K, value: V, sensitive: bool) -> RequestBuilder\n    where\n        HeaderName: TryFrom<K>,\n        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,\n        HeaderValue: TryFrom<V>,\n        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,\n    {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match <HeaderName as TryFrom<K>>::try_from(key) {\n                Ok(key) => match <HeaderValue as TryFrom<V>>::try_from(value) {\n                    Ok(mut value) => {\n                        // We want to potentially make an non-sensitive header\n                        // to be sensitive, not the reverse. So, don't turn off\n                        // a previously sensitive header.\n                        if sensitive {\n                            value.set_sensitive(true);\n                        }\n                        req.headers_mut().append(key, value);\n                    }\n                    Err(e) => error = Some(crate::error::builder(e.into())),\n                },\n                Err(e) => error = Some(crate::error::builder(e.into())),\n            };\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Add a set of Headers to the existing ones on this Request.\n    ///\n    /// The headers will be merged in to any already set.\n    pub fn headers(mut self, headers: crate::header::HeaderMap) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            crate::util::replace_headers(req.headers_mut(), headers);\n        }\n        self\n    }\n\n    /// Enable HTTP basic authentication.\n    ///\n    /// ```rust\n    /// # use reqwest::Error;\n    ///\n    /// # async fn run() -> Result<(), Error> {\n    /// let client = reqwest::Client::new();\n    /// let resp = client.delete(\"http://httpbin.org/delete\")\n    ///     .basic_auth(\"admin\", Some(\"good password\"))\n    ///     .send()\n    ///     .await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> RequestBuilder\n    where\n        U: fmt::Display,\n        P: fmt::Display,\n    {\n        let header_value = crate::util::basic_auth(username, password);\n        self.header_sensitive(crate::header::AUTHORIZATION, header_value, true)\n    }\n\n    /// Enable HTTP bearer authentication.\n    pub fn bearer_auth<T>(self, token: T) -> RequestBuilder\n    where\n        T: fmt::Display,\n    {\n        let header_value = format!(\"Bearer {token}\");\n        self.header_sensitive(crate::header::AUTHORIZATION, header_value, true)\n    }\n\n    /// Set the request body.\n    pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.body_mut() = Some(body.into());\n        }\n        self\n    }\n\n    /// Enables a request timeout.\n    ///\n    /// The timeout is applied from when the request starts connecting until the\n    /// response body has finished. It affects only this request and overrides\n    /// the timeout configured using `ClientBuilder::timeout()`.\n    pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.timeout_mut() = Some(timeout);\n        }\n        self\n    }\n\n    /// Sends a multipart/form-data body.\n    ///\n    /// ```\n    /// # use reqwest::Error;\n    ///\n    /// # async fn run() -> Result<(), Error> {\n    /// let client = reqwest::Client::new();\n    /// let form = reqwest::multipart::Form::new()\n    ///     .text(\"key3\", \"value3\")\n    ///     .text(\"key4\", \"value4\");\n    ///\n    ///\n    /// let response = client.post(\"your url\")\n    ///     .multipart(form)\n    ///     .send()\n    ///     .await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// In additional the request's body, the Content-Type and Content-Length fields are\n    /// appropriately set.\n    #[cfg(feature = \"multipart\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"multipart\")))]\n    pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder {\n        let mut builder = self.header(\n            CONTENT_TYPE,\n            format!(\"multipart/form-data; boundary={}\", multipart.boundary()).as_str(),\n        );\n\n        builder = match multipart.compute_length() {\n            Some(length) => builder.header(CONTENT_LENGTH, length),\n            None => builder,\n        };\n\n        if let Ok(ref mut req) = builder.request {\n            *req.body_mut() = Some(multipart.stream())\n        }\n        builder\n    }\n\n    /// Modify the query string of the URL.\n    ///\n    /// Modifies the URL of this request, adding the parameters provided.\n    /// This method appends and does not overwrite. This means that it can\n    /// be called multiple times and that existing query parameters are not\n    /// overwritten if the same key is used. The key will simply show up\n    /// twice in the query string.\n    /// Calling `.query(&[(\"foo\", \"a\"), (\"foo\", \"b\")])` gives `\"foo=a&foo=b\"`.\n    ///\n    /// # Note\n    /// This method does not support serializing a single key-value\n    /// pair. Instead of using `.query((\"key\", \"val\"))`, use a sequence, such\n    /// as `.query(&[(\"key\", \"val\")])`. It's also possible to serialize structs\n    /// and maps into a key-value pair.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `query` feature to be enabled.\n    ///\n    /// # Errors\n    /// This method will fail if the object you provide cannot be serialized\n    /// into a query string.\n    #[cfg(feature = \"query\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"query\")))]\n    pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            let url = req.url_mut();\n            let mut pairs = url.query_pairs_mut();\n            let serializer = serde_urlencoded::Serializer::new(&mut pairs);\n\n            if let Err(err) = query.serialize(serializer) {\n                error = Some(crate::error::builder(err));\n            }\n        }\n        if let Ok(ref mut req) = self.request {\n            if let Some(\"\") = req.url().query() {\n                req.url_mut().set_query(None);\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Set HTTP version\n    pub fn version(mut self, version: Version) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.version = version;\n        }\n        self\n    }\n\n    /// Send a form body.\n    ///\n    /// Sets the body to the url encoded serialization of the passed value,\n    /// and also sets the `Content-Type: application/x-www-form-urlencoded`\n    /// header.\n    ///\n    /// ```rust\n    /// # use reqwest::Error;\n    /// # use std::collections::HashMap;\n    /// #\n    /// # async fn run() -> Result<(), Error> {\n    /// let mut params = HashMap::new();\n    /// params.insert(\"lang\", \"rust\");\n    ///\n    /// let client = reqwest::Client::new();\n    /// let res = client.post(\"http://httpbin.org\")\n    ///     .form(&params)\n    ///     .send()\n    ///     .await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `form` feature to be enabled.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if the passed value cannot be serialized into\n    /// url encoded format\n    #[cfg(feature = \"form\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"form\")))]\n    pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_urlencoded::to_string(form) {\n                Ok(body) => {\n                    req.headers_mut()\n                        .entry(CONTENT_TYPE)\n                        .or_insert(HeaderValue::from_static(\n                            \"application/x-www-form-urlencoded\",\n                        ));\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Send a JSON body.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `json` feature enabled.\n    ///\n    /// # Errors\n    ///\n    /// Serialization can fail if `T`'s implementation of `Serialize` decides to\n    /// fail, or if `T` contains a map with non-string keys.\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_json::to_vec(json) {\n                Ok(body) => {\n                    req.headers_mut()\n                        .entry(CONTENT_TYPE)\n                        .or_insert_with(|| HeaderValue::from_static(\"application/json\"));\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    pub fn build(self) -> crate::Result<Request> {\n        self.request\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    ///\n    /// This is similar to [`RequestBuilder::build()`], but also returns the\n    /// embedded `Client`.\n    pub fn build_split(self) -> (Client, crate::Result<Request>) {\n        (self.client, self.request)\n    }\n\n    /// Constructs the Request and sends it to the target URL, returning a\n    /// future Response.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request,\n    /// redirect loop was detected or redirect limit was exhausted.\n    ///\n    /// # Example\n    ///\n    /// ```no_run\n    /// # use reqwest::Error;\n    /// #\n    /// # async fn run() -> Result<(), Error> {\n    /// let response = reqwest::Client::new()\n    ///     .get(\"https://hyper.rs\")\n    ///     .send()\n    ///     .await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn send(self) -> impl Future<Output = Result<Response, crate::Error>> {\n        match self.request {\n            Ok(req) => self.client.execute_request(req),\n            Err(err) => Pending::new_err(err),\n        }\n    }\n\n    /// Attempt to clone the RequestBuilder.\n    ///\n    /// `None` is returned if the RequestBuilder can not be cloned,\n    /// i.e. if the request body is a stream.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use reqwest::Error;\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let client = reqwest::Client::new();\n    /// let builder = client.post(\"http://httpbin.org/post\")\n    ///     .body(\"from a &str!\");\n    /// let clone = builder.try_clone();\n    /// assert!(clone.is_some());\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn try_clone(&self) -> Option<RequestBuilder> {\n        self.request\n            .as_ref()\n            .ok()\n            .and_then(|req| req.try_clone())\n            .map(|req| RequestBuilder {\n                client: self.client.clone(),\n                request: Ok(req),\n            })\n    }\n}\n\nimpl fmt::Debug for Request {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt_request_fields(&mut f.debug_struct(\"Request\"), self).finish()\n    }\n}\n\nimpl fmt::Debug for RequestBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"RequestBuilder\");\n        match self.request {\n            Ok(ref req) => fmt_request_fields(&mut builder, req).finish(),\n            Err(ref err) => builder.field(\"error\", err).finish(),\n        }\n    }\n}\n\nfn fmt_request_fields<'a, 'b>(\n    f: &'a mut fmt::DebugStruct<'a, 'b>,\n    req: &Request,\n) -> &'a mut fmt::DebugStruct<'a, 'b> {\n    f.field(\"method\", &req.method)\n        .field(\"url\", &req.url)\n        .field(\"headers\", &req.headers)\n}\n\n/// Check the request URL for a \"username:password\" type authority, and if\n/// found, remove it from the URL and return it.\npub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>)> {\n    use percent_encoding::percent_decode;\n\n    if url.has_authority() {\n        let username: String = percent_decode(url.username().as_bytes())\n            .decode_utf8()\n            .ok()?\n            .into();\n        let password = url.password().and_then(|pass| {\n            percent_decode(pass.as_bytes())\n                .decode_utf8()\n                .ok()\n                .map(String::from)\n        });\n        if !username.is_empty() || password.is_some() {\n            url.set_username(\"\")\n                .expect(\"has_authority means set_username shouldn't fail\");\n            url.set_password(None)\n                .expect(\"has_authority means set_password shouldn't fail\");\n            return Some((username, password));\n        }\n    }\n\n    None\n}\n\nimpl<T> TryFrom<HttpRequest<T>> for Request\nwhere\n    T: Into<Body>,\n{\n    type Error = crate::Error;\n\n    fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {\n        let (parts, body) = req.into_parts();\n        let Parts {\n            method,\n            uri,\n            headers,\n            version,\n            extensions,\n            ..\n        } = parts;\n        let url = Url::parse(&uri.to_string()).map_err(crate::error::builder)?;\n        Ok(Request {\n            method,\n            url,\n            headers,\n            body: Some(body.into()),\n            version,\n            extensions,\n        })\n    }\n}\n\nimpl TryFrom<Request> for HttpRequest<Body> {\n    type Error = crate::Error;\n\n    fn try_from(req: Request) -> crate::Result<Self> {\n        let Request {\n            method,\n            url,\n            headers,\n            body,\n            version,\n            extensions,\n            ..\n        } = req;\n\n        let mut req = HttpRequest::builder()\n            .version(version)\n            .method(method)\n            .uri(url.as_str())\n            .body(body.unwrap_or_else(Body::empty))\n            .map_err(crate::error::builder)?;\n\n        *req.headers_mut() = headers;\n        *req.extensions_mut() = extensions;\n        Ok(req)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #![cfg(not(feature = \"rustls-no-provider\"))]\n\n    use super::*;\n    #[cfg(feature = \"query\")]\n    use std::collections::BTreeMap;\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_append() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url);\n\n        let r = r.query(&[(\"foo\", \"bar\")]);\n        let r = r.query(&[(\"qux\", 3)]);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=3\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_append_same() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url);\n\n        let r = r.query(&[(\"foo\", \"a\"), (\"foo\", \"b\")]);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=a&foo=b\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_struct() {\n        #[derive(Serialize)]\n        struct Params {\n            foo: String,\n            qux: i32,\n        }\n\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url);\n\n        let params = Params {\n            foo: \"bar\".into(),\n            qux: 3,\n        };\n\n        let r = r.query(&params);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=3\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_map() {\n        let mut params = BTreeMap::new();\n        params.insert(\"foo\", \"bar\");\n        params.insert(\"qux\", \"three\");\n\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url);\n\n        let r = r.query(&params);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=three\"));\n    }\n\n    #[test]\n    fn test_replace_headers() {\n        use http::HeaderMap;\n\n        let mut headers = HeaderMap::new();\n        headers.insert(\"foo\", \"bar\".parse().unwrap());\n        headers.append(\"foo\", \"baz\".parse().unwrap());\n\n        let client = Client::new();\n        let req = client\n            .get(\"https://hyper.rs\")\n            .header(\"im-a\", \"keeper\")\n            .header(\"foo\", \"pop me\")\n            .headers(headers)\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.headers()[\"im-a\"], \"keeper\");\n\n        let foo = req.headers().get_all(\"foo\").iter().collect::<Vec<_>>();\n        assert_eq!(foo.len(), 2);\n        assert_eq!(foo[0], \"bar\");\n        assert_eq!(foo[1], \"baz\");\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn normalize_empty_query() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let empty_query: &[(&str, &str)] = &[];\n\n        let req = client\n            .get(some_url)\n            .query(empty_query)\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().query(), None);\n        assert_eq!(req.url().as_str(), \"https://google.com/\");\n    }\n\n    #[test]\n    fn try_clone_reusable() {\n        let client = Client::new();\n        let builder = client\n            .post(\"http://httpbin.org/post\")\n            .header(\"foo\", \"bar\")\n            .body(\"from a &str!\");\n        let req = builder\n            .try_clone()\n            .expect(\"clone successful\")\n            .build()\n            .expect(\"request is valid\");\n        assert_eq!(req.url().as_str(), \"http://httpbin.org/post\");\n        assert_eq!(req.method(), Method::POST);\n        assert_eq!(req.headers()[\"foo\"], \"bar\");\n    }\n\n    #[test]\n    fn try_clone_no_body() {\n        let client = Client::new();\n        let builder = client.get(\"http://httpbin.org/get\");\n        let req = builder\n            .try_clone()\n            .expect(\"clone successful\")\n            .build()\n            .expect(\"request is valid\");\n        assert_eq!(req.url().as_str(), \"http://httpbin.org/get\");\n        assert_eq!(req.method(), Method::GET);\n        assert!(req.body().is_none());\n    }\n\n    #[test]\n    #[cfg(feature = \"stream\")]\n    fn try_clone_stream() {\n        let chunks: Vec<Result<_, ::std::io::Error>> = vec![Ok(\"hello\"), Ok(\" \"), Ok(\"world\")];\n        let stream = futures_util::stream::iter(chunks);\n        let client = Client::new();\n        let builder = client\n            .get(\"http://httpbin.org/get\")\n            .body(super::Body::wrap_stream(stream));\n        let clone = builder.try_clone();\n        assert!(clone.is_none());\n    }\n\n    #[test]\n    fn convert_url_authority_into_basic_auth() {\n        let client = Client::new();\n        let some_url = \"https://Aladdin:open sesame@localhost/\";\n\n        let req = client.get(some_url).build().expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(\n            req.headers()[\"authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n    }\n\n    #[test]\n    fn test_basic_auth_sensitive_header() {\n        let client = Client::new();\n        let some_url = \"https://localhost/\";\n\n        let req = client\n            .get(some_url)\n            .basic_auth(\"Aladdin\", Some(\"open sesame\"))\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(\n            req.headers()[\"authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n        assert!(req.headers()[\"authorization\"].is_sensitive());\n    }\n\n    #[test]\n    fn test_bearer_auth_sensitive_header() {\n        let client = Client::new();\n        let some_url = \"https://localhost/\";\n\n        let req = client\n            .get(some_url)\n            .bearer_auth(\"Hold my bear\")\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(req.headers()[\"authorization\"], \"Bearer Hold my bear\");\n        assert!(req.headers()[\"authorization\"].is_sensitive());\n    }\n\n    #[test]\n    fn test_explicit_sensitive_header() {\n        let client = Client::new();\n        let some_url = \"https://localhost/\";\n\n        let mut header = http::HeaderValue::from_static(\"in plain sight\");\n        header.set_sensitive(true);\n\n        let req = client\n            .get(some_url)\n            .header(\"hiding\", header)\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(req.headers()[\"hiding\"], \"in plain sight\");\n        assert!(req.headers()[\"hiding\"].is_sensitive());\n    }\n\n    #[test]\n    fn convert_from_http_request() {\n        let http_request = HttpRequest::builder()\n            .method(\"GET\")\n            .uri(\"http://localhost/\")\n            .header(\"User-Agent\", \"my-awesome-agent/1.0\")\n            .body(\"test test test\")\n            .unwrap();\n        let req: Request = Request::try_from(http_request).unwrap();\n        assert!(req.body().is_some());\n        let test_data = b\"test test test\";\n        assert_eq!(req.body().unwrap().as_bytes(), Some(&test_data[..]));\n        let headers = req.headers();\n        assert_eq!(headers.get(\"User-Agent\").unwrap(), \"my-awesome-agent/1.0\");\n        assert_eq!(req.method(), Method::GET);\n        assert_eq!(req.url().as_str(), \"http://localhost/\");\n    }\n\n    #[test]\n    fn set_http_request_version() {\n        let http_request = HttpRequest::builder()\n            .method(\"GET\")\n            .uri(\"http://localhost/\")\n            .header(\"User-Agent\", \"my-awesome-agent/1.0\")\n            .version(Version::HTTP_11)\n            .body(\"test test test\")\n            .unwrap();\n        let req: Request = Request::try_from(http_request).unwrap();\n        assert!(req.body().is_some());\n        let test_data = b\"test test test\";\n        assert_eq!(req.body().unwrap().as_bytes(), Some(&test_data[..]));\n        let headers = req.headers();\n        assert_eq!(headers.get(\"User-Agent\").unwrap(), \"my-awesome-agent/1.0\");\n        assert_eq!(req.method(), Method::GET);\n        assert_eq!(req.url().as_str(), \"http://localhost/\");\n        assert_eq!(req.version(), Version::HTTP_11);\n    }\n\n    #[test]\n    fn builder_split_reassemble() {\n        let builder = {\n            let client = Client::new();\n            client.get(\"http://example.com\")\n        };\n        let (client, inner) = builder.build_split();\n        let request = inner.unwrap();\n        let builder = RequestBuilder::from_parts(client, request);\n        builder.build().unwrap();\n    }\n\n    /*\n    use {body, Method};\n    use super::Client;\n    use header::{Host, Headers, ContentType};\n    use std::collections::HashMap;\n    use serde_urlencoded;\n    use serde_json;\n\n    #[test]\n    fn basic_get_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Get);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_head_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.head(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Head);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_post_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Post);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_put_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.put(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Put);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_patch_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.patch(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Patch);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_delete_request() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let r = client.delete(some_url).unwrap().build();\n\n        assert_eq!(r.method, Method::Delete);\n        assert_eq!(r.url.as_str(), some_url);\n    }\n\n    #[test]\n    fn add_header() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let header = Host {\n            hostname: \"google.com\".to_string(),\n            port: None,\n        };\n\n        // Add a copy of the header to the request builder\n        let r = r.header(header.clone()).build();\n\n        // then check it was actually added\n        assert_eq!(r.headers.get::<Host>(), Some(&header));\n    }\n\n    #[test]\n    fn add_headers() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let header = Host {\n            hostname: \"google.com\".to_string(),\n            port: None,\n        };\n\n        let mut headers = Headers::new();\n        headers.set(header);\n\n        // Add a copy of the headers to the request builder\n        let r = r.headers(headers.clone()).build();\n\n        // then make sure they were added correctly\n        assert_eq!(r.headers, headers);\n    }\n\n    #[test]\n    fn add_headers_multi() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let header = Host {\n            hostname: \"google.com\".to_string(),\n            port: None,\n        };\n\n        let mut headers = Headers::new();\n        headers.set(header);\n\n        // Add a copy of the headers to the request builder\n        let r = r.headers(headers.clone()).build();\n\n        // then make sure they were added correctly\n        assert_eq!(r.headers, headers);\n    }\n\n    #[test]\n    fn add_body() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let body = \"Some interesting content\";\n\n        let r = r.body(body).build();\n\n        let buf = body::read_to_string(r.body.unwrap()).unwrap();\n\n        assert_eq!(buf, body);\n    }\n\n    #[test]\n    fn add_form() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let mut form_data = HashMap::new();\n        form_data.insert(\"foo\", \"bar\");\n\n        let r = r.form(&form_data).unwrap().build();\n\n        // Make sure the content type was set\n        assert_eq!(r.headers.get::<ContentType>(),\n                   Some(&ContentType::form_url_encoded()));\n\n        let buf = body::read_to_string(r.body.unwrap()).unwrap();\n\n        let body_should_be = serde_urlencoded::to_string(&form_data).unwrap();\n        assert_eq!(buf, body_should_be);\n    }\n\n    #[test]\n    fn add_json() {\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n\n        let mut json_data = HashMap::new();\n        json_data.insert(\"foo\", \"bar\");\n\n        let r = r.json(&json_data).unwrap().build();\n\n        // Make sure the content type was set\n        assert_eq!(r.headers.get::<ContentType>(), Some(&ContentType::json()));\n\n        let buf = body::read_to_string(r.body.unwrap()).unwrap();\n\n        let body_should_be = serde_json::to_string(&json_data).unwrap();\n        assert_eq!(buf, body_should_be);\n    }\n\n    #[test]\n    fn add_json_fail() {\n        use serde::{Serialize, Serializer};\n        use serde::ser::Error;\n        struct MyStruct;\n        impl Serialize for MyStruct {\n            fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>\n                where S: Serializer\n                {\n                    Err(S::Error::custom(\"nope\"))\n                }\n        }\n\n        let client = Client::new().unwrap();\n        let some_url = \"https://google.com/\";\n        let mut r = client.post(some_url).unwrap();\n        let json_data = MyStruct{};\n        assert!(r.json(&json_data).unwrap_err().is_serialization());\n    }\n    */\n}\n"
  },
  {
    "path": "src/async_impl/response.rs",
    "content": "use std::fmt;\nuse std::net::SocketAddr;\nuse std::pin::Pin;\nuse std::time::Duration;\n\nuse bytes::Bytes;\nuse http_body_util::BodyExt;\nuse hyper::{HeaderMap, StatusCode, Version};\nuse hyper_util::client::legacy::connect::HttpInfo;\n#[cfg(feature = \"json\")]\nuse serde::de::DeserializeOwned;\n#[cfg(feature = \"json\")]\nuse serde_json;\nuse tokio::time::Sleep;\nuse url::Url;\n\nuse super::body::Body;\nuse crate::async_impl::body::ResponseBody;\n#[cfg(feature = \"cookies\")]\nuse crate::cookie;\n\n#[cfg(feature = \"charset\")]\nuse encoding_rs::{Encoding, UTF_8};\n#[cfg(feature = \"charset\")]\nuse mime::Mime;\n\n/// A Response to a submitted `Request`.\npub struct Response {\n    pub(super) res: hyper::Response<ResponseBody>,\n    // Boxed to save space (11 words to 1 word), and it's not accessed\n    // frequently internally.\n    url: Box<Url>,\n}\n\nimpl Response {\n    pub(super) fn new(\n        res: hyper::Response<ResponseBody>,\n        url: Url,\n        total_timeout: Option<Pin<Box<Sleep>>>,\n        read_timeout: Option<Duration>,\n    ) -> Response {\n        let (parts, body) = res.into_parts();\n        let res = hyper::Response::from_parts(\n            parts,\n            super::body::response(body, total_timeout, read_timeout),\n        );\n\n        Response {\n            res,\n            url: Box::new(url),\n        }\n    }\n\n    /// Get the `StatusCode` of this `Response`.\n    #[inline]\n    pub fn status(&self) -> StatusCode {\n        self.res.status()\n    }\n\n    /// Get the HTTP `Version` of this `Response`.\n    #[inline]\n    pub fn version(&self) -> Version {\n        self.res.version()\n    }\n\n    /// Get the `Headers` of this `Response`.\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        self.res.headers()\n    }\n\n    /// Get a mutable reference to the `Headers` of this `Response`.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        self.res.headers_mut()\n    }\n\n    /// Get the content length of the response, if it is known.\n    ///\n    /// This value does not directly represents the value of the `Content-Length`\n    /// header, but rather the size of the response's body. To read the header's\n    /// value, please use the [`Response::headers`] method instead.\n    ///\n    /// Reasons it may not be known:\n    ///\n    /// - The response does not include a body (e.g. it responds to a `HEAD`\n    ///   request).\n    /// - The response is gzipped and automatically decoded (thus changing the\n    ///   actual decoded length).\n    pub fn content_length(&self) -> Option<u64> {\n        use hyper::body::Body;\n\n        Body::size_hint(self.res.body()).exact()\n    }\n\n    /// Retrieve the cookies contained in the response.\n    ///\n    /// Note that invalid 'Set-Cookie' headers will be ignored.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookies<'a>(&'a self) -> impl Iterator<Item = cookie::Cookie<'a>> + 'a {\n        cookie::extract_response_cookies(self.res.headers()).filter_map(Result::ok)\n    }\n\n    /// Get the final `Url` of this `Response`.\n    #[inline]\n    pub fn url(&self) -> &Url {\n        &self.url\n    }\n\n    /// Get the remote address used to get this `Response`.\n    pub fn remote_addr(&self) -> Option<SocketAddr> {\n        self.res\n            .extensions()\n            .get::<HttpInfo>()\n            .map(|info| info.remote_addr())\n    }\n\n    /// Returns a reference to the associated extensions.\n    pub fn extensions(&self) -> &http::Extensions {\n        self.res.extensions()\n    }\n\n    /// Returns a mutable reference to the associated extensions.\n    pub fn extensions_mut(&mut self) -> &mut http::Extensions {\n        self.res.extensions_mut()\n    }\n\n    // body methods\n\n    /// Get the full response text.\n    ///\n    /// This method decodes the response body with BOM sniffing\n    /// and with malformed sequences replaced with the\n    /// [`char::REPLACEMENT_CHARACTER`].\n    /// Encoding is determined from the `charset` parameter of `Content-Type` header,\n    /// and defaults to `utf-8` if not presented.\n    ///\n    /// Note that the BOM is stripped from the returned String.\n    ///\n    /// # Note\n    ///\n    /// If the `charset` feature is disabled the method will only attempt to decode the\n    /// response as UTF-8, regardless of the given `Content-Type`\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let content = reqwest::get(\"http://httpbin.org/range/26\")\n    ///     .await?\n    ///     .text()\n    ///     .await?;\n    ///\n    /// println!(\"text: {content:?}\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub async fn text(self) -> crate::Result<String> {\n        #[cfg(feature = \"charset\")]\n        {\n            self.text_with_charset(\"utf-8\").await\n        }\n\n        #[cfg(not(feature = \"charset\"))]\n        {\n            let full = self.bytes().await?;\n            let text = String::from_utf8_lossy(&full);\n            Ok(text.into_owned())\n        }\n    }\n\n    /// Get the full response text given a specific encoding.\n    ///\n    /// This method decodes the response body with BOM sniffing\n    /// and with malformed sequences replaced with the [`char::REPLACEMENT_CHARACTER`].\n    /// You can provide a default encoding for decoding the raw message, while the\n    /// `charset` parameter of `Content-Type` header is still prioritized. For more information\n    /// about the possible encoding name, please go to [`encoding_rs`] docs.\n    ///\n    /// Note that the BOM is stripped from the returned String.\n    ///\n    /// [`encoding_rs`]: https://docs.rs/encoding_rs/0.8/encoding_rs/#relationship-with-windows-code-pages\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `encoding_rs` feature enabled.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let content = reqwest::get(\"http://httpbin.org/range/26\")\n    ///     .await?\n    ///     .text_with_charset(\"utf-8\")\n    ///     .await?;\n    ///\n    /// println!(\"text: {content:?}\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[cfg(feature = \"charset\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"charset\")))]\n    pub async fn text_with_charset(self, default_encoding: &str) -> crate::Result<String> {\n        let content_type = self\n            .headers()\n            .get(crate::header::CONTENT_TYPE)\n            .and_then(|value| value.to_str().ok())\n            .and_then(|value| value.parse::<Mime>().ok());\n        let encoding_name = content_type\n            .as_ref()\n            .and_then(|mime| mime.get_param(\"charset\").map(|charset| charset.as_str()))\n            .unwrap_or(default_encoding);\n        let encoding = Encoding::for_label(encoding_name.as_bytes()).unwrap_or(UTF_8);\n\n        let full = self.bytes().await?;\n\n        let (text, _, _) = encoding.decode(&full);\n        Ok(text.into_owned())\n    }\n\n    /// Try to deserialize the response body as JSON.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `json` feature enabled.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # extern crate serde;\n    /// #\n    /// # use reqwest::Error;\n    /// # use serde::Deserialize;\n    /// #\n    /// // This `derive` requires the `serde` dependency.\n    /// #[derive(Deserialize)]\n    /// struct Ip {\n    ///     origin: String,\n    /// }\n    ///\n    /// # async fn run() -> Result<(), Error> {\n    /// let ip = reqwest::get(\"http://httpbin.org/ip\")\n    ///     .await?\n    ///     .json::<Ip>()\n    ///     .await?;\n    ///\n    /// println!(\"ip: {}\", ip.origin);\n    /// # Ok(())\n    /// # }\n    /// #\n    /// # fn main() { }\n    /// ```\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the response body is not in JSON format,\n    /// or it cannot be properly deserialized to target type `T`. For more\n    /// details please see [`serde_json::from_reader`].\n    ///\n    /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {\n        let full = self.bytes().await?;\n\n        serde_json::from_slice(&full).map_err(crate::error::decode)\n    }\n\n    /// Get the full response body as `Bytes`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let bytes = reqwest::get(\"http://httpbin.org/ip\")\n    ///     .await?\n    ///     .bytes()\n    ///     .await?;\n    ///\n    /// println!(\"bytes: {bytes:?}\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub async fn bytes(self) -> crate::Result<Bytes> {\n        use http_body_util::BodyExt;\n\n        BodyExt::collect(self.res.into_body())\n            .await\n            .map(|buf| buf.to_bytes())\n            .map_err(crate::error::decode)\n    }\n\n    /// Stream a chunk of the response body.\n    ///\n    /// When the response body has been exhausted, this will return `None`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut res = reqwest::get(\"https://hyper.rs\").await?;\n    ///\n    /// while let Some(chunk) = res.chunk().await? {\n    ///     println!(\"Chunk: {chunk:?}\");\n    /// }\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub async fn chunk(&mut self) -> crate::Result<Option<Bytes>> {\n        use http_body_util::BodyExt;\n\n        // loop to ignore unrecognized frames\n        loop {\n            if let Some(res) = self.res.body_mut().frame().await {\n                let frame = res.map_err(crate::error::decode)?;\n                if let Ok(buf) = frame.into_data() {\n                    return Ok(Some(buf));\n                }\n                // else continue\n            } else {\n                return Ok(None);\n            }\n        }\n    }\n\n    /// Convert the response into a `Stream` of `Bytes` from the body.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use futures_util::StreamExt;\n    ///\n    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut stream = reqwest::get(\"http://httpbin.org/ip\")\n    ///     .await?\n    ///     .bytes_stream();\n    ///\n    /// while let Some(item) = stream.next().await {\n    ///     println!(\"Chunk: {:?}\", item?);\n    /// }\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `stream` feature to be enabled.\n    #[cfg(feature = \"stream\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"stream\")))]\n    pub fn bytes_stream(self) -> impl futures_core::Stream<Item = crate::Result<Bytes>> {\n        http_body_util::BodyDataStream::new(self.res.into_body().map_err(crate::error::decode))\n    }\n\n    // util methods\n\n    /// Turn a response into an error if the server returned an error.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use reqwest::Response;\n    /// fn on_response(res: Response) {\n    ///     match res.error_for_status() {\n    ///         Ok(_res) => (),\n    ///         Err(err) => {\n    ///             // asserting a 400 as an example\n    ///             // it could be any status between 400...599\n    ///             assert_eq!(\n    ///                 err.status(),\n    ///                 Some(reqwest::StatusCode::BAD_REQUEST)\n    ///             );\n    ///         }\n    ///     }\n    /// }\n    /// # fn main() {}\n    /// ```\n    pub fn error_for_status(self) -> crate::Result<Self> {\n        let status = self.status();\n        let reason = self.extensions().get::<hyper::ext::ReasonPhrase>().cloned();\n        if status.is_client_error() || status.is_server_error() {\n            Err(crate::error::status_code(*self.url, status, reason))\n        } else {\n            Ok(self)\n        }\n    }\n\n    /// Turn a reference to a response into an error if the server returned an error.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use reqwest::Response;\n    /// fn on_response(res: &Response) {\n    ///     match res.error_for_status_ref() {\n    ///         Ok(_res) => (),\n    ///         Err(err) => {\n    ///             // asserting a 400 as an example\n    ///             // it could be any status between 400...599\n    ///             assert_eq!(\n    ///                 err.status(),\n    ///                 Some(reqwest::StatusCode::BAD_REQUEST)\n    ///             );\n    ///         }\n    ///     }\n    /// }\n    /// # fn main() {}\n    /// ```\n    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {\n        let status = self.status();\n        let reason = self.extensions().get::<hyper::ext::ReasonPhrase>().cloned();\n        if status.is_client_error() || status.is_server_error() {\n            Err(crate::error::status_code(*self.url.clone(), status, reason))\n        } else {\n            Ok(self)\n        }\n    }\n\n    // private\n\n    // The Response's body is an implementation detail.\n    // You no longer need to get a reference to it, there are async methods\n    // on the `Response` itself.\n    //\n    // This method is just used by the blocking API.\n    #[cfg(feature = \"blocking\")]\n    pub(crate) fn body_mut(&mut self) -> &mut ResponseBody {\n        self.res.body_mut()\n    }\n}\n\nimpl fmt::Debug for Response {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Response\")\n            .field(\"url\", &self.url().as_str())\n            .field(\"status\", &self.status())\n            .field(\"headers\", self.headers())\n            .finish()\n    }\n}\n\n/// A `Response` can be piped as the `Body` of another request.\nimpl From<Response> for Body {\n    fn from(r: Response) -> Body {\n        Body::wrap(r.res.into_body())\n    }\n}\n\n// I'm not sure this conversion is that useful... People should be encouraged\n// to use `http::Response`, not `reqwest::Response`.\nimpl<T: Into<Body>> From<http::Response<T>> for Response {\n    fn from(r: http::Response<T>) -> Response {\n        use crate::response::ResponseUrl;\n\n        let (mut parts, body) = r.into_parts();\n        let body: crate::async_impl::body::Body = body.into();\n        let url = parts\n            .extensions\n            .remove::<ResponseUrl>()\n            .unwrap_or_else(|| ResponseUrl(Url::parse(\"http://no.url.provided.local\").unwrap()));\n        let url = url.0;\n        let res = hyper::Response::from_parts(parts, ResponseBody::new(body.map_err(Into::into)));\n        Response {\n            res,\n            url: Box::new(url),\n        }\n    }\n}\n\n/// A `Response` can be converted into a `http::Response`.\n// It's supposed to be the inverse of the conversion above.\nimpl From<Response> for http::Response<Body> {\n    fn from(r: Response) -> http::Response<Body> {\n        let (parts, body) = r.res.into_parts();\n        let body = Body::wrap(body);\n        http::Response::from_parts(parts, body)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::Response;\n    use crate::ResponseBuilderExt;\n    use http::response::Builder;\n    use url::Url;\n\n    #[test]\n    fn test_from_http_response() {\n        let url = Url::parse(\"http://example.com\").unwrap();\n        let response = Builder::new()\n            .status(200)\n            .url(url.clone())\n            .body(\"foo\")\n            .unwrap();\n        let response = Response::from(response);\n\n        assert_eq!(response.status(), 200);\n        assert_eq!(*response.url(), url);\n    }\n}\n"
  },
  {
    "path": "src/async_impl/upgrade.rs",
    "content": "use std::pin::Pin;\nuse std::task::{self, Poll};\nuse std::{fmt, io};\n\nuse hyper_util::rt::TokioIo;\nuse tokio::io::{AsyncRead, AsyncWrite, ReadBuf};\n\n/// An upgraded HTTP connection.\npub struct Upgraded {\n    inner: TokioIo<hyper::upgrade::Upgraded>,\n}\n\nimpl AsyncRead for Upgraded {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut task::Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        Pin::new(&mut self.inner).poll_read(cx, buf)\n    }\n}\n\nimpl AsyncWrite for Upgraded {\n    fn poll_write(\n        mut self: Pin<&mut Self>,\n        cx: &mut task::Context<'_>,\n        buf: &[u8],\n    ) -> Poll<io::Result<usize>> {\n        Pin::new(&mut self.inner).poll_write(cx, buf)\n    }\n\n    fn poll_write_vectored(\n        mut self: Pin<&mut Self>,\n        cx: &mut task::Context<'_>,\n        bufs: &[io::IoSlice<'_>],\n    ) -> Poll<io::Result<usize>> {\n        Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)\n    }\n\n    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {\n        Pin::new(&mut self.inner).poll_flush(cx)\n    }\n\n    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {\n        Pin::new(&mut self.inner).poll_shutdown(cx)\n    }\n\n    fn is_write_vectored(&self) -> bool {\n        self.inner.is_write_vectored()\n    }\n}\n\nimpl fmt::Debug for Upgraded {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Upgraded\").finish()\n    }\n}\n\nimpl From<hyper::upgrade::Upgraded> for Upgraded {\n    fn from(inner: hyper::upgrade::Upgraded) -> Self {\n        Upgraded {\n            inner: TokioIo::new(inner),\n        }\n    }\n}\n\nimpl super::response::Response {\n    /// Consumes the response and returns a future for a possible HTTP upgrade.\n    pub async fn upgrade(self) -> crate::Result<Upgraded> {\n        hyper::upgrade::on(self.res)\n            .await\n            .map(Upgraded::from)\n            .map_err(crate::error::upgrade)\n    }\n}\n"
  },
  {
    "path": "src/blocking/body.rs",
    "content": "use std::fmt;\nuse std::fs::File;\nuse std::future::Future;\n#[cfg(feature = \"multipart\")]\nuse std::io::Cursor;\nuse std::io::{self, Read};\nuse std::mem::{self, MaybeUninit};\nuse std::ptr;\n\nuse bytes::Bytes;\nuse futures_channel::mpsc;\n\nuse crate::async_impl;\n\n/// The body of a `Request`.\n///\n/// In most cases, this is not needed directly, as the\n/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows\n/// passing many things (like a string or vector of bytes).\n///\n/// [builder]: ./struct.RequestBuilder.html#method.body\n#[derive(Debug)]\npub struct Body {\n    kind: Kind,\n}\n\nimpl Body {\n    /// Instantiate a `Body` from a reader.\n    ///\n    /// # Note\n    ///\n    /// While allowing for many types to be used, these bodies do not have\n    /// a way to reset to the beginning and be reused. This means that when\n    /// encountering a 307 or 308 status code, instead of repeating the\n    /// request at the new location, the `Response` will be returned with\n    /// the redirect status code set.\n    ///\n    /// ```rust\n    /// # use std::fs::File;\n    /// # use reqwest::blocking::Body;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let file = File::open(\"national_secrets.txt\")?;\n    /// let body = Body::new(file);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// If you have a set of bytes, like `String` or `Vec<u8>`, using the\n    /// `From` implementations for `Body` will store the data in a manner\n    /// it can be reused.\n    ///\n    /// ```rust\n    /// # use reqwest::blocking::Body;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let s = \"A stringy body\";\n    /// let body = Body::from(s);\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn new<R: Read + Send + 'static>(reader: R) -> Body {\n        Body {\n            kind: Kind::Reader(Box::from(reader), None),\n        }\n    }\n\n    /// Create a `Body` from a `Read` where the size is known in advance\n    /// but the data should not be fully loaded into memory. This will\n    /// set the `Content-Length` header and stream from the `Read`.\n    ///\n    /// ```rust\n    /// # use std::fs::File;\n    /// # use reqwest::blocking::Body;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let file = File::open(\"a_large_file.txt\")?;\n    /// let file_size = file.metadata()?.len();\n    /// let body = Body::sized(file, file_size);\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn sized<R: Read + Send + 'static>(reader: R, len: u64) -> Body {\n        Body {\n            kind: Kind::Reader(Box::from(reader), Some(len)),\n        }\n    }\n\n    /// Returns the body as a byte slice if the body is already buffered in\n    /// memory. For streamed requests this method returns `None`.\n    pub fn as_bytes(&self) -> Option<&[u8]> {\n        match self.kind {\n            Kind::Reader(_, _) => None,\n            Kind::Bytes(ref bytes) => Some(bytes.as_ref()),\n        }\n    }\n\n    /// Converts streamed requests to their buffered equivalent and\n    /// returns a reference to the buffer. If the request is already\n    /// buffered, this has no effect.\n    ///\n    /// Be aware that for large requests this method is expensive\n    /// and may cause your program to run out of memory.\n    pub fn buffer(&mut self) -> Result<&[u8], crate::Error> {\n        match self.kind {\n            Kind::Reader(ref mut reader, maybe_len) => {\n                let mut bytes = if let Some(len) = maybe_len {\n                    Vec::with_capacity(len as usize)\n                } else {\n                    Vec::new()\n                };\n                io::copy(reader, &mut bytes).map_err(crate::error::builder)?;\n                self.kind = Kind::Bytes(bytes.into());\n                self.buffer()\n            }\n            Kind::Bytes(ref bytes) => Ok(bytes.as_ref()),\n        }\n    }\n\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn len(&self) -> Option<u64> {\n        match self.kind {\n            Kind::Reader(_, len) => len,\n            Kind::Bytes(ref bytes) => Some(bytes.len() as u64),\n        }\n    }\n\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn into_reader(self) -> Reader {\n        match self.kind {\n            Kind::Reader(r, _) => Reader::Reader(r),\n            Kind::Bytes(b) => Reader::Bytes(Cursor::new(b)),\n        }\n    }\n\n    pub(crate) fn into_async(self) -> (Option<Sender>, async_impl::Body, Option<u64>) {\n        match self.kind {\n            Kind::Reader(read, len) => {\n                let (tx, rx) = mpsc::channel(0);\n                let tx = Sender {\n                    body: (read, len),\n                    tx,\n                };\n                (Some(tx), async_impl::Body::stream(rx), len)\n            }\n            Kind::Bytes(chunk) => {\n                let len = chunk.len() as u64;\n                (None, async_impl::Body::reusable(chunk), Some(len))\n            }\n        }\n    }\n\n    pub(crate) fn try_clone(&self) -> Option<Body> {\n        self.kind.try_clone().map(|kind| Body { kind })\n    }\n}\n\nenum Kind {\n    Reader(Box<dyn Read + Send>, Option<u64>),\n    Bytes(Bytes),\n}\n\nimpl Kind {\n    fn try_clone(&self) -> Option<Kind> {\n        match self {\n            Kind::Reader(..) => None,\n            Kind::Bytes(v) => Some(Kind::Bytes(v.clone())),\n        }\n    }\n}\n\nimpl From<Vec<u8>> for Body {\n    #[inline]\n    fn from(v: Vec<u8>) -> Body {\n        Body {\n            kind: Kind::Bytes(v.into()),\n        }\n    }\n}\n\nimpl From<String> for Body {\n    #[inline]\n    fn from(s: String) -> Body {\n        s.into_bytes().into()\n    }\n}\n\nimpl From<&'static [u8]> for Body {\n    #[inline]\n    fn from(s: &'static [u8]) -> Body {\n        Body {\n            kind: Kind::Bytes(Bytes::from_static(s)),\n        }\n    }\n}\n\nimpl From<&'static str> for Body {\n    #[inline]\n    fn from(s: &'static str) -> Body {\n        s.as_bytes().into()\n    }\n}\n\nimpl From<File> for Body {\n    #[inline]\n    fn from(f: File) -> Body {\n        let len = f.metadata().map(|m| m.len()).ok();\n        Body {\n            kind: Kind::Reader(Box::new(f), len),\n        }\n    }\n}\nimpl From<Bytes> for Body {\n    #[inline]\n    fn from(b: Bytes) -> Body {\n        Body {\n            kind: Kind::Bytes(b),\n        }\n    }\n}\n\nimpl fmt::Debug for Kind {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match *self {\n            Kind::Reader(_, ref v) => f\n                .debug_struct(\"Reader\")\n                .field(\"length\", &DebugLength(v))\n                .finish(),\n            Kind::Bytes(ref v) => fmt::Debug::fmt(v, f),\n        }\n    }\n}\n\nstruct DebugLength<'a>(&'a Option<u64>);\n\nimpl<'a> fmt::Debug for DebugLength<'a> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match *self.0 {\n            Some(ref len) => fmt::Debug::fmt(len, f),\n            None => f.write_str(\"Unknown\"),\n        }\n    }\n}\n\n#[cfg(feature = \"multipart\")]\npub(crate) enum Reader {\n    Reader(Box<dyn Read + Send>),\n    Bytes(Cursor<Bytes>),\n}\n\n#[cfg(feature = \"multipart\")]\nimpl Read for Reader {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        match *self {\n            Reader::Reader(ref mut rdr) => rdr.read(buf),\n            Reader::Bytes(ref mut rdr) => rdr.read(buf),\n        }\n    }\n}\n\npub(crate) struct Sender {\n    body: (Box<dyn Read + Send>, Option<u64>),\n    tx: mpsc::Sender<Result<Bytes, Abort>>,\n}\n\n#[derive(Debug)]\nstruct Abort;\n\nimpl fmt::Display for Abort {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"abort request body\")\n    }\n}\n\nimpl std::error::Error for Abort {}\n\nasync fn send_future(sender: Sender) -> Result<(), crate::Error> {\n    use bytes::{BufMut, BytesMut};\n    use futures_util::SinkExt;\n    use std::cmp;\n\n    let con_len = sender.body.1;\n    let cap = cmp::min(sender.body.1.unwrap_or(8192), 8192);\n    let mut written = 0;\n    let mut buf = BytesMut::zeroed(cap as usize);\n    buf.clear();\n    let mut body = sender.body.0;\n    // Put in an option so that it can be consumed on error to call abort()\n    let mut tx = Some(sender.tx);\n\n    loop {\n        if Some(written) == con_len {\n            // Written up to content-length, so stop.\n            return Ok(());\n        }\n\n        // The input stream is read only if the buffer is empty so\n        // that there is only one read in the buffer at any time.\n        //\n        // We need to know whether there is any data to send before\n        // we check the transmission channel (with poll_ready below)\n        // because sometimes the receiver disappears as soon as it\n        // considers the data is completely transmitted, which may\n        // be true.\n        //\n        // The use case is a web server that closes its\n        // input stream as soon as the data received is valid JSON.\n        // This behaviour is questionable, but it exists and the\n        // fact is that there is actually no remaining data to read.\n        if buf.is_empty() {\n            if buf.capacity() == buf.len() {\n                buf.reserve(8192);\n                // zero out the reserved memory\n                let uninit = buf.spare_capacity_mut();\n                let uninit_len = uninit.len();\n                unsafe {\n                    ptr::write_bytes(uninit.as_mut_ptr().cast::<u8>(), 0, uninit_len);\n                }\n            }\n\n            let bytes = unsafe {\n                mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(buf.spare_capacity_mut())\n            };\n            match body.read(bytes) {\n                Ok(0) => {\n                    // The buffer was empty and nothing's left to\n                    // read. Return.\n                    return Ok(());\n                }\n                Ok(n) => unsafe {\n                    buf.advance_mut(n);\n                },\n                Err(e) => {\n                    let _ = tx\n                        .take()\n                        .expect(\"tx only taken on error\")\n                        .clone()\n                        .try_send(Err(Abort));\n                    return Err(crate::error::body(e));\n                }\n            }\n        }\n\n        // The only way to get here is when the buffer is not empty.\n        // We can check the transmission channel\n\n        let buf_len = buf.len() as u64;\n        tx.as_mut()\n            .expect(\"tx only taken on error\")\n            .send(Ok(buf.split().freeze()))\n            .await\n            .map_err(crate::error::body)?;\n\n        written += buf_len;\n    }\n}\n\nimpl Sender {\n    // A `Future` that may do blocking read calls.\n    // As a `Future`, this integrates easily with `wait::timeout`.\n    pub(crate) fn send(self) -> impl Future<Output = Result<(), crate::Error>> {\n        send_future(self)\n    }\n}\n\n// useful for tests, but not publicly exposed\n#[cfg(test)]\npub(crate) fn read_to_string(mut body: Body) -> io::Result<String> {\n    let mut s = String::new();\n    match body.kind {\n        Kind::Reader(ref mut reader, _) => reader.read_to_string(&mut s),\n        Kind::Bytes(ref mut bytes) => (&**bytes).read_to_string(&mut s),\n    }\n    .map(|_| s)\n}\n"
  },
  {
    "path": "src/blocking/client.rs",
    "content": "#[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\nuse std::any::Any;\nuse std::convert::TryInto;\nuse std::fmt;\nuse std::future::Future;\nuse std::net::IpAddr;\nuse std::net::SocketAddr;\nuse std::sync::Arc;\nuse std::task::{ready, Poll};\nuse std::thread;\nuse std::time::Duration;\n\nuse http::header::HeaderValue;\nuse log::{error, trace};\nuse tokio::sync::{mpsc, oneshot};\nuse tower::Layer;\nuse tower::Service;\n\nuse super::request::{Request, RequestBuilder};\nuse super::response::Response;\nuse super::wait;\nuse crate::connect::sealed::{Conn, Unnameable};\n#[cfg(unix)]\nuse crate::connect::uds::UnixSocketProvider;\nuse crate::connect::BoxedConnectorService;\nuse crate::dns::Resolve;\nuse crate::error::BoxError;\n#[cfg(feature = \"__tls\")]\nuse crate::tls;\n#[cfg(feature = \"__rustls\")]\nuse crate::tls::CertificateRevocationList;\n#[cfg(feature = \"__tls\")]\nuse crate::Certificate;\n#[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\nuse crate::Identity;\nuse crate::{async_impl, header, redirect, IntoUrl, Method, Proxy};\n\n/// A `Client` to make Requests with.\n///\n/// The Client has various configuration values to tweak, but the defaults\n/// are set to what is usually the most commonly desired value. To configure a\n/// `Client`, use `Client::builder()`.\n///\n/// The `Client` holds a connection pool internally, so it is advised that\n/// you create one and **reuse** it.\n///\n/// # Examples\n///\n/// ```rust\n/// use reqwest::blocking::Client;\n/// #\n/// # fn run() -> Result<(), reqwest::Error> {\n/// let client = Client::new();\n/// let resp = client.get(\"http://httpbin.org/\").send()?;\n/// #   drop(resp);\n/// #   Ok(())\n/// # }\n///\n/// ```\n#[derive(Clone)]\npub struct Client {\n    inner: ClientHandle,\n}\n\n/// A `ClientBuilder` can be used to create a `Client` with  custom configuration.\n///\n/// # Example\n///\n/// ```\n/// # fn run() -> Result<(), reqwest::Error> {\n/// use std::time::Duration;\n///\n/// let client = reqwest::blocking::Client::builder()\n///     .timeout(Duration::from_secs(10))\n///     .build()?;\n/// # Ok(())\n/// # }\n/// ```\n#[must_use]\npub struct ClientBuilder {\n    inner: async_impl::ClientBuilder,\n    timeout: Timeout,\n}\n\nimpl Default for ClientBuilder {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl ClientBuilder {\n    /// Constructs a new `ClientBuilder`.\n    ///\n    /// This is the same as `Client::builder()`.\n    pub fn new() -> Self {\n        ClientBuilder {\n            inner: async_impl::ClientBuilder::new(),\n            timeout: Timeout::default(),\n        }\n    }\n}\n\nimpl ClientBuilder {\n    /// Returns a `Client` that uses this `ClientBuilder` configuration.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if TLS backend cannot be initialized, or the resolver\n    /// cannot load the system configuration.\n    ///\n    /// # Panics\n    ///\n    /// This method panics if called from within an async runtime. See docs on\n    /// [`reqwest::blocking`][crate::blocking] for details.\n    pub fn build(self) -> crate::Result<Client> {\n        ClientHandle::new(self).map(|handle| Client { inner: handle })\n    }\n\n    // Higher-level options\n\n    /// Sets the `User-Agent` header to be used by this client.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # fn doc() -> Result<(), reqwest::Error> {\n    /// // Name your user agent after your app?\n    /// static APP_USER_AGENT: &str = concat!(\n    ///     env!(\"CARGO_PKG_NAME\"),\n    ///     \"/\",\n    ///     env!(\"CARGO_PKG_VERSION\"),\n    /// );\n    ///\n    /// let client = reqwest::blocking::Client::builder()\n    ///     .user_agent(APP_USER_AGENT)\n    ///     .build()?;\n    /// let res = client.get(\"https://www.rust-lang.org\").send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn user_agent<V>(self, value: V) -> ClientBuilder\n    where\n        V: TryInto<HeaderValue>,\n        V::Error: Into<http::Error>,\n    {\n        self.with_inner(move |inner| inner.user_agent(value))\n    }\n\n    /// Sets the default headers for every request.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use reqwest::header;\n    /// # fn build_client() -> Result<(), reqwest::Error> {\n    /// let mut headers = header::HeaderMap::new();\n    /// headers.insert(\"X-MY-HEADER\", header::HeaderValue::from_static(\"value\"));\n    /// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static(\"secret\"));\n    ///\n    /// // Consider marking security-sensitive headers with `set_sensitive`.\n    /// let mut auth_value = header::HeaderValue::from_static(\"secret\");\n    /// auth_value.set_sensitive(true);\n    /// headers.insert(header::AUTHORIZATION, auth_value);\n    ///\n    /// // get a client builder\n    /// let client = reqwest::blocking::Client::builder()\n    ///     .default_headers(headers)\n    ///     .build()?;\n    /// let res = client.get(\"https://www.rust-lang.org\").send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn default_headers(self, headers: header::HeaderMap) -> ClientBuilder {\n        self.with_inner(move |inner| inner.default_headers(headers))\n    }\n\n    /// Enable a persistent cookie store for the client.\n    ///\n    /// Cookies received in responses will be preserved and included in\n    /// additional requests.\n    ///\n    /// By default, no cookie store is used.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookie_store(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.cookie_store(enable))\n    }\n\n    /// Set the persistent cookie store for the client.\n    ///\n    /// Cookies received in responses will be passed to this store, and\n    /// additional requests will query this store for cookies.\n    ///\n    /// By default, no cookie store is used.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookie_provider<C: crate::cookie::CookieStore + 'static>(\n        self,\n        cookie_store: Arc<C>,\n    ) -> ClientBuilder {\n        self.with_inner(|inner| inner.cookie_provider(cookie_store))\n    }\n\n    /// Enable auto gzip decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto gzip decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `gzip`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that\n    ///   equals to `gzip`, both values `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `gzip` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `gzip` feature to be enabled\n    #[cfg(feature = \"gzip\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"gzip\")))]\n    pub fn gzip(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.gzip(enable))\n    }\n\n    /// Enable auto brotli decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto brotli decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `br`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that\n    ///   equals to `br`, both values `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `brotli` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `brotli` feature to be enabled\n    #[cfg(feature = \"brotli\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"brotli\")))]\n    pub fn brotli(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.brotli(enable))\n    }\n\n    /// Enable auto zstd decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto zstd decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `zstd`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if its headers contain a `Content-Encoding` value of\n    ///   `zstd`, both `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `zstd` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `zstd` feature to be enabled\n    #[cfg(feature = \"zstd\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"zstd\")))]\n    pub fn zstd(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.zstd(enable))\n    }\n\n    /// Enable auto deflate decompression by checking the `Content-Encoding` response header.\n    ///\n    /// If auto deflate decompression is turned on:\n    ///\n    /// - When sending a request and if the request's headers do not already contain\n    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `deflate`.\n    ///   The request body is **not** automatically compressed.\n    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that\n    ///   equals to `deflate`, both values `Content-Encoding` and `Content-Length` are removed from the\n    ///   headers' set. The response body is automatically decompressed.\n    ///\n    /// If the `deflate` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `deflate` feature to be enabled\n    #[cfg(feature = \"deflate\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"deflate\")))]\n    pub fn deflate(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.deflate(enable))\n    }\n\n    /// Disable auto response body gzip decompression.\n    ///\n    /// This method exists even if the optional `gzip` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use gzip decompression\n    /// even if another dependency were to enable the optional `gzip` feature.\n    pub fn no_gzip(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.no_gzip())\n    }\n\n    /// Disable auto response body brotli decompression.\n    ///\n    /// This method exists even if the optional `brotli` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use brotli decompression\n    /// even if another dependency were to enable the optional `brotli` feature.\n    pub fn no_brotli(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.no_brotli())\n    }\n\n    /// Disable auto response body zstd decompression.\n    ///\n    /// This method exists even if the optional `zstd` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use zstd decompression\n    /// even if another dependency were to enable the optional `zstd` feature.\n    pub fn no_zstd(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.no_zstd())\n    }\n\n    /// Disable auto response body deflate decompression.\n    ///\n    /// This method exists even if the optional `deflate` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use deflate decompression\n    /// even if another dependency were to enable the optional `deflate` feature.\n    pub fn no_deflate(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.no_deflate())\n    }\n\n    // Redirect options\n\n    /// Set a `redirect::Policy` for this client.\n    ///\n    /// Default will follow redirects up to a maximum of 10.\n    pub fn redirect(self, policy: redirect::Policy) -> ClientBuilder {\n        self.with_inner(move |inner| inner.redirect(policy))\n    }\n\n    /// Set a request retry policy.\n    ///\n    /// Default behavior is to retry protocol NACKs.\n    pub fn retry(self, policy: crate::retry::Builder) -> ClientBuilder {\n        self.with_inner(move |inner| inner.retry(policy))\n    }\n\n    /// Enable or disable automatic setting of the `Referer` header.\n    ///\n    /// Default is `true`.\n    pub fn referer(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.referer(enable))\n    }\n\n    // Proxy options\n\n    /// Add a `Proxy` to the list of proxies the `Client` will use.\n    ///\n    /// # Note\n    ///\n    /// Adding a proxy will disable the automatic usage of the \"system\" proxy.\n    pub fn proxy(self, proxy: Proxy) -> ClientBuilder {\n        self.with_inner(move |inner| inner.proxy(proxy))\n    }\n\n    /// Clear all `Proxies`, so `Client` will use no proxy anymore.\n    ///\n    /// # Note\n    /// To add a proxy exclusion list, use [Proxy::no_proxy()]\n    /// on all desired proxies instead.\n    ///\n    /// This also disables the automatic usage of the \"system\" proxy.\n    pub fn no_proxy(self) -> ClientBuilder {\n        self.with_inner(move |inner| inner.no_proxy())\n    }\n\n    // Timeout options\n\n    /// Set a timeout for connect, read and write operations of a `Client`.\n    ///\n    /// Default is 30 seconds.\n    ///\n    /// Pass `None` to disable timeout.\n    pub fn timeout<T>(mut self, timeout: T) -> ClientBuilder\n    where\n        T: Into<Option<Duration>>,\n    {\n        self.timeout = Timeout(timeout.into());\n        self\n    }\n\n    /// Set a timeout for only the connect phase of a `Client`.\n    ///\n    /// Default is `None`.\n    pub fn connect_timeout<T>(self, timeout: T) -> ClientBuilder\n    where\n        T: Into<Option<Duration>>,\n    {\n        let timeout = timeout.into();\n        if let Some(dur) = timeout {\n            self.with_inner(|inner| inner.connect_timeout(dur))\n        } else {\n            self\n        }\n    }\n\n    /// Set whether connections should emit verbose logs.\n    ///\n    /// Enabling this option will emit [log][] messages at the `TRACE` level\n    /// for read and write operations on connections.\n    ///\n    /// [log]: https://crates.io/crates/log\n    pub fn connection_verbose(self, verbose: bool) -> ClientBuilder {\n        self.with_inner(move |inner| inner.connection_verbose(verbose))\n    }\n\n    // HTTP options\n\n    /// Set an optional timeout for idle sockets being kept-alive.\n    ///\n    /// Pass `None` to disable timeout.\n    ///\n    /// Default is 90 seconds.\n    pub fn pool_idle_timeout<D>(self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.with_inner(|inner| inner.pool_idle_timeout(val))\n    }\n\n    /// Sets the maximum idle connection per host allowed in the pool.\n    pub fn pool_max_idle_per_host(self, max: usize) -> ClientBuilder {\n        self.with_inner(move |inner| inner.pool_max_idle_per_host(max))\n    }\n\n    /// Send headers as title case instead of lowercase.\n    pub fn http1_title_case_headers(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http1_title_case_headers())\n    }\n\n    /// Set whether HTTP/1 connections will accept obsolete line folding for\n    /// header values.\n    ///\n    /// Newline codepoints (`\\r` and `\\n`) will be transformed to spaces when\n    /// parsing.\n    pub fn http1_allow_obsolete_multiline_headers_in_responses(self, value: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.http1_allow_obsolete_multiline_headers_in_responses(value))\n    }\n\n    /// Sets whether invalid header lines should be silently ignored in HTTP/1 responses.\n    pub fn http1_ignore_invalid_headers_in_responses(self, value: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.http1_ignore_invalid_headers_in_responses(value))\n    }\n\n    /// Set whether HTTP/1 connections will accept spaces between header\n    /// names and the colon that follow them in responses.\n    ///\n    /// Newline codepoints (\\r and \\n) will be transformed to spaces when\n    /// parsing.\n    pub fn http1_allow_spaces_after_header_name_in_responses(self, value: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.http1_allow_spaces_after_header_name_in_responses(value))\n    }\n\n    /// Only use HTTP/1.\n    pub fn http1_only(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http1_only())\n    }\n\n    /// Allow HTTP/0.9 responses\n    pub fn http09_responses(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http09_responses())\n    }\n\n    /// Only use HTTP/2.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_prior_knowledge(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_prior_knowledge())\n    }\n\n    /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.\n    ///\n    /// Default is currently 65,535 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_initial_stream_window_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_initial_stream_window_size(sz))\n    }\n\n    /// Sets the max connection-level flow control for HTTP2\n    ///\n    /// Default is currently 65,535 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_initial_connection_window_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_initial_connection_window_size(sz))\n    }\n\n    /// Sets whether to use an adaptive flow control.\n    ///\n    /// Enabling this will override the limits set in `http2_initial_stream_window_size` and\n    /// `http2_initial_connection_window_size`.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_adaptive_window(self, enabled: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_adaptive_window(enabled))\n    }\n\n    /// Sets the maximum frame size to use for HTTP2.\n    ///\n    /// Default is currently 16,384 but may change internally to optimize for common uses.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_max_frame_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_max_frame_size(sz))\n    }\n\n    /// Sets the maximum size of received header frames for HTTP2.\n    ///\n    /// Default is currently 16KB, but can change.\n    #[cfg(feature = \"http2\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http2\")))]\n    pub fn http2_max_header_list_size(self, max_header_size_bytes: u32) -> ClientBuilder {\n        self.with_inner(|inner| inner.http2_max_header_list_size(max_header_size_bytes))\n    }\n\n    /// This requires the optional `http3` feature to be\n    /// enabled.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"http3\")))]\n    pub fn http3_prior_knowledge(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_prior_knowledge())\n    }\n\n    /// Maximum duration of inactivity to accept before timing out the QUIC connection.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_max_idle_timeout(self, value: Duration) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_max_idle_timeout(value))\n    }\n\n    /// Maximum number of bytes the peer may transmit without acknowledgement on any one stream\n    /// before becoming blocked.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is over 2^62.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_stream_receive_window(self, value: u64) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_stream_receive_window(value))\n    }\n\n    /// Maximum number of bytes the peer may transmit across all streams of a connection before\n    /// becoming blocked.\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is over 2^62.\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_conn_receive_window(self, value: u64) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_conn_receive_window(value))\n    }\n\n    /// Maximum number of bytes to transmit to a peer without acknowledgment\n    ///\n    /// Please see docs in [`TransportConfig`] in [`quinn`].\n    ///\n    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_send_window(self, value: u64) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_send_window(value))\n    }\n\n    /// Override the default congestion control algorithm to use [BBR]\n    ///\n    /// The current default congestion control algorithm is [CUBIC]. This method overrides the\n    /// default.\n    ///\n    /// [BBR]: https://datatracker.ietf.org/doc/html/draft-ietf-ccwg-bbr\n    /// [CUBIC]: https://datatracker.ietf.org/doc/html/rfc8312\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_congestion_bbr(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_congestion_bbr())\n    }\n\n    /// Set the maximum HTTP/3 header size this client is willing to accept.\n    ///\n    /// See [header size constraints] section of the specification for details.\n    ///\n    /// [header size constraints]: https://www.rfc-editor.org/rfc/rfc9114.html#name-header-size-constraints\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.max_field_section_size\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_max_field_section_size(self, value: u64) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_max_field_section_size(value))\n    }\n\n    /// Enable whether to send HTTP/3 protocol grease on the connections.\n    ///\n    /// HTTP/3 uses the concept of \"grease\"\n    ///\n    /// to prevent potential interoperability issues in the future.\n    /// In HTTP/3, the concept of grease is used to ensure that the protocol can evolve\n    /// and accommodate future changes without breaking existing implementations.\n    ///\n    /// Please see docs in [`Builder`] in [`h3`].\n    ///\n    /// [`Builder`]: https://docs.rs/h3/latest/h3/client/struct.Builder.html#method.send_grease\n    #[cfg(feature = \"http3\")]\n    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = \"http3\",))))]\n    pub fn http3_send_grease(self, enabled: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.http3_send_grease(enabled))\n    }\n\n    // TCP options\n\n    /// Set whether sockets have `TCP_NODELAY` enabled.\n    ///\n    /// Default is `true`.\n    pub fn tcp_nodelay(self, enabled: bool) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tcp_nodelay(enabled))\n    }\n\n    /// Bind to a local IP Address.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use std::net::IpAddr;\n    /// let local_addr = IpAddr::from([12, 4, 1, 8]);\n    /// let client = reqwest::blocking::Client::builder()\n    ///     .local_address(local_addr)\n    ///     .build().unwrap();\n    /// ```\n    pub fn local_address<T>(self, addr: T) -> ClientBuilder\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        self.with_inner(move |inner| inner.local_address(addr))\n    }\n\n    /// Bind to an interface by `SO_BINDTODEVICE`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// let interface = \"lo\";\n    /// let client = reqwest::blocking::Client::builder()\n    ///     .interface(interface)\n    ///     .build().unwrap();\n    /// ```\n    #[cfg(any(\n        target_os = \"android\",\n        target_os = \"fuchsia\",\n        target_os = \"illumos\",\n        target_os = \"ios\",\n        target_os = \"linux\",\n        target_os = \"macos\",\n        target_os = \"solaris\",\n        target_os = \"tvos\",\n        target_os = \"visionos\",\n        target_os = \"watchos\",\n    ))]\n    pub fn interface(self, interface: &str) -> ClientBuilder {\n        self.with_inner(move |inner| inner.interface(interface))\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive<D>(self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.with_inner(move |inner| inner.tcp_keepalive(val))\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied interval.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive_interval<D>(self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.with_inner(move |inner| inner.tcp_keepalive_interval(val))\n    }\n\n    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied retry count.\n    ///\n    /// If `None`, the option will not be set.\n    pub fn tcp_keepalive_retries<C>(self, retries: C) -> ClientBuilder\n    where\n        C: Into<Option<u32>>,\n    {\n        self.with_inner(move |inner| inner.tcp_keepalive_retries(retries))\n    }\n\n    /// Set that all sockets have `TCP_USER_TIMEOUT` set with the supplied duration.\n    ///\n    /// This option controls how long transmitted data may remain unacknowledged before\n    /// the connection is force-closed.\n    ///\n    /// The current default is `None` (option disabled).\n    #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n    pub fn tcp_user_timeout<D>(self, val: D) -> ClientBuilder\n    where\n        D: Into<Option<Duration>>,\n    {\n        self.with_inner(move |inner| inner.tcp_user_timeout(val))\n    }\n\n    // Alt Transports\n\n    /// Set that all connections will use this Unix socket.\n    ///\n    /// If a request URI uses the `https` scheme, TLS will still be used over\n    /// the Unix socket.\n    ///\n    /// # Note\n    ///\n    /// This option is not compatible with any of the TCP or Proxy options.\n    /// Setting this will ignore all those options previously set.\n    ///\n    /// Likewise, DNS resolution will not be done on the domain name.\n    #[cfg(unix)]\n    pub fn unix_socket(self, path: impl UnixSocketProvider) -> ClientBuilder {\n        self.with_inner(move |inner| inner.unix_socket(path))\n    }\n\n    // TLS options\n\n    /// Add custom root certificates.\n    ///\n    /// This allows connecting to a server that has a self-signed\n    /// certificate for example. This **does not** replace the existing\n    /// trusted store.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn build_client() -> Result<(), Box<dyn std::error::Error>> {\n    /// // read a local binary DER encoded certificate\n    /// let der = std::fs::read(\"my-cert.der\")?;\n    ///\n    /// // create a certificate\n    /// let cert = reqwest::Certificate::from_der(&der)?;\n    ///\n    /// // get a client builder\n    /// let client = reqwest::blocking::Client::builder()\n    ///     .tls_certs_merge([cert])\n    ///     .build()?;\n    /// # drop(client);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_certs_merge(self, certs: impl IntoIterator<Item = Certificate>) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_certs_merge(certs))\n    }\n\n    /// Use only the provided certificate roots.\n    ///\n    /// This can be used to connect to a server that has a self-signed\n    /// certificate for example.\n    ///\n    /// This option disables any native or built-in roots, and **only** uses\n    /// the roots provided to this method.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_certs_only(self, certs: impl IntoIterator<Item = Certificate>) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_certs_only(certs))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_certs_merge()`] or [`ClientBuilder::tls_certs_only()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {\n        self.with_inner(move |inner| inner.add_root_certificate(cert))\n    }\n\n    /// Add multiple certificate revocation lists.\n    ///\n    /// # Errors\n    ///\n    /// This only works if also using only provided root certificates. This\n    /// cannot work with the native verifier.\n    ///\n    /// If CRLs are added but `tls_certs_only()` is not called, the builder\n    /// will return an error.\n    ///\n    /// # Optional\n    ///\n    /// This requires the `rustls(-...)` Cargo feature enabled.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn tls_crls_only(\n        self,\n        crls: impl IntoIterator<Item = CertificateRevocationList>,\n    ) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_crls_only(crls))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn add_crl(self, crl: CertificateRevocationList) -> ClientBuilder {\n        self.with_inner(move |inner| inner.add_crl(crl))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn add_crls(\n        self,\n        crls: impl IntoIterator<Item = CertificateRevocationList>,\n    ) -> ClientBuilder {\n        self.with_inner(move |inner| inner.add_crls(crls))\n    }\n\n    /// Sets the identity to be used for client certificate authentication.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `native-tls` or `rustls(-...)` feature to be\n    /// enabled.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\"))]\n    #[cfg_attr(docsrs, doc(cfg(any(feature = \"native-tls\", feature = \"rustls\"))))]\n    pub fn identity(self, identity: Identity) -> ClientBuilder {\n        self.with_inner(move |inner| inner.identity(identity))\n    }\n\n    /// Controls the use of hostname verification.\n    ///\n    /// Defaults to `false`.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before you use this method. If\n    /// hostname verification is not used, any valid certificate for any\n    /// site will be trusted for use from any other. This introduces a\n    /// significant vulnerability to man-in-the-middle attacks.\n    ///\n    /// # Errors\n    ///\n    /// Depending on the TLS backend and verifier, this might not work with\n    /// native certificates, only those added with [`ClientBuilder::tls_certs_only()`].\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_danger_accept_invalid_hostnames(\n        self,\n        accept_invalid_hostname: bool,\n    ) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_danger_accept_invalid_hostnames(accept_invalid_hostname))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_hostnames()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname))\n    }\n\n    /// Controls the use of certificate validation.\n    ///\n    /// Defaults to `false`.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before using this method. If\n    /// invalid certificates are trusted, *any* certificate for *any* site\n    /// will be trusted for use. This includes expired certificates. This\n    /// introduces significant vulnerabilities, and should only be used\n    /// as a last resort.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_danger_accept_invalid_certs(accept_invalid_certs))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_certs()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))\n    }\n\n    /// Controls the use of TLS server name indication.\n    ///\n    /// Defaults to `true`.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_sni(self, tls_sni: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_sni(tls_sni))\n    }\n\n    /// Set the minimum required TLS version for connections.\n    ///\n    /// By default, the TLS backend's own default is used.\n    ///\n    /// # Errors\n    ///\n    /// A value of `tls::Version::TLS_1_3` will cause an error with the\n    /// `native-tls` backend. This does not mean the version\n    /// isn't supported, just that it can't be set as a minimum due to\n    /// technical limitations.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_version_min(self, version: tls::Version) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_version_min(version))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_version_min()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn min_tls_version(self, version: tls::Version) -> ClientBuilder {\n        self.with_inner(|inner| inner.min_tls_version(version))\n    }\n\n    /// Set the maximum allowed TLS version for connections.\n    ///\n    /// By default, there's no maximum.\n    ///\n    /// # Errors\n    ///\n    /// A value of `tls::Version::TLS_1_3` will cause an error with the\n    /// `native-tls` backend. This does not mean the version\n    /// isn't supported, just that it can't be set as a maximum due to\n    /// technical limitations.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_version_max(self, version: tls::Version) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_version_max(version))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_version_max()`] instead.\n    #[cfg(feature = \"__tls\")]\n    pub fn max_tls_version(self, version: tls::Version) -> ClientBuilder {\n        self.with_inner(|inner| inner.max_tls_version(version))\n    }\n\n    /// Force using the native TLS backend.\n    ///\n    /// Since multiple TLS backends can be optionally enabled, this option will\n    /// force the `native-tls` backend to be used for this `Client`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `native-tls` feature to be enabled.\n    #[cfg(feature = \"__native-tls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"native-tls\")))]\n    pub fn tls_backend_native(self) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_backend_native())\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_native()`] instead.\n    #[cfg(feature = \"__native-tls\")]\n    pub fn use_native_tls(self) -> ClientBuilder {\n        self.with_inner(move |inner| inner.use_native_tls())\n    }\n\n    /// Force using the Rustls TLS backend.\n    ///\n    /// Since multiple TLS backends can be optionally enabled, this option will\n    /// force the `rustls` backend to be used for this `Client`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `rustls(-...)` feature to be enabled.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn tls_backend_rustls(self) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_backend_rustls())\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_rustls()`] instead.\n    #[cfg(feature = \"__rustls\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"rustls\")))]\n    pub fn use_rustls_tls(self) -> ClientBuilder {\n        self.with_inner(move |inner| inner.use_rustls_tls())\n    }\n\n    /// Add TLS information as `TlsInfo` extension to responses.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `default-tls`, `native-tls`, or `rustls(-...)`\n    /// feature to be enabled.\n    #[cfg(feature = \"__tls\")]\n    #[cfg_attr(\n        docsrs,\n        doc(cfg(any(feature = \"default-tls\", feature = \"native-tls\", feature = \"rustls\")))\n    )]\n    pub fn tls_info(self, tls_info: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.tls_info(tls_info))\n    }\n\n    /// Use a preconfigured TLS backend.\n    ///\n    /// If the passed `Any` argument is not a TLS backend that reqwest\n    /// understands, the `ClientBuilder` will error when calling `build`.\n    ///\n    /// # Advanced\n    ///\n    /// This is an advanced option, and can be somewhat brittle. Usage requires\n    /// keeping the preconfigured TLS argument version in sync with reqwest,\n    /// since version mismatches will result in an \"unknown\" TLS backend.\n    ///\n    /// If possible, it's preferable to use the methods on `ClientBuilder`\n    /// to configure reqwest's TLS.\n    ///\n    /// # Optional\n    ///\n    /// This requires one of the optional features `native-tls` or\n    /// `rustls(-...)` to be enabled.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n    #[cfg_attr(docsrs, doc(cfg(any(feature = \"native-tls\", feature = \"rustls\"))))]\n    pub fn tls_backend_preconfigured(self, tls: impl Any) -> ClientBuilder {\n        self.with_inner(move |inner| inner.tls_backend_preconfigured(tls))\n    }\n\n    /// Deprecated: use [`ClientBuilder::tls_backend_preconfigured()`] instead.\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n    pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {\n        self.with_inner(move |inner| inner.use_preconfigured_tls(tls))\n    }\n\n    /// Enables the [hickory-dns](hickory_resolver) async resolver instead of a default threadpool using `getaddrinfo`.\n    ///\n    /// If the `hickory-dns` feature is turned on, the default option is enabled.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `hickory-dns` feature to be enabled\n    #[cfg(feature = \"hickory-dns\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"hickory-dns\")))]\n    pub fn hickory_dns(self, enable: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.hickory_dns(enable))\n    }\n\n    /// Disables the hickory-dns async resolver.\n    ///\n    /// This method exists even if the optional `hickory-dns` feature is not enabled.\n    /// This can be used to ensure a `Client` doesn't use the hickory-dns async resolver\n    /// even if another dependency were to enable the optional `hickory-dns` feature.\n    pub fn no_hickory_dns(self) -> ClientBuilder {\n        self.with_inner(|inner| inner.no_hickory_dns())\n    }\n\n    /// Restrict the Client to be used with HTTPS only requests.\n    ///\n    /// Defaults to false.\n    pub fn https_only(self, enabled: bool) -> ClientBuilder {\n        self.with_inner(|inner| inner.https_only(enabled))\n    }\n\n    /// Override DNS resolution for specific domains to a particular IP address.\n    ///\n    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).\n    /// Ports in the URL itself will always be used instead of the port in the overridden addr.\n    pub fn resolve(self, domain: &str, addr: SocketAddr) -> ClientBuilder {\n        self.resolve_to_addrs(domain, &[addr])\n    }\n\n    /// Override DNS resolution for specific domains to particular IP addresses.\n    ///\n    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).\n    /// Ports in the URL itself will always be used instead of the port in the overridden addr.\n    pub fn resolve_to_addrs(self, domain: &str, addrs: &[SocketAddr]) -> ClientBuilder {\n        self.with_inner(|inner| inner.resolve_to_addrs(domain, addrs))\n    }\n\n    /// Override the DNS resolver implementation.\n    ///\n    /// Pass an `Arc` wrapping a trait object implementing `Resolve`.\n    /// Overrides for specific names passed to `resolve` and `resolve_to_addrs` will\n    /// still be applied on top of this resolver.\n    pub fn dns_resolver<R: Resolve + 'static>(self, resolver: Arc<R>) -> ClientBuilder {\n        self.with_inner(|inner| inner.dns_resolver(resolver))\n    }\n\n    /// Adds a new Tower [`Layer`](https://docs.rs/tower/latest/tower/trait.Layer.html) to the\n    /// base connector [`Service`](https://docs.rs/tower/latest/tower/trait.Service.html) which\n    /// is responsible for connection establishment.\n    ///\n    /// Each subsequent invocation of this function will wrap previous layers.\n    ///\n    /// Example usage:\n    /// ```\n    /// use std::time::Duration;\n    ///\n    /// let client = reqwest::blocking::Client::builder()\n    ///                      // resolved to outermost layer, meaning while we are waiting on concurrency limit\n    ///                      .connect_timeout(Duration::from_millis(200))\n    ///                      // underneath the concurrency check, so only after concurrency limit lets us through\n    ///                      .connector_layer(tower::timeout::TimeoutLayer::new(Duration::from_millis(50)))\n    ///                      .connector_layer(tower::limit::concurrency::ConcurrencyLimitLayer::new(2))\n    ///                      .build()\n    ///                      .unwrap();\n    /// ```\n    pub fn connector_layer<L>(self, layer: L) -> ClientBuilder\n    where\n        L: Layer<BoxedConnectorService> + Clone + Send + Sync + 'static,\n        L::Service:\n            Service<Unnameable, Response = Conn, Error = BoxError> + Clone + Send + Sync + 'static,\n        <L::Service as Service<Unnameable>>::Future: Send + 'static,\n    {\n        self.with_inner(|inner| inner.connector_layer(layer))\n    }\n\n    // private\n\n    fn with_inner<F>(mut self, func: F) -> ClientBuilder\n    where\n        F: FnOnce(async_impl::ClientBuilder) -> async_impl::ClientBuilder,\n    {\n        self.inner = func(self.inner);\n        self\n    }\n}\n\nimpl From<async_impl::ClientBuilder> for ClientBuilder {\n    fn from(builder: async_impl::ClientBuilder) -> Self {\n        Self {\n            inner: builder,\n            timeout: Timeout::default(),\n        }\n    }\n}\n\nimpl Default for Client {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl Client {\n    /// Constructs a new `Client`.\n    ///\n    /// # Panic\n    ///\n    /// This method panics if TLS backend cannot be initialized, or the resolver\n    /// cannot load the system configuration.\n    ///\n    /// Use `Client::builder()` if you wish to handle the failure as an `Error`\n    /// instead of panicking.\n    ///\n    /// This method also panics if called from within an async runtime. See docs\n    /// on [`reqwest::blocking`][crate::blocking] for details.\n    pub fn new() -> Client {\n        ClientBuilder::new().build().expect(\"Client::new()\")\n    }\n\n    /// Creates a `ClientBuilder` to configure a `Client`.\n    ///\n    /// This is the same as `ClientBuilder::new()`.\n    pub fn builder() -> ClientBuilder {\n        ClientBuilder::new()\n    }\n\n    /// Convenience method to make a `GET` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::GET, url)\n    }\n\n    /// Convenience method to make a `POST` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::POST, url)\n    }\n\n    /// Convenience method to make a `PUT` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PUT, url)\n    }\n\n    /// Convenience method to make a `PATCH` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PATCH, url)\n    }\n\n    /// Convenience method to make a `DELETE` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::DELETE, url)\n    }\n\n    /// Convenience method to make a `HEAD` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::HEAD, url)\n    }\n\n    /// Start building a `Request` with the `Method` and `Url`.\n    ///\n    /// Returns a `RequestBuilder`, which will allow setting headers and\n    /// request body before sending.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {\n        let req = url.into_url().map(move |url| Request::new(method, url));\n        RequestBuilder::new(self.clone(), req)\n    }\n\n    /// Executes a `Request`.\n    ///\n    /// A `Request` can be built manually with `Request::new()` or obtained\n    /// from a RequestBuilder with `RequestBuilder::build()`.\n    ///\n    /// You should prefer to use the `RequestBuilder` and\n    /// `RequestBuilder::send()`.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request,\n    /// or redirect limit was exhausted.\n    pub fn execute(&self, request: Request) -> crate::Result<Response> {\n        self.inner.execute_request(request)\n    }\n}\n\nimpl fmt::Debug for Client {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Client\")\n            //.field(\"gzip\", &self.inner.gzip)\n            //.field(\"redirect_policy\", &self.inner.redirect_policy)\n            //.field(\"referer\", &self.inner.referer)\n            .finish()\n    }\n}\n\nimpl fmt::Debug for ClientBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\n#[derive(Clone)]\nstruct ClientHandle {\n    timeout: Timeout,\n    inner: Arc<InnerClientHandle>,\n}\n\ntype OneshotResponse = oneshot::Sender<crate::Result<async_impl::Response>>;\ntype ThreadSender = mpsc::UnboundedSender<(async_impl::Request, OneshotResponse)>;\n\nstruct InnerClientHandle {\n    tx: Option<ThreadSender>,\n    thread: Option<thread::JoinHandle<()>>,\n}\n\nimpl Drop for InnerClientHandle {\n    fn drop(&mut self) {\n        let id = self\n            .thread\n            .as_ref()\n            .map(|h| h.thread().id())\n            .expect(\"thread not dropped yet\");\n\n        trace!(\"closing runtime thread ({id:?})\");\n        self.tx.take();\n        trace!(\"signaled close for runtime thread ({id:?})\");\n        self.thread.take().map(|h| h.join());\n        trace!(\"closed runtime thread ({id:?})\");\n    }\n}\n\nimpl ClientHandle {\n    fn new(builder: ClientBuilder) -> crate::Result<ClientHandle> {\n        let timeout = builder.timeout;\n        let builder = builder.inner;\n        let (tx, rx) = mpsc::unbounded_channel::<(async_impl::Request, OneshotResponse)>();\n        let (spawn_tx, spawn_rx) = oneshot::channel::<crate::Result<()>>();\n        let handle = thread::Builder::new()\n            .name(\"reqwest-internal-sync-runtime\".into())\n            .spawn(move || {\n                use tokio::runtime;\n                let rt = match runtime::Builder::new_current_thread()\n                    .enable_all()\n                    .build()\n                    .map_err(crate::error::builder)\n                {\n                    Err(e) => {\n                        if let Err(e) = spawn_tx.send(Err(e)) {\n                            error!(\"Failed to communicate runtime creation failure: {e:?}\");\n                        }\n                        return;\n                    }\n                    Ok(v) => v,\n                };\n\n                let f = async move {\n                    let client = match builder.build() {\n                        Err(e) => {\n                            if let Err(e) = spawn_tx.send(Err(e)) {\n                                error!(\"Failed to communicate client creation failure: {e:?}\");\n                            }\n                            return;\n                        }\n                        Ok(v) => v,\n                    };\n                    if let Err(e) = spawn_tx.send(Ok(())) {\n                        error!(\"Failed to communicate successful startup: {e:?}\");\n                        return;\n                    }\n\n                    let mut rx = rx;\n\n                    while let Some((req, req_tx)) = rx.recv().await {\n                        let req_fut = client.execute(req);\n                        tokio::spawn(forward(req_fut, req_tx));\n                    }\n\n                    trace!(\"({:?}) Receiver is shutdown\", thread::current().id());\n                };\n\n                trace!(\"({:?}) start runtime::block_on\", thread::current().id());\n                rt.block_on(f);\n                trace!(\"({:?}) end runtime::block_on\", thread::current().id());\n                drop(rt);\n                trace!(\"({:?}) finished\", thread::current().id());\n            })\n            .map_err(crate::error::builder)?;\n\n        // Wait for the runtime thread to start up...\n        match wait::timeout(spawn_rx, None) {\n            Ok(Ok(())) => (),\n            Ok(Err(err)) => return Err(err),\n            Err(_canceled) => event_loop_panicked(),\n        }\n\n        let inner_handle = Arc::new(InnerClientHandle {\n            tx: Some(tx),\n            thread: Some(handle),\n        });\n\n        Ok(ClientHandle {\n            timeout,\n            inner: inner_handle,\n        })\n    }\n\n    fn execute_request(&self, req: Request) -> crate::Result<Response> {\n        let (tx, rx) = oneshot::channel();\n        let (req, body) = req.into_async();\n        let url = req.url().clone();\n        let timeout = req.timeout().copied().or(self.timeout.0);\n\n        self.inner\n            .tx\n            .as_ref()\n            .expect(\"core thread exited early\")\n            .send((req, tx))\n            .expect(\"core thread panicked\");\n\n        let result: Result<crate::Result<async_impl::Response>, wait::Waited<crate::Error>> =\n            if let Some(body) = body {\n                let f = async move {\n                    body.send().await?;\n                    rx.await.map_err(|_canceled| event_loop_panicked())\n                };\n                wait::timeout(f, timeout)\n            } else {\n                let f = async move { rx.await.map_err(|_canceled| event_loop_panicked()) };\n                wait::timeout(f, timeout)\n            };\n\n        match result {\n            Ok(Err(err)) => Err(err.with_url(url)),\n            Ok(Ok(res)) => Ok(Response::new(\n                res,\n                timeout,\n                KeepCoreThreadAlive(Some(self.inner.clone())),\n            )),\n            Err(wait::Waited::TimedOut(e)) => Err(crate::error::request(e).with_url(url)),\n            Err(wait::Waited::Inner(err)) => Err(err.with_url(url)),\n        }\n    }\n}\n\nasync fn forward<F>(fut: F, mut tx: OneshotResponse)\nwhere\n    F: Future<Output = crate::Result<async_impl::Response>>,\n{\n    futures_util::pin_mut!(fut);\n\n    // \"select\" on the sender being canceled, and the future completing\n    let res = std::future::poll_fn(|cx| {\n        match fut.as_mut().poll(cx) {\n            Poll::Ready(val) => Poll::Ready(Some(val)),\n            Poll::Pending => {\n                // check if the callback is canceled\n                ready!(tx.poll_closed(cx));\n                Poll::Ready(None)\n            }\n        }\n    })\n    .await;\n\n    if let Some(res) = res {\n        let _ = tx.send(res);\n    }\n    // else request is canceled\n}\n\n#[derive(Clone, Copy)]\nstruct Timeout(Option<Duration>);\n\nimpl Default for Timeout {\n    fn default() -> Timeout {\n        // default mentioned in ClientBuilder::timeout() doc comment\n        Timeout(Some(Duration::from_secs(30)))\n    }\n}\n\npub(crate) struct KeepCoreThreadAlive(#[allow(dead_code)] Option<Arc<InnerClientHandle>>);\n\nimpl KeepCoreThreadAlive {\n    pub(crate) fn empty() -> KeepCoreThreadAlive {\n        KeepCoreThreadAlive(None)\n    }\n}\n\n#[cold]\n#[inline(never)]\nfn event_loop_panicked() -> ! {\n    // The only possible reason there would be a Canceled error\n    // is if the thread running the event loop panicked. We could return\n    // an Err here, like a BrokenPipe, but the Client is not\n    // recoverable. Additionally, the panic in the other thread\n    // is not normal, and should likely be propagated.\n    panic!(\"event loop thread panicked\");\n}\n"
  },
  {
    "path": "src/blocking/mod.rs",
    "content": "//! A blocking Client API.\n//!\n//! The blocking `Client` will block the current thread to execute, instead\n//! of returning futures that need to be executed on a runtime.\n//!\n//! Conversely, the functionality in `reqwest::blocking` must *not* be executed\n//! within an async runtime, or it will panic when attempting to block. If\n//! calling directly from an async function, consider using an async\n//! [`reqwest::Client`][crate::Client] instead. If the immediate context is only\n//! synchronous, but a transitive caller is async, consider changing that caller\n//! to use [`tokio::task::spawn_blocking`] around the calls that need to block.\n//!\n//! # Optional\n//!\n//! This requires the optional `blocking` feature to be enabled.\n//!\n//! # Making a GET request\n//!\n//! For a single request, you can use the [`get`] shortcut method.\n//!\n//! ```rust\n//! # use reqwest::{Error, Response};\n//!\n//! # fn run() -> Result<(), Error> {\n//! let body = reqwest::blocking::get(\"https://www.rust-lang.org\")?\n//!     .text()?;\n//!\n//! println!(\"body = {body:?}\");\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! Additionally, the blocking [`Response`] struct implements Rust's\n//! `Read` trait, so many useful standard library and third party crates will\n//! have convenience methods that take a `Response` anywhere `T: Read` is\n//! acceptable.\n//!\n//! **NOTE**: If you plan to perform multiple requests, it is best to create a\n//! [`Client`] and reuse it, taking advantage of keep-alive connection pooling.\n//!\n//! # Making POST requests (or setting request bodies)\n//!\n//! There are several ways you can set the body of a request. The basic one is\n//! by using the `body()` method of a [`RequestBuilder`]. This lets you set the\n//! exact raw bytes of what the body should be. It accepts various types,\n//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom\n//! Reader, you can use the `reqwest::blocking::Body::new()` constructor.\n//!\n//! ```rust\n//! # use reqwest::Error;\n//! #\n//! # fn run() -> Result<(), Error> {\n//! let client = reqwest::blocking::Client::new();\n//! let res = client.post(\"http://httpbin.org/post\")\n//!     .body(\"the exact body that is sent\")\n//!     .send()?;\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! ## And More\n//!\n//! Most features available to the asynchronous `Client` are also available,\n//! on the blocking `Client`, see those docs for more.\n\nmod body;\nmod client;\n#[cfg(feature = \"multipart\")]\npub mod multipart;\nmod request;\nmod response;\nmod wait;\n\npub use self::body::Body;\npub use self::client::{Client, ClientBuilder};\npub use self::request::{Request, RequestBuilder};\npub use self::response::Response;\n\n/// Shortcut method to quickly make a *blocking* `GET` request.\n///\n/// **NOTE**: This function creates a new internal `Client` on each call,\n/// and so should not be used if making many requests. Create a\n/// [`Client`](./struct.Client.html) instead.\n///\n/// # Examples\n///\n/// ```rust\n/// # fn run() -> Result<(), reqwest::Error> {\n/// let body = reqwest::blocking::get(\"https://www.rust-lang.org\")?\n///     .text()?;\n/// # Ok(())\n/// # }\n/// # fn main() { }\n/// ```\n///\n/// # Errors\n///\n/// This function fails if:\n///\n/// - the native TLS backend cannot be initialized,\n/// - the supplied `Url` cannot be parsed,\n/// - there was an error while sending request,\n/// - a redirect loop was detected,\n/// - the redirect limit was exhausted, or\n/// - the total download time exceeds 30 seconds.\npub fn get<T: crate::IntoUrl>(url: T) -> crate::Result<Response> {\n    Client::builder().build()?.get(url).send()\n}\n"
  },
  {
    "path": "src/blocking/multipart.rs",
    "content": "//! multipart/form-data\n//!\n//! To send a `multipart/form-data` body, a [`Form`] is built up, adding\n//! fields or customized [`Part`]s, and then calling the\n//! [`multipart`][builder] method on the `RequestBuilder`.\n//!\n//! # Example\n//!\n//! ```\n//! use reqwest::blocking::multipart;\n//!\n//! # fn run() -> Result<(), Box<dyn std::error::Error>> {\n//! let form = multipart::Form::new()\n//!     // Adding just a simple text field...\n//!     .text(\"username\", \"seanmonstar\")\n//!     // And a file...\n//!     .file(\"photo\", \"/path/to/photo.png\")?;\n//!\n//! // Customize all the details of a Part if needed...\n//! let bio = multipart::Part::text(\"hallo peeps\")\n//!     .file_name(\"bio.txt\")\n//!     .mime_str(\"text/plain\")?;\n//!\n//! // Add the custom part to our form...\n//! let form = form.part(\"biography\", bio);\n//!\n//! // And finally, send the form\n//! let client = reqwest::blocking::Client::new();\n//! let resp = client\n//!     .post(\"http://localhost:8080/user\")\n//!     .multipart(form)\n//!     .send()?;\n//! # Ok(())\n//! # }\n//! # fn main() {}\n//! ```\n//!\n//! [builder]: ../struct.RequestBuilder.html#method.multipart\nuse std::borrow::Cow;\nuse std::fmt;\nuse std::fs::File;\nuse std::io::{self, Cursor, Read};\nuse std::path::Path;\n\nuse mime_guess::{self, Mime};\n\nuse super::Body;\nuse crate::async_impl::multipart::{FormParts, PartMetadata, PartProps};\nuse crate::header::HeaderMap;\n\n/// A multipart/form-data request.\npub struct Form {\n    inner: FormParts<Part>,\n}\n\n/// A field in a multipart form.\npub struct Part {\n    meta: PartMetadata,\n    value: Body,\n}\n\nimpl Default for Form {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl Form {\n    /// Creates a new Form without any content.\n    pub fn new() -> Form {\n        Form {\n            inner: FormParts::new(),\n        }\n    }\n\n    /// Get the boundary that this form will use.\n    #[inline]\n    pub fn boundary(&self) -> &str {\n        self.inner.boundary()\n    }\n\n    /// Add a data field with supplied name and value.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// let form = reqwest::blocking::multipart::Form::new()\n    ///     .text(\"username\", \"seanmonstar\")\n    ///     .text(\"password\", \"secret\");\n    /// ```\n    pub fn text<T, U>(self, name: T, value: U) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n        U: Into<Cow<'static, str>>,\n    {\n        self.part(name, Part::text(value))\n    }\n\n    /// Adds a file field.\n    ///\n    /// The path will be used to try to guess the filename and mime.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// # fn run() -> std::io::Result<()> {\n    /// let form = reqwest::blocking::multipart::Form::new()\n    ///     .file(\"key\", \"/path/to/file\")?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Errors\n    ///\n    /// Errors when the file cannot be opened.\n    pub fn file<T, U>(self, name: T, path: U) -> io::Result<Form>\n    where\n        T: Into<Cow<'static, str>>,\n        U: AsRef<Path>,\n    {\n        Ok(self.part(name, Part::file(path)?))\n    }\n\n    /// Adds a customized Part.\n    pub fn part<T>(self, name: T, part: Part) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.part(name, part))\n    }\n\n    /// Configure this `Form` to percent-encode using the `path-segment` rules.\n    pub fn percent_encode_path_segment(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_path_segment())\n    }\n\n    /// Configure this `Form` to percent-encode using the `attr-char` rules.\n    pub fn percent_encode_attr_chars(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_attr_chars())\n    }\n\n    /// Configure this `Form` to skip percent-encoding\n    pub fn percent_encode_noop(self) -> Form {\n        self.with_inner(|inner| inner.percent_encode_noop())\n    }\n\n    pub(crate) fn reader(self) -> Reader {\n        Reader::new(self)\n    }\n\n    /// Produce a reader over the multipart form data.\n    pub fn into_reader(self) -> impl Read {\n        self.reader()\n    }\n\n    // If predictable, computes the length the request will have\n    // The length should be predictable if only String and file fields have been added,\n    // but not if a generic reader has been added;\n    pub(crate) fn compute_length(&mut self) -> Option<u64> {\n        self.inner.compute_length()\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(FormParts<Part>) -> FormParts<Part>,\n    {\n        Form {\n            inner: func(self.inner),\n        }\n    }\n}\n\nimpl fmt::Debug for Form {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.inner.fmt_fields(\"Form\", f)\n    }\n}\n\nimpl Part {\n    /// Makes a text parameter.\n    pub fn text<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(string) => Body::from(string),\n        };\n        Part::new(body)\n    }\n\n    /// Makes a new parameter from arbitrary bytes.\n    pub fn bytes<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, [u8]>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(vec) => Body::from(vec),\n        };\n        Part::new(body)\n    }\n\n    /// Adds a generic reader.\n    ///\n    /// Does not set filename or mime.\n    pub fn reader<T: Read + Send + 'static>(value: T) -> Part {\n        Part::new(Body::new(value))\n    }\n\n    /// Adds a generic reader with known length.\n    ///\n    /// Does not set filename or mime.\n    pub fn reader_with_length<T: Read + Send + 'static>(value: T, length: u64) -> Part {\n        Part::new(Body::sized(value, length))\n    }\n\n    /// Makes a file parameter.\n    ///\n    /// # Errors\n    ///\n    /// Errors when the file cannot be opened.\n    pub fn file<T: AsRef<Path>>(path: T) -> io::Result<Part> {\n        let path = path.as_ref();\n        let file_name = path\n            .file_name()\n            .map(|filename| filename.to_string_lossy().into_owned());\n        let ext = path.extension().and_then(|ext| ext.to_str()).unwrap_or(\"\");\n        let mime = mime_guess::from_ext(ext).first_or_octet_stream();\n        let file = File::open(path)?;\n        let field = Part::new(Body::from(file)).mime(mime);\n\n        Ok(if let Some(file_name) = file_name {\n            field.file_name(file_name)\n        } else {\n            field\n        })\n    }\n\n    fn new(value: Body) -> Part {\n        Part {\n            meta: PartMetadata::new(),\n            value,\n        }\n    }\n\n    /// Tries to set the mime of this part.\n    pub fn mime_str(self, mime: &str) -> crate::Result<Part> {\n        Ok(self.mime(mime.parse().map_err(crate::error::builder)?))\n    }\n\n    // Re-export when mime 0.4 is available, with split MediaType/MediaRange.\n    fn mime(self, mime: Mime) -> Part {\n        self.with_inner(move |inner| inner.mime(mime))\n    }\n\n    /// Sets the filename, builder style.\n    pub fn file_name<T>(self, filename: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.file_name(filename))\n    }\n\n    /// Sets custom headers for the part.\n    pub fn headers(self, headers: HeaderMap) -> Part {\n        self.with_inner(move |inner| inner.headers(headers))\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(PartMetadata) -> PartMetadata,\n    {\n        Part {\n            meta: func(self.meta),\n            value: self.value,\n        }\n    }\n}\n\nimpl fmt::Debug for Part {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut dbg = f.debug_struct(\"Part\");\n        dbg.field(\"value\", &self.value);\n        self.meta.fmt_fields(&mut dbg);\n        dbg.finish()\n    }\n}\n\nimpl PartProps for Part {\n    fn value_len(&self) -> Option<u64> {\n        self.value.len()\n    }\n\n    fn metadata(&self) -> &PartMetadata {\n        &self.meta\n    }\n}\n\npub(crate) struct Reader {\n    form: Form,\n    active_reader: Option<Box<dyn Read + Send>>,\n}\n\nimpl fmt::Debug for Reader {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Reader\").field(\"form\", &self.form).finish()\n    }\n}\n\nimpl Reader {\n    fn new(form: Form) -> Reader {\n        let mut reader = Reader {\n            form,\n            active_reader: None,\n        };\n        reader.next_reader();\n        reader\n    }\n\n    fn next_reader(&mut self) {\n        self.active_reader = if !self.form.inner.fields.is_empty() {\n            // We need to move out of the vector here because we are consuming the field's reader\n            let (name, field) = self.form.inner.fields.remove(0);\n            let boundary = Cursor::new(format!(\"--{}\\r\\n\", self.form.boundary()));\n            let header = Cursor::new({\n                // Try to use cached headers created by compute_length\n                let mut h = if !self.form.inner.computed_headers.is_empty() {\n                    self.form.inner.computed_headers.remove(0)\n                } else {\n                    self.form\n                        .inner\n                        .percent_encoding\n                        .encode_headers(&name, field.metadata())\n                };\n                h.extend_from_slice(b\"\\r\\n\\r\\n\");\n                h\n            });\n            let reader = boundary\n                .chain(header)\n                .chain(field.value.into_reader())\n                .chain(Cursor::new(\"\\r\\n\"));\n            // According to https://tools.ietf.org/html/rfc2046#section-5.1.1\n            // the very last field has a special boundary\n            if !self.form.inner.fields.is_empty() {\n                Some(Box::new(reader))\n            } else {\n                Some(Box::new(reader.chain(Cursor::new(format!(\n                    \"--{}--\\r\\n\",\n                    self.form.boundary()\n                )))))\n            }\n        } else {\n            None\n        }\n    }\n}\n\nimpl Read for Reader {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        let mut total_bytes_read = 0usize;\n        let mut last_read_bytes;\n        loop {\n            match self.active_reader {\n                Some(ref mut reader) => {\n                    last_read_bytes = reader.read(&mut buf[total_bytes_read..])?;\n                    total_bytes_read += last_read_bytes;\n                    if total_bytes_read == buf.len() {\n                        return Ok(total_bytes_read);\n                    }\n                }\n                None => return Ok(total_bytes_read),\n            };\n            if last_read_bytes == 0 && !buf.is_empty() {\n                self.next_reader();\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn form_empty() {\n        let mut output = Vec::new();\n        let mut form = Form::new();\n        let length = form.compute_length();\n        form.reader().read_to_end(&mut output).unwrap();\n        assert_eq!(output, b\"\");\n        assert_eq!(length.unwrap(), 0);\n    }\n\n    #[test]\n    fn read_to_end() {\n        let mut output = Vec::new();\n        let mut form = Form::new()\n            .part(\"reader1\", Part::reader(std::io::empty()))\n            .part(\"key1\", Part::text(\"value1\"))\n            .part(\n                \"key2\",\n                Part::text(\"value2\").mime(mime_guess::mime::IMAGE_BMP),\n            )\n            .part(\"reader2\", Part::reader(std::io::empty()))\n            .part(\"key3\", Part::text(\"value3\").file_name(\"filename\"));\n        form.inner.boundary = \"boundary\".to_string();\n        let length = form.compute_length();\n        let expected = \"--boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"reader1\\\"\\r\\n\\r\\n\\\n             \\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key1\\\"\\r\\n\\r\\n\\\n             value1\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key2\\\"\\r\\n\\\n             Content-Type: image/bmp\\r\\n\\r\\n\\\n             value2\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"reader2\\\"\\r\\n\\r\\n\\\n             \\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key3\\\"; filename=\\\"filename\\\"\\r\\n\\r\\n\\\n             value3\\r\\n--boundary--\\r\\n\";\n        form.reader().read_to_end(&mut output).unwrap();\n        // These prints are for debug purposes in case the test fails\n        println!(\n            \"START REAL\\n{}\\nEND REAL\",\n            std::str::from_utf8(&output).unwrap()\n        );\n        println!(\"START EXPECTED\\n{expected}\\nEND EXPECTED\");\n        assert_eq!(std::str::from_utf8(&output).unwrap(), expected);\n        assert!(length.is_none());\n    }\n\n    #[test]\n    fn read_to_end_with_length() {\n        let mut output = Vec::new();\n        let mut form = Form::new()\n            .text(\"key1\", \"value1\")\n            .part(\n                \"key2\",\n                Part::text(\"value2\").mime(mime_guess::mime::IMAGE_BMP),\n            )\n            .part(\"key3\", Part::text(\"value3\").file_name(\"filename\"));\n        form.inner.boundary = \"boundary\".to_string();\n        let length = form.compute_length();\n        let expected = \"--boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key1\\\"\\r\\n\\r\\n\\\n             value1\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key2\\\"\\r\\n\\\n             Content-Type: image/bmp\\r\\n\\r\\n\\\n             value2\\r\\n\\\n             --boundary\\r\\n\\\n             Content-Disposition: form-data; name=\\\"key3\\\"; filename=\\\"filename\\\"\\r\\n\\r\\n\\\n             value3\\r\\n--boundary--\\r\\n\";\n        form.reader().read_to_end(&mut output).unwrap();\n        // These prints are for debug purposes in case the test fails\n        println!(\n            \"START REAL\\n{}\\nEND REAL\",\n            std::str::from_utf8(&output).unwrap()\n        );\n        println!(\"START EXPECTED\\n{expected}\\nEND EXPECTED\");\n        assert_eq!(std::str::from_utf8(&output).unwrap(), expected);\n        assert_eq!(length.unwrap(), expected.len() as u64);\n    }\n\n    #[test]\n    fn read_to_end_with_header() {\n        let mut output = Vec::new();\n        let mut part = Part::text(\"value2\").mime(mime_guess::mime::IMAGE_BMP);\n        let mut headers = HeaderMap::new();\n        headers.insert(\"Hdr3\", \"/a/b/c\".parse().unwrap());\n        part = part.headers(headers);\n        let mut form = Form::new().part(\"key2\", part);\n        form.inner.boundary = \"boundary\".to_string();\n        let expected = \"--boundary\\r\\n\\\n                        Content-Disposition: form-data; name=\\\"key2\\\"\\r\\n\\\n                        Content-Type: image/bmp\\r\\n\\\n                        hdr3: /a/b/c\\r\\n\\\n                        \\r\\n\\\n                        value2\\r\\n\\\n                        --boundary--\\r\\n\";\n        form.reader().read_to_end(&mut output).unwrap();\n        // These prints are for debug purposes in case the test fails\n        println!(\n            \"START REAL\\n{}\\nEND REAL\",\n            std::str::from_utf8(&output).unwrap()\n        );\n        println!(\"START EXPECTED\\n{expected}\\nEND EXPECTED\");\n        assert_eq!(std::str::from_utf8(&output).unwrap(), expected);\n    }\n}\n"
  },
  {
    "path": "src/blocking/request.rs",
    "content": "use std::convert::TryFrom;\nuse std::fmt;\nuse std::time::Duration;\n\nuse http::{request::Parts, Request as HttpRequest, Version};\n#[cfg(any(feature = \"query\", feature = \"form\", feature = \"json\"))]\nuse serde::Serialize;\n#[cfg(feature = \"json\")]\nuse serde_json;\n\nuse super::body::{self, Body};\n#[cfg(feature = \"multipart\")]\nuse super::multipart;\nuse super::Client;\n#[cfg(any(feature = \"multipart\", feature = \"form\", feature = \"json\"))]\nuse crate::header::CONTENT_TYPE;\nuse crate::header::{HeaderMap, HeaderName, HeaderValue};\nuse crate::{async_impl, Method, Url};\n\n/// A request which can be executed with `Client::execute()`.\npub struct Request {\n    body: Option<Body>,\n    inner: async_impl::Request,\n}\n\n/// A builder to construct the properties of a `Request`.\n///\n/// To construct a `RequestBuilder`, refer to the `Client` documentation.\n#[derive(Debug)]\n#[must_use = \"RequestBuilder does nothing until you 'send' it\"]\npub struct RequestBuilder {\n    client: Client,\n    request: crate::Result<Request>,\n}\n\nimpl Request {\n    /// Constructs a new request.\n    #[inline]\n    pub fn new(method: Method, url: Url) -> Self {\n        Request {\n            body: None,\n            inner: async_impl::Request::new(method, url),\n        }\n    }\n\n    /// Get the method.\n    #[inline]\n    pub fn method(&self) -> &Method {\n        self.inner.method()\n    }\n\n    /// Get a mutable reference to the method.\n    #[inline]\n    pub fn method_mut(&mut self) -> &mut Method {\n        self.inner.method_mut()\n    }\n\n    /// Get the url.\n    #[inline]\n    pub fn url(&self) -> &Url {\n        self.inner.url()\n    }\n\n    /// Get a mutable reference to the url.\n    #[inline]\n    pub fn url_mut(&mut self) -> &mut Url {\n        self.inner.url_mut()\n    }\n\n    /// Get the headers.\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        self.inner.headers()\n    }\n\n    /// Get a mutable reference to the headers.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        self.inner.headers_mut()\n    }\n\n    /// Get the http version.\n    #[inline]\n    pub fn version(&self) -> Version {\n        self.inner.version()\n    }\n\n    /// Get a mutable reference to the http version.\n    #[inline]\n    pub fn version_mut(&mut self) -> &mut Version {\n        self.inner.version_mut()\n    }\n\n    /// Get the body.\n    #[inline]\n    pub fn body(&self) -> Option<&Body> {\n        self.body.as_ref()\n    }\n\n    /// Get a mutable reference to the body.\n    #[inline]\n    pub fn body_mut(&mut self) -> &mut Option<Body> {\n        &mut self.body\n    }\n\n    /// Get the timeout.\n    #[inline]\n    pub fn timeout(&self) -> Option<&Duration> {\n        self.inner.timeout()\n    }\n\n    /// Get a mutable reference to the timeout.\n    #[inline]\n    pub fn timeout_mut(&mut self) -> &mut Option<Duration> {\n        self.inner.timeout_mut()\n    }\n\n    /// Attempts to clone the `Request`.\n    ///\n    /// None is returned if a body is which can not be cloned. This can be because the body is a\n    /// stream.\n    pub fn try_clone(&self) -> Option<Request> {\n        let body = if let Some(ref body) = self.body.as_ref() {\n            if let Some(body) = body.try_clone() {\n                Some(body)\n            } else {\n                return None;\n            }\n        } else {\n            None\n        };\n        let mut req = Request::new(self.method().clone(), self.url().clone());\n        *req.timeout_mut() = self.timeout().copied();\n        *req.headers_mut() = self.headers().clone();\n        *req.version_mut() = self.version().clone();\n        req.body = body;\n        Some(req)\n    }\n\n    pub(crate) fn into_async(self) -> (async_impl::Request, Option<body::Sender>) {\n        use crate::header::CONTENT_LENGTH;\n\n        let mut req_async = self.inner;\n        let body = self.body.and_then(|body| {\n            let (tx, body, len) = body.into_async();\n            if let Some(len) = len {\n                req_async.headers_mut().insert(CONTENT_LENGTH, len.into());\n            }\n            *req_async.body_mut() = Some(body);\n            tx\n        });\n        (req_async, body)\n    }\n}\n\nimpl RequestBuilder {\n    pub(crate) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder {\n        let mut builder = RequestBuilder { client, request };\n\n        let auth = builder\n            .request\n            .as_mut()\n            .ok()\n            .and_then(|req| async_impl::request::extract_authority(req.url_mut()));\n\n        if let Some((username, password)) = auth {\n            builder.basic_auth(username, password)\n        } else {\n            builder\n        }\n    }\n\n    /// Assemble a builder starting from an existing `Client` and a `Request`.\n    pub fn from_parts(client: Client, request: Request) -> RequestBuilder {\n        RequestBuilder {\n            client,\n            request: crate::Result::Ok(request),\n        }\n    }\n\n    /// Add a `Header` to this Request.\n    ///\n    /// ```rust\n    /// use reqwest::header::USER_AGENT;\n    ///\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.get(\"https://www.rust-lang.org\")\n    ///     .header(USER_AGENT, \"foo\")\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn header<K, V>(self, key: K, value: V) -> RequestBuilder\n    where\n        HeaderName: TryFrom<K>,\n        HeaderValue: TryFrom<V>,\n        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,\n        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,\n    {\n        self.header_sensitive(key, value, false)\n    }\n\n    /// Add a `Header` to this Request with ability to define if header_value is sensitive.\n    fn header_sensitive<K, V>(mut self, key: K, value: V, sensitive: bool) -> RequestBuilder\n    where\n        HeaderName: TryFrom<K>,\n        HeaderValue: TryFrom<V>,\n        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,\n        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,\n    {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match <HeaderName as TryFrom<K>>::try_from(key) {\n                Ok(key) => match <HeaderValue as TryFrom<V>>::try_from(value) {\n                    Ok(mut value) => {\n                        // We want to potentially make an unsensitive header\n                        // to be sensitive, not the reverse. So, don't turn off\n                        // a previously sensitive header.\n                        if sensitive {\n                            value.set_sensitive(true);\n                        }\n                        req.headers_mut().append(key, value);\n                    }\n                    Err(e) => error = Some(crate::error::builder(e.into())),\n                },\n                Err(e) => error = Some(crate::error::builder(e.into())),\n            };\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Add a set of Headers to the existing ones on this Request.\n    ///\n    /// The headers will be merged in to any already set.\n    ///\n    /// ```rust\n    /// use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT, CONTENT_TYPE};\n    /// # use std::fs;\n    ///\n    /// fn construct_headers() -> HeaderMap {\n    ///     let mut headers = HeaderMap::new();\n    ///     headers.insert(USER_AGENT, HeaderValue::from_static(\"reqwest\"));\n    ///     headers.insert(CONTENT_TYPE, HeaderValue::from_static(\"image/png\"));\n    ///     headers\n    /// }\n    ///\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let file = fs::File::open(\"much_beauty.png\")?;\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org/post\")\n    ///     .headers(construct_headers())\n    ///     .body(file)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn headers(mut self, headers: crate::header::HeaderMap) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            crate::util::replace_headers(req.headers_mut(), headers);\n        }\n        self\n    }\n\n    /// Enable HTTP basic authentication.\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let resp = client.delete(\"http://httpbin.org/delete\")\n    ///     .basic_auth(\"admin\", Some(\"good password\"))\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> RequestBuilder\n    where\n        U: fmt::Display,\n        P: fmt::Display,\n    {\n        let header_value = crate::util::basic_auth(username, password);\n        self.header_sensitive(crate::header::AUTHORIZATION, header_value, true)\n    }\n\n    /// Enable HTTP bearer authentication.\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let resp = client.delete(\"http://httpbin.org/delete\")\n    ///     .bearer_auth(\"token\")\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn bearer_auth<T>(self, token: T) -> RequestBuilder\n    where\n        T: fmt::Display,\n    {\n        let header_value = format!(\"Bearer {token}\");\n        self.header_sensitive(crate::header::AUTHORIZATION, &*header_value, true)\n    }\n\n    /// Set the request body.\n    ///\n    /// # Examples\n    ///\n    /// Using a string:\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org/post\")\n    ///     .body(\"from a &str!\")\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// Using a `File`:\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let file = std::fs::File::open(\"from_a_file.txt\")?;\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org/post\")\n    ///     .body(file)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// Using arbitrary bytes:\n    ///\n    /// ```rust\n    /// # use std::fs;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// // from bytes!\n    /// let bytes: Vec<u8> = vec![1, 10, 100];\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org/post\")\n    ///     .body(bytes)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.body_mut() = Some(body.into());\n        }\n        self\n    }\n\n    /// Enables a request timeout.\n    ///\n    /// The timeout is applied from when the request starts connecting until the\n    /// response body has finished. It affects only this request and overrides\n    /// the timeout configured using `ClientBuilder::timeout()`.\n    pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.timeout_mut() = Some(timeout);\n        }\n        self\n    }\n\n    /// Modify the query string of the URL.\n    ///\n    /// Modifies the URL of this request, adding the parameters provided.\n    /// This method appends and does not overwrite. This means that it can\n    /// be called multiple times and that existing query parameters are not\n    /// overwritten if the same key is used. The key will simply show up\n    /// twice in the query string.\n    /// Calling `.query(&[(\"foo\", \"a\"), (\"foo\", \"b\")])` gives `\"foo=a&foo=b\"`.\n    ///\n    /// ```rust\n    /// # use reqwest::Error;\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.get(\"http://httpbin.org\")\n    ///     .query(&[(\"lang\", \"rust\")])\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Note\n    /// This method does not support serializing a single key-value\n    /// pair. Instead of using `.query((\"key\", \"val\"))`, use a sequence, such\n    /// as `.query(&[(\"key\", \"val\")])`. It's also possible to serialize structs\n    /// and maps into a key-value pair.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `query` feature to be enabled.\n    ///\n    /// # Errors\n    /// This method will fail if the object you provide cannot be serialized\n    /// into a query string.\n    #[cfg(feature = \"query\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"query\")))]\n    pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            let url = req.url_mut();\n            let mut pairs = url.query_pairs_mut();\n            let serializer = serde_urlencoded::Serializer::new(&mut pairs);\n\n            if let Err(err) = query.serialize(serializer) {\n                error = Some(crate::error::builder(err));\n            }\n        }\n        if let Ok(ref mut req) = self.request {\n            if let Some(\"\") = req.url().query() {\n                req.url_mut().set_query(None);\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Set HTTP version\n    pub fn version(mut self, version: Version) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.version_mut() = version;\n        }\n        self\n    }\n\n    /// Send a form body.\n    ///\n    /// Sets the body to the url encoded serialization of the passed value,\n    /// and also sets the `Content-Type: application/x-www-form-urlencoded`\n    /// header.\n    ///\n    /// ```rust\n    /// # use reqwest::Error;\n    /// # use std::collections::HashMap;\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let mut params = HashMap::new();\n    /// params.insert(\"lang\", \"rust\");\n    ///\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org\")\n    ///     .form(&params)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `form` feature to be enabled.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if the passed value cannot be serialized into\n    /// url encoded format\n    #[cfg(feature = \"form\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"form\")))]\n    pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_urlencoded::to_string(form) {\n                Ok(body) => {\n                    req.headers_mut()\n                        .entry(CONTENT_TYPE)\n                        .or_insert(HeaderValue::from_static(\n                            \"application/x-www-form-urlencoded\",\n                        ));\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Send a JSON body.\n    ///\n    /// Sets the body to the JSON serialization of the passed value, and\n    /// also sets the `Content-Type: application/json` header.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `json` feature enabled.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use reqwest::Error;\n    /// # use std::collections::HashMap;\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let mut map = HashMap::new();\n    /// map.insert(\"lang\", \"rust\");\n    ///\n    /// let client = reqwest::blocking::Client::new();\n    /// let res = client.post(\"http://httpbin.org\")\n    ///     .json(&map)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Errors\n    ///\n    /// Serialization can fail if `T`'s implementation of `Serialize` decides to\n    /// fail, or if `T` contains a map with non-string keys.\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_json::to_vec(json) {\n                Ok(body) => {\n                    req.headers_mut()\n                        .entry(CONTENT_TYPE)\n                        .or_insert_with(|| HeaderValue::from_static(\"application/json\"));\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Sends a multipart/form-data body.\n    ///\n    /// ```\n    /// # use reqwest::Error;\n    ///\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let form = reqwest::blocking::multipart::Form::new()\n    ///     .text(\"key3\", \"value3\")\n    ///     .file(\"file\", \"/path/to/field\")?;\n    ///\n    /// let response = client.post(\"your url\")\n    ///     .multipart(form)\n    ///     .send()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// See [`multipart`](multipart/) for more examples.\n    #[cfg(feature = \"multipart\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"multipart\")))]\n    pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder {\n        let mut builder = self.header(\n            CONTENT_TYPE,\n            format!(\"multipart/form-data; boundary={}\", multipart.boundary()).as_str(),\n        );\n        if let Ok(ref mut req) = builder.request {\n            *req.body_mut() = Some(match multipart.compute_length() {\n                Some(length) => Body::sized(multipart.reader(), length),\n                None => Body::new(multipart.reader()),\n            })\n        }\n        builder\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    pub fn build(self) -> crate::Result<Request> {\n        self.request\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    ///\n    /// This is similar to [`RequestBuilder::build()`], but also returns the\n    /// embedded `Client`.\n    pub fn build_split(self) -> (Client, crate::Result<Request>) {\n        (self.client, self.request)\n    }\n\n    /// Constructs the Request and sends it the target URL, returning a Response.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request,\n    /// redirect loop was detected or redirect limit was exhausted.\n    pub fn send(self) -> crate::Result<super::Response> {\n        self.client.execute(self.request?)\n    }\n\n    /// Attempts to clone the `RequestBuilder`.\n    ///\n    /// None is returned if a body is which can not be cloned. This can be because the body is a\n    /// stream.\n    ///\n    /// # Examples\n    ///\n    /// With a static body\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let builder = client.post(\"http://httpbin.org/post\")\n    ///     .body(\"from a &str!\");\n    /// let clone = builder.try_clone();\n    /// assert!(clone.is_some());\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// Without a body\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let builder = client.get(\"http://httpbin.org/get\");\n    /// let clone = builder.try_clone();\n    /// assert!(clone.is_some());\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// With a non-cloneable body\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::blocking::Client::new();\n    /// let builder = client.get(\"http://httpbin.org/get\")\n    ///     .body(reqwest::blocking::Body::new(std::io::empty()));\n    /// let clone = builder.try_clone();\n    /// assert!(clone.is_none());\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn try_clone(&self) -> Option<RequestBuilder> {\n        self.request\n            .as_ref()\n            .ok()\n            .and_then(|req| req.try_clone())\n            .map(|req| RequestBuilder {\n                client: self.client.clone(),\n                request: Ok(req),\n            })\n    }\n}\n\nimpl<T> TryFrom<HttpRequest<T>> for Request\nwhere\n    T: Into<Body>,\n{\n    type Error = crate::Error;\n\n    fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {\n        let (parts, body) = req.into_parts();\n        let Parts {\n            method,\n            uri,\n            headers,\n            ..\n        } = parts;\n        let url = Url::parse(&uri.to_string()).map_err(crate::error::builder)?;\n        let mut inner = async_impl::Request::new(method, url);\n        crate::util::replace_headers(inner.headers_mut(), headers);\n        Ok(Request {\n            body: Some(body.into()),\n            inner,\n        })\n    }\n}\n\nimpl fmt::Debug for Request {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt_request_fields(&mut f.debug_struct(\"Request\"), self).finish()\n    }\n}\n\nfn fmt_request_fields<'a, 'b>(\n    f: &'a mut fmt::DebugStruct<'a, 'b>,\n    req: &Request,\n) -> &'a mut fmt::DebugStruct<'a, 'b> {\n    f.field(\"method\", req.method())\n        .field(\"url\", req.url())\n        .field(\"headers\", req.headers())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::header::{ACCEPT, HOST};\n    #[cfg(feature = \"query\")]\n    use std::collections::BTreeMap;\n    #[cfg(feature = \"form\")]\n    use std::collections::HashMap;\n\n    #[test]\n    fn basic_get_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.get(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::GET);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_head_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.head(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::HEAD);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_post_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::POST);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_put_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.put(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::PUT);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_patch_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.patch(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::PATCH);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn basic_delete_request() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.delete(some_url).build().unwrap();\n\n        assert_eq!(r.method(), &Method::DELETE);\n        assert_eq!(r.url().as_str(), some_url);\n    }\n\n    #[test]\n    fn add_header() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let header = HeaderValue::from_static(\"google.com\");\n\n        // Add a copy of the header to the request builder\n        let r = r.header(HOST, header.clone()).build().unwrap();\n\n        // then check it was actually added\n        assert_eq!(r.headers().get(HOST), Some(&header));\n    }\n\n    #[test]\n    fn add_headers() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let header = HeaderValue::from_static(\"google.com\");\n\n        let mut headers = HeaderMap::new();\n        headers.insert(HOST, header);\n\n        // Add a copy of the headers to the request builder\n        let r = r.headers(headers.clone()).build().unwrap();\n\n        // then make sure they were added correctly\n        assert_eq!(r.headers(), &headers);\n    }\n\n    #[test]\n    fn add_headers_multi() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let header_json = HeaderValue::from_static(\"application/json\");\n        let header_xml = HeaderValue::from_static(\"application/xml\");\n\n        let mut headers = HeaderMap::new();\n        headers.append(ACCEPT, header_json);\n        headers.append(ACCEPT, header_xml);\n\n        // Add a copy of the headers to the request builder\n        let r = r.headers(headers.clone()).build().unwrap();\n\n        // then make sure they were added correctly\n        assert_eq!(r.headers(), &headers);\n        let mut all_values = r.headers().get_all(ACCEPT).iter();\n        assert_eq!(all_values.next().unwrap(), &\"application/json\");\n        assert_eq!(all_values.next().unwrap(), &\"application/xml\");\n        assert_eq!(all_values.next(), None);\n    }\n\n    #[test]\n    fn add_body() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let body = \"Some interesting content\";\n\n        let mut r = r.body(body).build().unwrap();\n\n        let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();\n\n        assert_eq!(buf, body);\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_append() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let mut r = client.get(some_url);\n\n        r = r.query(&[(\"foo\", \"bar\")]);\n        r = r.query(&[(\"qux\", 3)]);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=3\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_append_same() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let mut r = client.get(some_url);\n\n        r = r.query(&[(\"foo\", \"a\"), (\"foo\", \"b\")]);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=a&foo=b\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_struct() {\n        #[derive(Serialize)]\n        struct Params {\n            foo: String,\n            qux: i32,\n        }\n\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let mut r = client.get(some_url);\n\n        let params = Params {\n            foo: \"bar\".into(),\n            qux: 3,\n        };\n\n        r = r.query(&params);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=3\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn add_query_map() {\n        let mut params = BTreeMap::new();\n        params.insert(\"foo\", \"bar\");\n        params.insert(\"qux\", \"three\");\n\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let mut r = client.get(some_url);\n\n        r = r.query(&params);\n\n        let req = r.build().expect(\"request is valid\");\n        assert_eq!(req.url().query(), Some(\"foo=bar&qux=three\"));\n    }\n\n    #[test]\n    #[cfg(feature = \"form\")]\n    fn add_form() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let mut form_data = HashMap::new();\n        form_data.insert(\"foo\", \"bar\");\n\n        let mut r = r.form(&form_data).build().unwrap();\n\n        // Make sure the content type was set\n        assert_eq!(\n            r.headers().get(CONTENT_TYPE).unwrap(),\n            &\"application/x-www-form-urlencoded\"\n        );\n\n        let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();\n\n        let body_should_be = serde_urlencoded::to_string(&form_data).unwrap();\n        assert_eq!(buf, body_should_be);\n    }\n\n    #[test]\n    #[cfg(feature = \"json\")]\n    fn add_json() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n\n        let mut json_data = HashMap::new();\n        json_data.insert(\"foo\", \"bar\");\n\n        let mut r = r.json(&json_data).build().unwrap();\n\n        // Make sure the content type was set\n        assert_eq!(r.headers().get(CONTENT_TYPE).unwrap(), &\"application/json\");\n\n        let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();\n\n        let body_should_be = serde_json::to_string(&json_data).unwrap();\n        assert_eq!(buf, body_should_be);\n    }\n\n    #[test]\n    #[cfg(feature = \"json\")]\n    fn add_json_fail() {\n        use serde::ser::Error as _;\n        use serde::{Serialize, Serializer};\n        use std::error::Error as _;\n        struct MyStruct;\n        impl Serialize for MyStruct {\n            fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>\n            where\n                S: Serializer,\n            {\n                Err(S::Error::custom(\"nope\"))\n            }\n        }\n\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let r = client.post(some_url);\n        let json_data = MyStruct;\n        let err = r.json(&json_data).build().unwrap_err();\n        assert!(err.is_builder()); // well, duh ;)\n        assert!(err.source().unwrap().is::<serde_json::Error>());\n    }\n\n    #[test]\n    fn test_replace_headers() {\n        use http::HeaderMap;\n\n        let mut headers = HeaderMap::new();\n        headers.insert(\"foo\", \"bar\".parse().unwrap());\n        headers.append(\"foo\", \"baz\".parse().unwrap());\n\n        let client = Client::new();\n        let req = client\n            .get(\"https://hyper.rs\")\n            .header(\"im-a\", \"keeper\")\n            .header(\"foo\", \"pop me\")\n            .headers(headers)\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.headers()[\"im-a\"], \"keeper\");\n\n        let foo = req.headers().get_all(\"foo\").iter().collect::<Vec<_>>();\n        assert_eq!(foo.len(), 2);\n        assert_eq!(foo[0], \"bar\");\n        assert_eq!(foo[1], \"baz\");\n    }\n\n    #[test]\n    #[cfg(feature = \"query\")]\n    fn normalize_empty_query() {\n        let client = Client::new();\n        let some_url = \"https://google.com/\";\n        let empty_query: &[(&str, &str)] = &[];\n\n        let req = client\n            .get(some_url)\n            .query(empty_query)\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().query(), None);\n        assert_eq!(req.url().as_str(), \"https://google.com/\");\n    }\n\n    #[test]\n    fn convert_url_authority_into_basic_auth() {\n        let client = Client::new();\n        let some_url = \"https://Aladdin:open sesame@localhost/\";\n\n        let req = client.get(some_url).build().expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(\n            req.headers()[\"authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n    }\n\n    #[test]\n    fn convert_from_http_request() {\n        let http_request = HttpRequest::builder()\n            .method(\"GET\")\n            .uri(\"http://localhost/\")\n            .header(\"User-Agent\", \"my-awesome-agent/1.0\")\n            .body(\"test test test\")\n            .unwrap();\n        let req: Request = Request::try_from(http_request).unwrap();\n        assert_eq!(req.body().is_none(), false);\n        let test_data = b\"test test test\";\n        assert_eq!(req.body().unwrap().as_bytes(), Some(&test_data[..]));\n        let headers = req.headers();\n        assert_eq!(headers.get(\"User-Agent\").unwrap(), \"my-awesome-agent/1.0\");\n        assert_eq!(req.method(), Method::GET);\n        assert_eq!(req.url().as_str(), \"http://localhost/\");\n    }\n\n    #[test]\n    fn set_http_request_version() {\n        let http_request = HttpRequest::builder()\n            .method(\"GET\")\n            .uri(\"http://localhost/\")\n            .header(\"User-Agent\", \"my-awesome-agent/1.0\")\n            .version(Version::HTTP_11)\n            .body(\"test test test\")\n            .unwrap();\n        let req: Request = Request::try_from(http_request).unwrap();\n        assert_eq!(req.body().is_none(), false);\n        let test_data = b\"test test test\";\n        assert_eq!(req.body().unwrap().as_bytes(), Some(&test_data[..]));\n        let headers = req.headers();\n        assert_eq!(headers.get(\"User-Agent\").unwrap(), \"my-awesome-agent/1.0\");\n        assert_eq!(req.method(), Method::GET);\n        assert_eq!(req.url().as_str(), \"http://localhost/\");\n        assert_eq!(req.version(), Version::HTTP_11);\n    }\n\n    #[test]\n    fn test_basic_auth_sensitive_header() {\n        let client = Client::new();\n        let some_url = \"https://localhost/\";\n\n        let req = client\n            .get(some_url)\n            .basic_auth(\"Aladdin\", Some(\"open sesame\"))\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(\n            req.headers()[\"authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n        assert_eq!(req.headers()[\"authorization\"].is_sensitive(), true);\n    }\n\n    #[test]\n    fn test_bearer_auth_sensitive_header() {\n        let client = Client::new();\n        let some_url = \"https://localhost/\";\n\n        let req = client\n            .get(some_url)\n            .bearer_auth(\"Hold my bear\")\n            .build()\n            .expect(\"request build\");\n\n        assert_eq!(req.url().as_str(), \"https://localhost/\");\n        assert_eq!(req.headers()[\"authorization\"], \"Bearer Hold my bear\");\n        assert_eq!(req.headers()[\"authorization\"].is_sensitive(), true);\n    }\n\n    #[test]\n    fn test_request_cloning() {\n        let mut request = Request::new(Method::GET, \"https://example.com\".try_into().unwrap());\n        *request.timeout_mut() = Some(Duration::from_secs(42));\n        *request.version_mut() = Version::HTTP_11;\n\n        let clone = request.try_clone().unwrap();\n        assert_eq!(request.version(), clone.version());\n        assert_eq!(request.headers(), clone.headers());\n        assert_eq!(request.timeout(), clone.timeout());\n    }\n}\n"
  },
  {
    "path": "src/blocking/response.rs",
    "content": "use std::fmt;\nuse std::io::{self, Read};\nuse std::mem;\nuse std::net::SocketAddr;\nuse std::pin::Pin;\nuse std::time::Duration;\n\nuse bytes::Bytes;\nuse futures_util::TryStreamExt;\nuse http;\nuse http_body_util::BodyExt;\nuse hyper::header::HeaderMap;\n#[cfg(feature = \"json\")]\nuse serde::de::DeserializeOwned;\n\nuse super::client::KeepCoreThreadAlive;\nuse super::wait;\n#[cfg(feature = \"cookies\")]\nuse crate::cookie;\nuse crate::{async_impl, StatusCode, Url, Version};\n\n/// A Response to a submitted `Request`.\npub struct Response {\n    inner: async_impl::Response,\n    body: Option<Pin<Box<dyn futures_util::io::AsyncRead + Send + Sync>>>,\n    timeout: Option<Duration>,\n    _thread_handle: KeepCoreThreadAlive,\n}\n\nimpl fmt::Debug for Response {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt::Debug::fmt(&self.inner, f)\n    }\n}\n\nimpl Response {\n    pub(crate) fn new(\n        res: async_impl::Response,\n        timeout: Option<Duration>,\n        thread: KeepCoreThreadAlive,\n    ) -> Response {\n        Response {\n            inner: res,\n            body: None,\n            timeout,\n            _thread_handle: thread,\n        }\n    }\n\n    /// Get the `StatusCode` of this `Response`.\n    ///\n    /// # Examples\n    ///\n    /// Checking for general status class:\n    ///\n    /// ```rust\n    /// # #[cfg(feature = \"json\")]\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let resp = reqwest::blocking::get(\"http://httpbin.org/get\")?;\n    /// if resp.status().is_success() {\n    ///     println!(\"success!\");\n    /// } else if resp.status().is_server_error() {\n    ///     println!(\"server error!\");\n    /// } else {\n    ///     println!(\"Something else happened. Status: {:?}\", resp.status());\n    /// }\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// Checking for specific status codes:\n    ///\n    /// ```rust\n    /// use reqwest::blocking::Client;\n    /// use reqwest::StatusCode;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = Client::new();\n    ///\n    /// let resp = client.post(\"http://httpbin.org/post\")\n    ///     .body(\"possibly too large\")\n    ///     .send()?;\n    ///\n    /// match resp.status() {\n    ///     StatusCode::OK => println!(\"success!\"),\n    ///     StatusCode::PAYLOAD_TOO_LARGE => {\n    ///         println!(\"Request payload is too large!\");\n    ///     }\n    ///     s => println!(\"Received response status: {s:?}\"),\n    /// };\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline]\n    pub fn status(&self) -> StatusCode {\n        self.inner.status()\n    }\n\n    /// Get the `Headers` of this `Response`.\n    ///\n    /// # Example\n    ///\n    /// Saving an etag when caching a file:\n    ///\n    /// ```\n    /// use reqwest::blocking::Client;\n    /// use reqwest::header::ETAG;\n    ///\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = Client::new();\n    ///\n    /// let mut resp = client.get(\"http://httpbin.org/cache\").send()?;\n    /// if resp.status().is_success() {\n    ///     if let Some(etag) = resp.headers().get(ETAG) {\n    ///         std::fs::write(\"etag\", etag.as_bytes());\n    ///     }\n    ///     let mut file = std::fs::File::create(\"file\")?;\n    ///     resp.copy_to(&mut file)?;\n    /// }\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        self.inner.headers()\n    }\n\n    /// Get a mutable reference to the `Headers` of this `Response`.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        self.inner.headers_mut()\n    }\n\n    /// Retrieve the cookies contained in the response.\n    ///\n    /// Note that invalid 'Set-Cookie' headers will be ignored.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `cookies` feature to be enabled.\n    #[cfg(feature = \"cookies\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"cookies\")))]\n    pub fn cookies<'a>(&'a self) -> impl Iterator<Item = cookie::Cookie<'a>> + 'a {\n        cookie::extract_response_cookies(self.headers()).filter_map(Result::ok)\n    }\n\n    /// Get the HTTP `Version` of this `Response`.\n    #[inline]\n    pub fn version(&self) -> Version {\n        self.inner.version()\n    }\n\n    /// Get the final `Url` of this `Response`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let resp = reqwest::blocking::get(\"http://httpbin.org/redirect/1\")?;\n    /// assert_eq!(resp.url().as_str(), \"http://httpbin.org/get\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline]\n    pub fn url(&self) -> &Url {\n        self.inner.url()\n    }\n\n    /// Get the remote address used to get this `Response`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let resp = reqwest::blocking::get(\"http://httpbin.org/redirect/1\")?;\n    /// println!(\"httpbin.org address: {:?}\", resp.remote_addr());\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn remote_addr(&self) -> Option<SocketAddr> {\n        self.inner.remote_addr()\n    }\n\n    /// Returns a reference to the associated extensions.\n    pub fn extensions(&self) -> &http::Extensions {\n        self.inner.extensions()\n    }\n\n    /// Returns a mutable reference to the associated extensions.\n    pub fn extensions_mut(&mut self) -> &mut http::Extensions {\n        self.inner.extensions_mut()\n    }\n\n    /// Get the content length of the response, if it is known.\n    ///\n    ///\n    /// This value does not directly represents the value of the `Content-Length`\n    /// header, but rather the size of the response's body. To read the header's\n    /// value, please use the [`Response::headers`] method instead.\n    ///\n    /// Reasons it may not be known:\n    ///\n    /// - The response does not include a body (e.g. it responds to a `HEAD`\n    ///   request).\n    /// - The response is gzipped and automatically decoded (thus changing the\n    ///   actual decoded length).\n    pub fn content_length(&self) -> Option<u64> {\n        self.inner.content_length()\n    }\n\n    /// Try and deserialize the response body as JSON using `serde`.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `json` feature enabled.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # extern crate reqwest;\n    /// # extern crate serde;\n    /// #\n    /// # use reqwest::Error;\n    /// # use serde::Deserialize;\n    /// #\n    /// // This `derive` requires the `serde` dependency.\n    /// #[derive(Deserialize)]\n    /// struct Ip {\n    ///     origin: String,\n    /// }\n    ///\n    /// # fn run() -> Result<(), Error> {\n    /// let json: Ip = reqwest::blocking::get(\"http://httpbin.org/ip\")?.json()?;\n    /// # Ok(())\n    /// # }\n    /// #\n    /// # fn main() { }\n    /// ```\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever the response body is not in JSON format,\n    /// or it cannot be properly deserialized to target type `T`. For more\n    /// details please see [`serde_json::from_reader`].\n    ///\n    /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    pub fn json<T: DeserializeOwned>(self) -> crate::Result<T> {\n        wait::timeout(self.inner.json(), self.timeout).map_err(|e| match e {\n            wait::Waited::TimedOut(e) => crate::error::decode(e),\n            wait::Waited::Inner(e) => e,\n        })\n    }\n\n    /// Get the full response body as `Bytes`.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let bytes = reqwest::blocking::get(\"http://httpbin.org/ip\")?.bytes()?;\n    ///\n    /// println!(\"bytes: {bytes:?}\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn bytes(self) -> crate::Result<Bytes> {\n        wait::timeout(self.inner.bytes(), self.timeout).map_err(|e| match e {\n            wait::Waited::TimedOut(e) => crate::error::decode(e),\n            wait::Waited::Inner(e) => e,\n        })\n    }\n\n    /// Get the response text.\n    ///\n    /// This method decodes the response body with BOM sniffing\n    /// and with malformed sequences replaced with the [`char::REPLACEMENT_CHARACTER`].\n    /// Encoding is determined from the `charset` parameter of `Content-Type` header,\n    /// and defaults to `utf-8` if not presented.\n    ///\n    /// # Note\n    ///\n    /// If the `charset` feature is disabled the method will only attempt to decode the\n    /// response as UTF-8, regardless of the given `Content-Type`\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let content = reqwest::blocking::get(\"http://httpbin.org/range/26\")?.text()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn text(self) -> crate::Result<String> {\n        wait::timeout(self.inner.text(), self.timeout).map_err(|e| match e {\n            wait::Waited::TimedOut(e) => crate::error::decode(e),\n            wait::Waited::Inner(e) => e,\n        })\n    }\n\n    /// Get the response text given a specific encoding.\n    ///\n    /// This method decodes the response body with BOM sniffing\n    /// and with malformed sequences replaced with the [`char::REPLACEMENT_CHARACTER`].\n    /// You can provide a default encoding for decoding the raw message, while the\n    /// `charset` parameter of `Content-Type` header is still prioritized. For more information\n    /// about the possible encoding name, please go to [`encoding_rs`] docs.\n    ///\n    /// [`encoding_rs`]: https://docs.rs/encoding_rs/0.8/encoding_rs/#relationship-with-windows-code-pages\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `charset` feature enabled.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let content = reqwest::blocking::get(\"http://httpbin.org/range/26\")?\n    ///     .text_with_charset(\"utf-8\")?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[cfg(feature = \"charset\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"charset\")))]\n    pub fn text_with_charset(self, default_encoding: &str) -> crate::Result<String> {\n        wait::timeout(self.inner.text_with_charset(default_encoding), self.timeout).map_err(|e| {\n            match e {\n                wait::Waited::TimedOut(e) => crate::error::decode(e),\n                wait::Waited::Inner(e) => e,\n            }\n        })\n    }\n\n    /// Copy the response body into a writer.\n    ///\n    /// This function internally uses [`std::io::copy`] and hence will continuously read data from\n    /// the body and then write it into writer in a streaming fashion until EOF is met.\n    ///\n    /// On success, the total number of bytes that were copied to `writer` is returned.\n    ///\n    /// [`std::io::copy`]: https://doc.rust-lang.org/std/io/fn.copy.html\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut resp = reqwest::blocking::get(\"http://httpbin.org/range/5\")?;\n    /// let mut buf: Vec<u8> = vec![];\n    /// resp.copy_to(&mut buf)?;\n    /// assert_eq!(b\"abcde\", buf.as_slice());\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn copy_to<W: ?Sized>(&mut self, w: &mut W) -> crate::Result<u64>\n    where\n        W: io::Write,\n    {\n        io::copy(self, w).map_err(crate::error::decode_io)\n    }\n\n    /// Turn a response into an error if the server returned an error.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let res = reqwest::blocking::get(\"http://httpbin.org/status/400\")?\n    ///     .error_for_status();\n    /// if let Err(err) = res {\n    ///     assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));\n    /// }\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn error_for_status(self) -> crate::Result<Self> {\n        let Response {\n            body,\n            inner,\n            timeout,\n            _thread_handle,\n        } = self;\n        inner.error_for_status().map(move |inner| Response {\n            inner,\n            body,\n            timeout,\n            _thread_handle,\n        })\n    }\n\n    /// Turn a reference to a response into an error if the server returned an error.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let res = reqwest::blocking::get(\"http://httpbin.org/status/400\")?;\n    /// let res = res.error_for_status_ref();\n    /// if let Err(err) = res {\n    ///     assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));\n    /// }\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {\n        self.inner.error_for_status_ref().and_then(|_| Ok(self))\n    }\n\n    // private\n\n    fn body_mut(&mut self) -> Pin<&mut dyn futures_util::io::AsyncRead> {\n        if self.body.is_none() {\n            let body = mem::replace(\n                self.inner.body_mut(),\n                async_impl::body::boxed(http_body_util::Empty::new()),\n            );\n\n            self.body = Some(Box::pin(\n                async_impl::body::Body::wrap(body)\n                    .into_data_stream()\n                    .map_err(crate::error::Error::into_io)\n                    .into_async_read(),\n            ));\n        }\n        self.body.as_mut().expect(\"body was init\").as_mut()\n    }\n}\n\nimpl Read for Response {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        use futures_util::io::AsyncReadExt;\n\n        let timeout = self.timeout;\n        wait::timeout(self.body_mut().read(buf), timeout).map_err(|e| match e {\n            wait::Waited::TimedOut(e) => crate::error::decode(e).into_io(),\n            wait::Waited::Inner(e) => e,\n        })\n    }\n}\n\nimpl<T: Into<async_impl::body::Body>> From<http::Response<T>> for Response {\n    fn from(r: http::Response<T>) -> Response {\n        let response = async_impl::Response::from(r);\n        Response::new(response, None, KeepCoreThreadAlive::empty())\n    }\n}\n"
  },
  {
    "path": "src/blocking/wait.rs",
    "content": "use std::future::Future;\nuse std::sync::Arc;\nuse std::task::{Context, Poll, Wake, Waker};\nuse std::thread::{self, Thread};\nuse std::time::Duration;\n\nuse tokio::time::Instant;\n\npub(crate) fn timeout<F, I, E>(fut: F, timeout: Option<Duration>) -> Result<I, Waited<E>>\nwhere\n    F: Future<Output = Result<I, E>>,\n{\n    enter();\n\n    let deadline = timeout.map(|d| {\n        log::trace!(\"wait at most {d:?}\");\n        Instant::now() + d\n    });\n\n    let thread = ThreadWaker(thread::current());\n    // Arc shouldn't be necessary, since `Thread` is reference counted internally,\n    // but let's just stay safe for now.\n    let waker = Waker::from(Arc::new(thread));\n    let mut cx = Context::from_waker(&waker);\n\n    futures_util::pin_mut!(fut);\n\n    loop {\n        match fut.as_mut().poll(&mut cx) {\n            Poll::Ready(Ok(val)) => return Ok(val),\n            Poll::Ready(Err(err)) => return Err(Waited::Inner(err)),\n            Poll::Pending => (), // fallthrough\n        }\n\n        if let Some(deadline) = deadline {\n            let now = Instant::now();\n            if now >= deadline {\n                log::trace!(\"wait timeout exceeded\");\n                return Err(Waited::TimedOut(crate::error::TimedOut));\n            }\n\n            log::trace!(\n                \"({:?}) park timeout {:?}\",\n                thread::current().id(),\n                deadline - now\n            );\n            thread::park_timeout(deadline - now);\n        } else {\n            log::trace!(\"({:?}) park without timeout\", thread::current().id());\n            thread::park();\n        }\n    }\n}\n\n#[derive(Debug)]\npub(crate) enum Waited<E> {\n    TimedOut(crate::error::TimedOut),\n    Inner(E),\n}\n\nstruct ThreadWaker(Thread);\n\nimpl Wake for ThreadWaker {\n    fn wake(self: Arc<Self>) {\n        self.wake_by_ref();\n    }\n\n    fn wake_by_ref(self: &Arc<Self>) {\n        self.0.unpark();\n    }\n}\n\nfn enter() {\n    // Check we aren't already in a runtime\n    #[cfg(debug_assertions)]\n    {\n        let _enter = tokio::runtime::Builder::new_current_thread()\n            .build()\n            .expect(\"build shell runtime\")\n            .enter();\n    }\n}\n"
  },
  {
    "path": "src/config.rs",
    "content": "//! The `config` module provides a generic mechanism for loading and managing\n//! request-scoped configuration.\n//!\n//! # Design Overview\n//!\n//! This module is centered around two abstractions:\n//!\n//! - The [`RequestConfigValue`] trait, used to associate a config key type with its value type.\n//! - The [`RequestConfig`] struct, which wraps an optional value of the type linked via [`RequestConfigValue`].\n//!\n//! Under the hood, the [`RequestConfig`] struct holds a single value for the associated config type.\n//! This value can be conveniently accessed, inserted, or mutated using [`http::Extensions`],\n//! enabling type-safe configuration storage and retrieval on a per-request basis.\n//!\n//! # Motivation\n//!\n//! The key design benefit is the ability to store multiple config types—potentially even with the same\n//! value type (e.g., [`Duration`])—without code duplication or ambiguity. By leveraging trait association,\n//! each config key is distinct at the type level, while code for storage and access remains totally generic.\n//!\n//! # Usage\n//!\n//! Implement [`RequestConfigValue`] for any marker type you wish to use as a config key,\n//! specifying the associated value type. Then use [`RequestConfig<T>`] in [`Extensions`]\n//! to set or retrieve config values for each key type in a uniform way.\n\nuse std::any::type_name;\nuse std::fmt::Debug;\nuse std::time::Duration;\n\nuse http::Extensions;\n\n/// This trait is empty and is only used to associate a configuration key type with its\n/// corresponding value type.\npub(crate) trait RequestConfigValue: Copy + Clone + 'static {\n    type Value: Clone + Debug + Send + Sync + 'static;\n}\n\n/// RequestConfig carries a request-scoped configuration value.\n#[derive(Clone, Copy)]\npub(crate) struct RequestConfig<T: RequestConfigValue>(Option<T::Value>);\n\nimpl<T: RequestConfigValue> Default for RequestConfig<T> {\n    fn default() -> Self {\n        RequestConfig(None)\n    }\n}\n\nimpl<T> RequestConfig<T>\nwhere\n    T: RequestConfigValue,\n{\n    pub(crate) fn new(v: Option<T::Value>) -> Self {\n        RequestConfig(v)\n    }\n\n    /// format request config value as struct field.\n    ///\n    /// We provide this API directly to avoid leak internal value to callers.\n    pub(crate) fn fmt_as_field(&self, f: &mut std::fmt::DebugStruct<'_, '_>) {\n        if let Some(v) = &self.0 {\n            f.field(type_name::<T>(), v);\n        }\n    }\n\n    /// Retrieve the value from the request-scoped configuration.\n    ///\n    /// If the request specifies a value, use that value; otherwise, attempt to retrieve it from the current instance (typically a client instance).\n    pub(crate) fn fetch<'client, 'request>(\n        &'client self,\n        ext: &'request Extensions,\n    ) -> Option<&'request T::Value>\n    where\n        'client: 'request,\n    {\n        ext.get::<RequestConfig<T>>()\n            .and_then(|v| v.0.as_ref())\n            .or(self.0.as_ref())\n    }\n\n    /// Retrieve the value from the request's Extensions.\n    pub(crate) fn get(ext: &Extensions) -> Option<&T::Value> {\n        ext.get::<RequestConfig<T>>().and_then(|v| v.0.as_ref())\n    }\n\n    /// Retrieve the mutable value from the request's Extensions.\n    pub(crate) fn get_mut(ext: &mut Extensions) -> &mut Option<T::Value> {\n        let cfg = ext.get_or_insert_default::<RequestConfig<T>>();\n        &mut cfg.0\n    }\n}\n\n// ================================\n//\n// The following sections are all configuration types\n// provided by reqwest.\n//\n// To add a new config:\n//\n// 1. create a new struct for the config key like `RequestTimeout`.\n// 2. implement `RequestConfigValue` for the struct, the `Value` is the config value's type.\n//\n// ================================\n\n#[derive(Clone, Copy)]\npub(crate) struct TotalTimeout;\n\nimpl RequestConfigValue for TotalTimeout {\n    type Value = Duration;\n}\n"
  },
  {
    "path": "src/connect.rs",
    "content": "#[cfg(feature = \"__tls\")]\nuse http::header::HeaderValue;\n#[cfg(feature = \"__tls\")]\nuse http::uri::Scheme;\nuse http::Uri;\nuse hyper::rt::{Read, ReadBufCursor, Write};\nuse hyper_util::client::legacy::connect::{Connected, Connection};\n#[cfg(any(feature = \"socks\", feature = \"__tls\", unix, target_os = \"windows\"))]\nuse hyper_util::rt::TokioIo;\n#[cfg(feature = \"__native-tls\")]\nuse native_tls_crate::{TlsConnector, TlsConnectorBuilder};\nuse pin_project_lite::pin_project;\nuse tower::util::{BoxCloneSyncServiceLayer, MapRequestLayer};\nuse tower::{timeout::TimeoutLayer, util::BoxCloneSyncService, ServiceBuilder};\nuse tower_service::Service;\n\nuse std::future::Future;\nuse std::io::{self, IoSlice};\nuse std::net::IpAddr;\nuse std::pin::Pin;\nuse std::sync::Arc;\nuse std::task::{Context, Poll};\nuse std::time::Duration;\n\n#[cfg(feature = \"__native-tls\")]\nuse self::native_tls_conn::NativeTlsConn;\n#[cfg(feature = \"__rustls\")]\nuse self::rustls_tls_conn::RustlsTlsConn;\nuse crate::dns::DynResolver;\nuse crate::error::{cast_to_internal_error, BoxError};\nuse crate::proxy::{Intercepted, Matcher as ProxyMatcher};\nuse sealed::{Conn, Unnameable};\n\npub(crate) type HttpConnector = hyper_util::client::legacy::connect::HttpConnector<DynResolver>;\n\n#[derive(Clone)]\npub(crate) enum Connector {\n    // base service, with or without an embedded timeout\n    Simple(ConnectorService),\n    // at least one custom layer along with maybe an outer timeout layer\n    // from `builder.connect_timeout()`\n    WithLayers(BoxCloneSyncService<Unnameable, Conn, BoxError>),\n}\n\nimpl Service<Uri> for Connector {\n    type Response = Conn;\n    type Error = BoxError;\n    type Future = Connecting;\n\n    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        match self {\n            Connector::Simple(service) => service.poll_ready(cx),\n            Connector::WithLayers(service) => service.poll_ready(cx),\n        }\n    }\n\n    fn call(&mut self, dst: Uri) -> Self::Future {\n        match self {\n            Connector::Simple(service) => service.call(dst),\n            Connector::WithLayers(service) => service.call(Unnameable(dst)),\n        }\n    }\n}\n\npub(crate) type BoxedConnectorService = BoxCloneSyncService<Unnameable, Conn, BoxError>;\n\npub(crate) type BoxedConnectorLayer =\n    BoxCloneSyncServiceLayer<BoxedConnectorService, Unnameable, Conn, BoxError>;\n\npub(crate) struct ConnectorBuilder {\n    inner: Inner,\n    proxies: Arc<Vec<ProxyMatcher>>,\n    verbose: verbose::Wrapper,\n    timeout: Option<Duration>,\n    #[cfg(feature = \"__tls\")]\n    nodelay: bool,\n    #[cfg(feature = \"__tls\")]\n    tls_info: bool,\n    #[cfg(feature = \"__tls\")]\n    user_agent: Option<HeaderValue>,\n    #[cfg(feature = \"socks\")]\n    resolver: Option<DynResolver>,\n    #[cfg(unix)]\n    unix_socket: Option<Arc<std::path::Path>>,\n    #[cfg(target_os = \"windows\")]\n    windows_named_pipe: Option<Arc<std::ffi::OsStr>>,\n}\n\nimpl ConnectorBuilder {\n    pub(crate) fn build(self, layers: Vec<BoxedConnectorLayer>) -> Connector\nwhere {\n        // construct the inner tower service\n        let mut base_service = ConnectorService {\n            inner: self.inner,\n            proxies: self.proxies,\n            verbose: self.verbose,\n            #[cfg(feature = \"__tls\")]\n            nodelay: self.nodelay,\n            #[cfg(feature = \"__tls\")]\n            tls_info: self.tls_info,\n            #[cfg(feature = \"__tls\")]\n            user_agent: self.user_agent,\n            simple_timeout: None,\n            #[cfg(feature = \"socks\")]\n            resolver: self.resolver.unwrap_or_else(DynResolver::gai),\n            #[cfg(unix)]\n            unix_socket: self.unix_socket,\n            #[cfg(target_os = \"windows\")]\n            windows_named_pipe: self.windows_named_pipe,\n        };\n\n        #[cfg(unix)]\n        if base_service.unix_socket.is_some() && !base_service.proxies.is_empty() {\n            base_service.proxies = Default::default();\n            log::trace!(\"unix_socket() set, proxies are ignored\");\n        }\n        #[cfg(target_os = \"windows\")]\n        if base_service.windows_named_pipe.is_some() && !base_service.proxies.is_empty() {\n            base_service.proxies = Default::default();\n            log::trace!(\"windows_named_pipe() set, proxies are ignored\");\n        }\n\n        if layers.is_empty() {\n            // we have no user-provided layers, only use concrete types\n            base_service.simple_timeout = self.timeout;\n            return Connector::Simple(base_service);\n        }\n\n        // otherwise we have user provided layers\n        // so we need type erasure all the way through\n        // as well as mapping the unnameable type of the layers back to Uri for the inner service\n        let unnameable_service = ServiceBuilder::new()\n            .layer(MapRequestLayer::new(|request: Unnameable| request.0))\n            .service(base_service);\n        let mut service = BoxCloneSyncService::new(unnameable_service);\n\n        for layer in layers {\n            service = ServiceBuilder::new().layer(layer).service(service);\n        }\n\n        // now we handle the concrete stuff - any `connect_timeout`,\n        // plus a final map_err layer we can use to cast default tower layer\n        // errors to internal errors\n        match self.timeout {\n            Some(timeout) => {\n                let service = ServiceBuilder::new()\n                    .layer(TimeoutLayer::new(timeout))\n                    .service(service);\n                let service = ServiceBuilder::new()\n                    .map_err(|error: BoxError| cast_to_internal_error(error))\n                    .service(service);\n                let service = BoxCloneSyncService::new(service);\n\n                Connector::WithLayers(service)\n            }\n            None => {\n                // no timeout, but still map err\n                // no named timeout layer but we still map errors since\n                // we might have user-provided timeout layer\n                let service = ServiceBuilder::new().service(service);\n                let service = ServiceBuilder::new()\n                    .map_err(|error: BoxError| cast_to_internal_error(error))\n                    .service(service);\n                let service = BoxCloneSyncService::new(service);\n                Connector::WithLayers(service)\n            }\n        }\n    }\n\n    #[cfg(not(feature = \"__tls\"))]\n    pub(crate) fn new<T>(\n        mut http: HttpConnector,\n        proxies: Arc<Vec<ProxyMatcher>>,\n        local_addr: T,\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        interface: Option<&str>,\n        nodelay: bool,\n    ) -> ConnectorBuilder\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        http.set_local_address(local_addr.into());\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        if let Some(interface) = interface {\n            http.set_interface(interface.to_owned());\n        }\n        http.set_nodelay(nodelay);\n\n        ConnectorBuilder {\n            inner: Inner::Http(http),\n            proxies,\n            verbose: verbose::OFF,\n            timeout: None,\n            #[cfg(feature = \"socks\")]\n            resolver: None,\n            #[cfg(unix)]\n            unix_socket: None,\n            #[cfg(target_os = \"windows\")]\n            windows_named_pipe: None,\n        }\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    pub(crate) fn new_native_tls<T>(\n        http: HttpConnector,\n        tls: TlsConnectorBuilder,\n        proxies: Arc<Vec<ProxyMatcher>>,\n        user_agent: Option<HeaderValue>,\n        local_addr: T,\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        interface: Option<&str>,\n        nodelay: bool,\n        tls_info: bool,\n    ) -> crate::Result<ConnectorBuilder>\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        let tls = tls.build().map_err(crate::error::builder)?;\n        Ok(Self::from_built_native_tls(\n            http,\n            tls,\n            proxies,\n            user_agent,\n            local_addr,\n            #[cfg(any(\n                target_os = \"android\",\n                target_os = \"fuchsia\",\n                target_os = \"illumos\",\n                target_os = \"ios\",\n                target_os = \"linux\",\n                target_os = \"macos\",\n                target_os = \"solaris\",\n                target_os = \"tvos\",\n                target_os = \"visionos\",\n                target_os = \"watchos\",\n            ))]\n            interface,\n            nodelay,\n            tls_info,\n        ))\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    pub(crate) fn from_built_native_tls<T>(\n        mut http: HttpConnector,\n        tls: TlsConnector,\n        proxies: Arc<Vec<ProxyMatcher>>,\n        user_agent: Option<HeaderValue>,\n        local_addr: T,\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        interface: Option<&str>,\n        nodelay: bool,\n        tls_info: bool,\n    ) -> ConnectorBuilder\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        http.set_local_address(local_addr.into());\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        if let Some(interface) = interface {\n            http.set_interface(interface);\n        }\n        http.set_nodelay(nodelay);\n        http.enforce_http(false);\n\n        ConnectorBuilder {\n            inner: Inner::NativeTls(http, tls),\n            proxies,\n            verbose: verbose::OFF,\n            nodelay,\n            tls_info,\n            user_agent,\n            timeout: None,\n            #[cfg(feature = \"socks\")]\n            resolver: None,\n            #[cfg(unix)]\n            unix_socket: None,\n            #[cfg(target_os = \"windows\")]\n            windows_named_pipe: None,\n        }\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    pub(crate) fn new_rustls_tls<T>(\n        mut http: HttpConnector,\n        tls: rustls::ClientConfig,\n        proxies: Arc<Vec<ProxyMatcher>>,\n        user_agent: Option<HeaderValue>,\n        local_addr: T,\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        interface: Option<&str>,\n        nodelay: bool,\n        tls_info: bool,\n    ) -> ConnectorBuilder\n    where\n        T: Into<Option<IpAddr>>,\n    {\n        http.set_local_address(local_addr.into());\n        #[cfg(any(\n            target_os = \"android\",\n            target_os = \"fuchsia\",\n            target_os = \"illumos\",\n            target_os = \"ios\",\n            target_os = \"linux\",\n            target_os = \"macos\",\n            target_os = \"solaris\",\n            target_os = \"tvos\",\n            target_os = \"visionos\",\n            target_os = \"watchos\",\n        ))]\n        if let Some(interface) = interface {\n            http.set_interface(interface.to_owned());\n        }\n        http.set_nodelay(nodelay);\n        http.enforce_http(false);\n\n        let (tls, tls_proxy) = if proxies.is_empty() {\n            let tls = Arc::new(tls);\n            (tls.clone(), tls)\n        } else {\n            let mut tls_proxy = tls.clone();\n            tls_proxy.alpn_protocols.clear();\n            (Arc::new(tls), Arc::new(tls_proxy))\n        };\n\n        ConnectorBuilder {\n            inner: Inner::RustlsTls {\n                http,\n                tls,\n                tls_proxy,\n            },\n            proxies,\n            verbose: verbose::OFF,\n            nodelay,\n            tls_info,\n            user_agent,\n            timeout: None,\n            #[cfg(feature = \"socks\")]\n            resolver: None,\n            #[cfg(unix)]\n            unix_socket: None,\n            #[cfg(target_os = \"windows\")]\n            windows_named_pipe: None,\n        }\n    }\n\n    pub(crate) fn set_timeout(&mut self, timeout: Option<Duration>) {\n        self.timeout = timeout;\n    }\n\n    pub(crate) fn set_verbose(&mut self, enabled: bool) {\n        self.verbose.0 = enabled;\n    }\n\n    pub(crate) fn set_keepalive(&mut self, dur: Option<Duration>) {\n        match &mut self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, _tls) => http.set_keepalive(dur),\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, .. } => http.set_keepalive(dur),\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => http.set_keepalive(dur),\n        }\n    }\n\n    pub(crate) fn set_keepalive_interval(&mut self, dur: Option<Duration>) {\n        match &mut self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, _tls) => http.set_keepalive_interval(dur),\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, .. } => http.set_keepalive_interval(dur),\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => http.set_keepalive_interval(dur),\n        }\n    }\n\n    pub(crate) fn set_keepalive_retries(&mut self, retries: Option<u32>) {\n        match &mut self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, _tls) => http.set_keepalive_retries(retries),\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, .. } => http.set_keepalive_retries(retries),\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => http.set_keepalive_retries(retries),\n        }\n    }\n\n    #[cfg(feature = \"socks\")]\n    pub(crate) fn set_socks_resolver(&mut self, resolver: DynResolver) {\n        self.resolver = Some(resolver);\n    }\n\n    #[cfg(any(target_os = \"android\", target_os = \"fuchsia\", target_os = \"linux\"))]\n    pub(crate) fn set_tcp_user_timeout(&mut self, dur: Option<Duration>) {\n        match &mut self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, _tls) => http.set_tcp_user_timeout(dur),\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, .. } => http.set_tcp_user_timeout(dur),\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => http.set_tcp_user_timeout(dur),\n        }\n    }\n\n    #[cfg(unix)]\n    pub(crate) fn set_unix_socket(&mut self, path: Option<Arc<std::path::Path>>) {\n        self.unix_socket = path;\n    }\n\n    #[cfg(target_os = \"windows\")]\n    pub(crate) fn set_windows_named_pipe(&mut self, pipe: Option<Arc<std::ffi::OsStr>>) {\n        self.windows_named_pipe = pipe;\n    }\n}\n\n#[allow(missing_debug_implementations)]\n#[derive(Clone)]\npub(crate) struct ConnectorService {\n    inner: Inner,\n    proxies: Arc<Vec<ProxyMatcher>>,\n    verbose: verbose::Wrapper,\n    /// When there is a single timeout layer and no other layers,\n    /// we embed it directly inside our base Service::call().\n    /// This lets us avoid an extra `Box::pin` indirection layer\n    /// since `tokio::time::Timeout` is `Unpin`\n    simple_timeout: Option<Duration>,\n    #[cfg(feature = \"__tls\")]\n    nodelay: bool,\n    #[cfg(feature = \"__tls\")]\n    tls_info: bool,\n    #[cfg(feature = \"__tls\")]\n    user_agent: Option<HeaderValue>,\n    #[cfg(feature = \"socks\")]\n    resolver: DynResolver,\n    /// If set, this always takes priority over TCP.\n    #[cfg(unix)]\n    unix_socket: Option<Arc<std::path::Path>>,\n    #[cfg(target_os = \"windows\")]\n    windows_named_pipe: Option<Arc<std::ffi::OsStr>>,\n}\n\n#[derive(Clone)]\nenum Inner {\n    #[cfg(not(feature = \"__tls\"))]\n    Http(HttpConnector),\n    #[cfg(feature = \"__native-tls\")]\n    NativeTls(HttpConnector, TlsConnector),\n    #[cfg(any(feature = \"__rustls\"))]\n    RustlsTls {\n        http: HttpConnector,\n        tls: Arc<rustls::ClientConfig>,\n        tls_proxy: Arc<rustls::ClientConfig>,\n    },\n}\n\nimpl Inner {\n    #[cfg(feature = \"socks\")]\n    fn get_http_connector(&mut self) -> &mut crate::connect::HttpConnector {\n        match self {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, _) => http,\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, .. } => http,\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => http,\n        }\n    }\n}\n\nimpl ConnectorService {\n    #[cfg(feature = \"socks\")]\n    async fn connect_socks(mut self, dst: Uri, proxy: Intercepted) -> Result<Conn, BoxError> {\n        let dns = match proxy.uri().scheme_str() {\n            Some(\"socks4\") | Some(\"socks5\") => socks::DnsResolve::Local,\n            Some(\"socks4a\") | Some(\"socks5h\") => socks::DnsResolve::Proxy,\n            _ => {\n                unreachable!(\"connect_socks is only called for socks proxies\");\n            }\n        };\n\n        match &mut self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, tls) => {\n                if dst.scheme() == Some(&Scheme::HTTPS) {\n                    let host = dst.host().ok_or(\"no host in url\")?.to_string();\n                    let conn = socks::connect(proxy, dst, dns, &self.resolver, http).await?;\n                    let conn = TokioIo::new(conn);\n                    let conn = TokioIo::new(conn);\n                    let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());\n                    let io = tls_connector.connect(&host, conn).await?;\n                    let io = TokioIo::new(io);\n                    return Ok(Conn {\n                        inner: self.verbose.wrap(NativeTlsConn { inner: io }),\n                        is_proxy: false,\n                        tls_info: self.tls_info,\n                    });\n                }\n            }\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, tls, .. } => {\n                if dst.scheme() == Some(&Scheme::HTTPS) {\n                    use std::convert::TryFrom;\n                    use tokio_rustls::TlsConnector as RustlsConnector;\n\n                    let tls = tls.clone();\n                    let host = dst.host().ok_or(\"no host in url\")?.to_string();\n                    let conn = socks::connect(proxy, dst, dns, &self.resolver, http).await?;\n                    let conn = TokioIo::new(conn);\n                    let conn = TokioIo::new(conn);\n                    let server_name =\n                        rustls_pki_types::ServerName::try_from(host.as_str().to_owned())\n                            .map_err(|_| \"Invalid Server Name\")?;\n                    let io = RustlsConnector::from(tls)\n                        .connect(server_name, conn)\n                        .await?;\n                    let io = TokioIo::new(io);\n                    return Ok(Conn {\n                        inner: self.verbose.wrap(RustlsTlsConn { inner: io }),\n                        is_proxy: false,\n                        tls_info: false,\n                    });\n                }\n            }\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(http) => {\n                let conn = socks::connect(proxy, dst, dns, &self.resolver, http).await?;\n                return Ok(Conn {\n                    inner: self.verbose.wrap(TokioIo::new(conn)),\n                    is_proxy: false,\n                    tls_info: false,\n                });\n            }\n        }\n\n        let resolver = &self.resolver;\n        let http = self.inner.get_http_connector();\n        socks::connect(proxy, dst, dns, resolver, http)\n            .await\n            .map(|tcp| Conn {\n                inner: self.verbose.wrap(TokioIo::new(tcp)),\n                is_proxy: false,\n                tls_info: false,\n            })\n            .map_err(Into::into)\n    }\n\n    async fn connect_with_maybe_proxy(self, dst: Uri, is_proxy: bool) -> Result<Conn, BoxError> {\n        match self.inner {\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(mut http) => {\n                let io = http.call(dst).await?;\n                Ok(Conn {\n                    inner: self.verbose.wrap(io),\n                    is_proxy,\n                    tls_info: false,\n                })\n            }\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, tls) => {\n                let mut http = http.clone();\n\n                // Disable Nagle's algorithm for TLS handshake\n                //\n                // https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES\n                if !self.nodelay && (dst.scheme() == Some(&Scheme::HTTPS)) {\n                    http.set_nodelay(true);\n                }\n\n                let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());\n                let mut http = hyper_tls::HttpsConnector::from((http, tls_connector));\n                let io = http.call(dst).await?;\n\n                if let hyper_tls::MaybeHttpsStream::Https(stream) = io {\n                    if !self.nodelay {\n                        stream\n                            .inner()\n                            .get_ref()\n                            .get_ref()\n                            .get_ref()\n                            .inner()\n                            .inner()\n                            .set_nodelay(false)?;\n                    }\n                    Ok(Conn {\n                        inner: self.verbose.wrap(NativeTlsConn { inner: stream }),\n                        is_proxy,\n                        tls_info: self.tls_info,\n                    })\n                } else {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(io),\n                        is_proxy,\n                        tls_info: false,\n                    })\n                }\n            }\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { http, tls, .. } => {\n                let mut http = http.clone();\n\n                // Disable Nagle's algorithm for TLS handshake\n                //\n                // https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES\n                if !self.nodelay && (dst.scheme() == Some(&Scheme::HTTPS)) {\n                    http.set_nodelay(true);\n                }\n\n                let mut http = hyper_rustls::HttpsConnector::from((http, tls.clone()));\n                let io = http.call(dst).await?;\n\n                if let hyper_rustls::MaybeHttpsStream::Https(stream) = io {\n                    if !self.nodelay {\n                        let (io, _) = stream.inner().get_ref();\n                        io.inner().inner().set_nodelay(false)?;\n                    }\n                    Ok(Conn {\n                        inner: self.verbose.wrap(RustlsTlsConn { inner: stream }),\n                        is_proxy,\n                        tls_info: self.tls_info,\n                    })\n                } else {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(io),\n                        is_proxy,\n                        tls_info: false,\n                    })\n                }\n            }\n        }\n    }\n\n    /// Connect over a local transport: Unix Domain Socket (on Unix) or Windows Named Pipe (on Windows).\n    #[cfg(any(unix, target_os = \"windows\"))]\n    async fn connect_local_transport(self, dst: Uri) -> Result<Conn, BoxError> {\n        #[cfg(unix)]\n        let svc = {\n            let path = self\n                .unix_socket\n                .as_ref()\n                .expect(\"connect local must have socket path\")\n                .clone();\n            tower::service_fn(move |_| {\n                let fut = tokio::net::UnixStream::connect(path.clone());\n                async move {\n                    let io = fut.await?;\n                    Ok::<_, std::io::Error>(TokioIo::new(io))\n                }\n            })\n        };\n        #[cfg(target_os = \"windows\")]\n        let svc = {\n            use tokio::net::windows::named_pipe::ClientOptions;\n            let pipe = self\n                .windows_named_pipe\n                .as_ref()\n                .expect(\"connect local must have pipe path\")\n                .clone();\n            tower::service_fn(move |_| {\n                let pipe = pipe.clone();\n                async move { ClientOptions::new().open(pipe).map(TokioIo::new) }\n            })\n        };\n        let is_proxy = false;\n        match self.inner {\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(..) => {\n                let mut svc = svc;\n                let io = svc.call(dst).await?;\n                Ok(Conn {\n                    inner: self.verbose.wrap(io),\n                    is_proxy,\n                    tls_info: false,\n                })\n            }\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(_, tls) => {\n                let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());\n                let mut http = hyper_tls::HttpsConnector::from((svc, tls_connector));\n                let io = http.call(dst).await?;\n\n                if let hyper_tls::MaybeHttpsStream::Https(stream) = io {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(NativeTlsConn { inner: stream }),\n                        is_proxy,\n                        tls_info: self.tls_info,\n                    })\n                } else {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(io),\n                        is_proxy,\n                        tls_info: false,\n                    })\n                }\n            }\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls { tls, .. } => {\n                let mut http = hyper_rustls::HttpsConnector::from((svc, tls.clone()));\n                let io = http.call(dst).await?;\n\n                if let hyper_rustls::MaybeHttpsStream::Https(stream) = io {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(RustlsTlsConn { inner: stream }),\n                        is_proxy,\n                        tls_info: self.tls_info,\n                    })\n                } else {\n                    Ok(Conn {\n                        inner: self.verbose.wrap(io),\n                        is_proxy,\n                        tls_info: false,\n                    })\n                }\n            }\n        }\n    }\n\n    async fn connect_via_proxy(self, dst: Uri, proxy: Intercepted) -> Result<Conn, BoxError> {\n        log::debug!(\"proxy({proxy:?}) intercepts '{:?}'\", dst.host());\n\n        #[cfg(feature = \"socks\")]\n        match proxy.uri().scheme_str().ok_or(\"proxy scheme expected\")? {\n            \"socks4\" | \"socks4a\" | \"socks5\" | \"socks5h\" => {\n                return self.connect_socks(dst, proxy).await\n            }\n            _ => (),\n        }\n\n        let proxy_dst = proxy.uri().clone();\n        #[cfg(feature = \"__tls\")]\n        let auth = proxy.basic_auth().cloned();\n\n        #[cfg(feature = \"__tls\")]\n        let misc = proxy.custom_headers().clone();\n\n        match &self.inner {\n            #[cfg(feature = \"__native-tls\")]\n            Inner::NativeTls(http, tls) => {\n                if dst.scheme() == Some(&Scheme::HTTPS) {\n                    log::trace!(\"tunneling HTTPS over proxy\");\n                    let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());\n                    let inner =\n                        hyper_tls::HttpsConnector::from((http.clone(), tls_connector.clone()));\n                    // TODO: we could cache constructing this\n                    let mut tunnel =\n                        hyper_util::client::legacy::connect::proxy::Tunnel::new(proxy_dst, inner);\n                    if let Some(auth) = auth {\n                        tunnel = tunnel.with_auth(auth);\n                    }\n                    if let Some(ua) = self.user_agent {\n                        let mut headers = http::HeaderMap::new();\n                        headers.insert(http::header::USER_AGENT, ua);\n                        tunnel = tunnel.with_headers(headers);\n                    }\n                    // Note that custom headers may override the user agent header.\n                    if let Some(custom_headers) = misc {\n                        tunnel = tunnel.with_headers(custom_headers.clone());\n                    }\n                    // We don't wrap this again in an HttpsConnector since that uses Maybe,\n                    // and we know this is definitely HTTPS.\n                    let tunneled = tunnel.call(dst.clone()).await?;\n                    let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());\n                    let io = tls_connector\n                        .connect(dst.host().ok_or(\"no host in url\")?, TokioIo::new(tunneled))\n                        .await?;\n                    return Ok(Conn {\n                        inner: self.verbose.wrap(NativeTlsConn {\n                            inner: TokioIo::new(io),\n                        }),\n                        is_proxy: false,\n                        tls_info: false,\n                    });\n                }\n            }\n            #[cfg(feature = \"__rustls\")]\n            Inner::RustlsTls {\n                http,\n                tls,\n                tls_proxy,\n            } => {\n                if dst.scheme() == Some(&Scheme::HTTPS) {\n                    use rustls_pki_types::ServerName;\n                    use std::convert::TryFrom;\n                    use tokio_rustls::TlsConnector as RustlsConnector;\n\n                    log::trace!(\"tunneling HTTPS over proxy\");\n                    let http = http.clone();\n                    let inner = hyper_rustls::HttpsConnector::from((http, tls_proxy.clone()));\n                    // TODO: we could cache constructing this\n                    let mut tunnel =\n                        hyper_util::client::legacy::connect::proxy::Tunnel::new(proxy_dst, inner);\n                    if let Some(auth) = auth {\n                        tunnel = tunnel.with_auth(auth);\n                    }\n                    if let Some(custom_headers) = misc {\n                        tunnel = tunnel.with_headers(custom_headers.clone());\n                    }\n                    if let Some(ua) = self.user_agent {\n                        let mut headers = http::HeaderMap::new();\n                        headers.insert(http::header::USER_AGENT, ua);\n                        tunnel = tunnel.with_headers(headers);\n                    }\n                    // We don't wrap this again in an HttpsConnector since that uses Maybe,\n                    // and we know this is definitely HTTPS.\n                    let tunneled = tunnel.call(dst.clone()).await?;\n                    let host = dst.host().ok_or(\"no host in url\")?.to_string();\n                    let server_name = ServerName::try_from(host.as_str().to_owned())\n                        .map_err(|_| \"Invalid Server Name\")?;\n                    let io = RustlsConnector::from(tls.clone())\n                        .connect(server_name, TokioIo::new(tunneled))\n                        .await?;\n\n                    return Ok(Conn {\n                        inner: self.verbose.wrap(RustlsTlsConn {\n                            inner: TokioIo::new(io),\n                        }),\n                        is_proxy: false,\n                        tls_info: false,\n                    });\n                }\n            }\n            #[cfg(not(feature = \"__tls\"))]\n            Inner::Http(_) => (),\n        }\n\n        self.connect_with_maybe_proxy(proxy_dst, true).await\n    }\n\n    #[cfg(any(unix, target_os = \"windows\"))]\n    fn should_use_local_transport(&self) -> bool {\n        #[cfg(unix)]\n        return self.unix_socket.is_some();\n\n        #[cfg(target_os = \"windows\")]\n        return self.windows_named_pipe.is_some();\n    }\n}\n\nasync fn with_timeout<T, F>(f: F, timeout: Option<Duration>) -> Result<T, BoxError>\nwhere\n    F: Future<Output = Result<T, BoxError>>,\n{\n    if let Some(to) = timeout {\n        match tokio::time::timeout(to, f).await {\n            Err(_elapsed) => Err(Box::new(crate::error::TimedOut) as BoxError),\n            Ok(Ok(try_res)) => Ok(try_res),\n            Ok(Err(e)) => Err(e),\n        }\n    } else {\n        f.await\n    }\n}\n\nimpl Service<Uri> for ConnectorService {\n    type Response = Conn;\n    type Error = BoxError;\n    type Future = Connecting;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, dst: Uri) -> Self::Future {\n        log::debug!(\"starting new connection '{:?}'\", dst.host());\n        let timeout = self.simple_timeout;\n\n        // Local transports (UDS, Windows Named Pipes) skip proxies\n        #[cfg(any(unix, target_os = \"windows\"))]\n        if self.should_use_local_transport() {\n            return Box::pin(with_timeout(\n                self.clone().connect_local_transport(dst),\n                timeout,\n            ));\n        }\n\n        for prox in self.proxies.iter() {\n            if let Some(intercepted) = prox.intercept(&dst) {\n                return Box::pin(with_timeout(\n                    self.clone().connect_via_proxy(dst, intercepted),\n                    timeout,\n                ));\n            }\n        }\n\n        Box::pin(with_timeout(\n            self.clone().connect_with_maybe_proxy(dst, false),\n            timeout,\n        ))\n    }\n}\n\n#[cfg(feature = \"__tls\")]\ntrait TlsInfoFactory {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo>;\n}\n\n#[cfg(feature = \"__tls\")]\nimpl<T: TlsInfoFactory> TlsInfoFactory for TokioIo<T> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        self.inner().tls_info()\n    }\n}\n\n// ===== TcpStream =====\n\n#[cfg(feature = \"__tls\")]\nimpl TlsInfoFactory for tokio::net::TcpStream {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        None\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\nimpl TlsInfoFactory for tokio_native_tls::TlsStream<TokioIo<TokioIo<tokio::net::TcpStream>>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\nimpl TlsInfoFactory\n    for tokio_native_tls::TlsStream<\n        TokioIo<hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::TcpStream>>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\nimpl TlsInfoFactory for hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::TcpStream>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_tls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_tls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl TlsInfoFactory for tokio_rustls::client::TlsStream<TokioIo<TokioIo<tokio::net::TcpStream>>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl TlsInfoFactory\n    for tokio_rustls::client::TlsStream<\n        TokioIo<hyper_rustls::MaybeHttpsStream<TokioIo<tokio::net::TcpStream>>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl TlsInfoFactory for hyper_rustls::MaybeHttpsStream<TokioIo<tokio::net::TcpStream>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_rustls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_rustls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\n// ===== UnixStream =====\n\n#[cfg(feature = \"__tls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory for tokio::net::UnixStream {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        None\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory for tokio_native_tls::TlsStream<TokioIo<TokioIo<tokio::net::UnixStream>>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory\n    for tokio_native_tls::TlsStream<\n        TokioIo<hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::UnixStream>>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory for hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::UnixStream>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_tls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_tls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory for tokio_rustls::client::TlsStream<TokioIo<TokioIo<tokio::net::UnixStream>>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory\n    for tokio_rustls::client::TlsStream<\n        TokioIo<hyper_rustls::MaybeHttpsStream<TokioIo<tokio::net::UnixStream>>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(unix)]\nimpl TlsInfoFactory for hyper_rustls::MaybeHttpsStream<TokioIo<tokio::net::UnixStream>> {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_rustls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_rustls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\n// ===== NamedPipe =====\n\n#[cfg(feature = \"__tls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory for tokio::net::windows::named_pipe::NamedPipeClient {\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        None\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for tokio_native_tls::TlsStream<\n        TokioIo<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for tokio_native_tls::TlsStream<\n        TokioIo<\n            hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>,\n        >,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .peer_certificate()\n            .ok()\n            .flatten()\n            .and_then(|c| c.to_der().ok());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_tls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_tls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for tokio_rustls::client::TlsStream<\n        TokioIo<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for tokio_rustls::client::TlsStream<\n        TokioIo<\n            hyper_rustls::MaybeHttpsStream<\n                TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>,\n            >,\n        >,\n    >\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        let peer_certificate = self\n            .get_ref()\n            .1\n            .peer_certificates()\n            .and_then(|certs| certs.first())\n            .map(|c| c.to_vec());\n        Some(crate::tls::TlsInfo { peer_certificate })\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(target_os = \"windows\")]\nimpl TlsInfoFactory\n    for hyper_rustls::MaybeHttpsStream<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>\n{\n    fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n        match self {\n            hyper_rustls::MaybeHttpsStream::Https(tls) => tls.tls_info(),\n            hyper_rustls::MaybeHttpsStream::Http(_) => None,\n        }\n    }\n}\n\npub(crate) trait AsyncConn:\n    Read + Write + Connection + Send + Sync + Unpin + 'static\n{\n}\n\nimpl<T: Read + Write + Connection + Send + Sync + Unpin + 'static> AsyncConn for T {}\n\n#[cfg(feature = \"__tls\")]\ntrait AsyncConnWithInfo: AsyncConn + TlsInfoFactory {}\n#[cfg(not(feature = \"__tls\"))]\ntrait AsyncConnWithInfo: AsyncConn {}\n\n#[cfg(feature = \"__tls\")]\nimpl<T: AsyncConn + TlsInfoFactory> AsyncConnWithInfo for T {}\n#[cfg(not(feature = \"__tls\"))]\nimpl<T: AsyncConn> AsyncConnWithInfo for T {}\n\ntype BoxConn = Box<dyn AsyncConnWithInfo>;\n\npub(crate) mod sealed {\n    use super::*;\n    #[derive(Debug)]\n    pub struct Unnameable(pub(super) Uri);\n\n    pin_project! {\n        /// Note: the `is_proxy` member means *is plain text HTTP proxy*.\n        /// This tells hyper whether the URI should be written in\n        /// * origin-form (`GET /just/a/path HTTP/1.1`), when `is_proxy == false`, or\n        /// * absolute-form (`GET http://foo.bar/and/a/path HTTP/1.1`), otherwise.\n        #[allow(missing_debug_implementations)]\n        pub struct Conn {\n            #[pin]\n            pub(super)inner: BoxConn,\n            pub(super) is_proxy: bool,\n            // Only needed for __tls, but #[cfg()] on fields breaks pin_project!\n            pub(super) tls_info: bool,\n        }\n    }\n\n    impl Connection for Conn {\n        fn connected(&self) -> Connected {\n            let connected = self.inner.connected().proxy(self.is_proxy);\n            #[cfg(feature = \"__tls\")]\n            if self.tls_info {\n                if let Some(tls_info) = self.inner.tls_info() {\n                    connected.extra(tls_info)\n                } else {\n                    connected\n                }\n            } else {\n                connected\n            }\n            #[cfg(not(feature = \"__tls\"))]\n            connected\n        }\n    }\n\n    impl Read for Conn {\n        fn poll_read(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: ReadBufCursor<'_>,\n        ) -> Poll<io::Result<()>> {\n            let this = self.project();\n            Read::poll_read(this.inner, cx, buf)\n        }\n    }\n\n    impl Write for Conn {\n        fn poll_write(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: &[u8],\n        ) -> Poll<Result<usize, io::Error>> {\n            let this = self.project();\n            Write::poll_write(this.inner, cx, buf)\n        }\n\n        fn poll_write_vectored(\n            self: Pin<&mut Self>,\n            cx: &mut Context<'_>,\n            bufs: &[IoSlice<'_>],\n        ) -> Poll<Result<usize, io::Error>> {\n            let this = self.project();\n            Write::poll_write_vectored(this.inner, cx, bufs)\n        }\n\n        fn is_write_vectored(&self) -> bool {\n            self.inner.is_write_vectored()\n        }\n\n        fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {\n            let this = self.project();\n            Write::poll_flush(this.inner, cx)\n        }\n\n        fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {\n            let this = self.project();\n            Write::poll_shutdown(this.inner, cx)\n        }\n    }\n}\n\n// Some sealed things for UDS\n#[cfg(unix)]\npub(crate) mod uds {\n    use std::path::Path;\n\n    /// A provider for Unix Domain Socket paths.\n    ///\n    /// This trait is sealed. This allows us expand the support in the future\n    /// by controlling who can implement the trait.\n    ///\n    /// It's available in the docs to see what type may be passed in.\n    #[cfg(unix)]\n    pub trait UnixSocketProvider {\n        #[doc(hidden)]\n        fn reqwest_uds_path(&self, _: Internal) -> &Path;\n    }\n\n    #[allow(missing_debug_implementations)]\n    pub struct Internal;\n\n    macro_rules! as_path {\n        ($($t:ty,)+) => {\n            $(\n                impl UnixSocketProvider for $t {\n                    #[doc(hidden)]\n                    fn reqwest_uds_path(&self, _: Internal) -> &Path {\n                        self.as_ref()\n                    }\n                }\n            )+\n        }\n    }\n\n    as_path![\n        String,\n        &'_ str,\n        &'_ Path,\n        std::path::PathBuf,\n        std::sync::Arc<Path>,\n    ];\n}\n\n// Sealed trait for Windows Named Pipe support\n#[cfg(target_os = \"windows\")]\npub(crate) mod windows_named_pipe {\n    use std::ffi::OsStr;\n    /// A provider for Windows Named Pipe paths.\n    ///\n    /// This trait is sealed. This allows us to expand support in the future\n    /// by controlling who can implement the trait.\n    #[cfg(target_os = \"windows\")]\n    pub trait WindowsNamedPipeProvider {\n        #[doc(hidden)]\n        fn reqwest_windows_named_pipe_path(&self, _: Internal) -> &OsStr;\n    }\n\n    #[allow(missing_debug_implementations)]\n    pub struct Internal;\n\n    macro_rules! as_os_str {\n        ($($t:ty,)+) => {\n            $(\n                impl WindowsNamedPipeProvider for $t {\n                    #[doc(hidden)]\n                    fn reqwest_windows_named_pipe_path(&self, _: Internal) -> &OsStr {\n                        self.as_ref()\n                    }\n                }\n            )+\n        }\n    }\n\n    as_os_str![\n        String,\n        &'_ str,\n        std::path::PathBuf,\n        &'_ std::path::Path,\n        std::ffi::OsString,\n        &'_ OsStr,\n    ];\n}\n\npub(crate) type Connecting = Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>;\n\n#[cfg(feature = \"__native-tls\")]\nmod native_tls_conn {\n    use super::TlsInfoFactory;\n    use hyper::rt::{Read, ReadBufCursor, Write};\n    use hyper_tls::MaybeHttpsStream;\n    use hyper_util::client::legacy::connect::{Connected, Connection};\n    use hyper_util::rt::TokioIo;\n    use pin_project_lite::pin_project;\n    use std::{\n        io::{self, IoSlice},\n        pin::Pin,\n        task::{Context, Poll},\n    };\n    use tokio::io::{AsyncRead, AsyncWrite};\n    use tokio::net::TcpStream;\n    use tokio_native_tls::TlsStream;\n\n    pin_project! {\n        pub(super) struct NativeTlsConn<T> {\n            #[pin] pub(super) inner: TokioIo<TlsStream<T>>,\n        }\n    }\n\n    impl Connection for NativeTlsConn<TokioIo<TokioIo<TcpStream>>> {\n        fn connected(&self) -> Connected {\n            let connected = self\n                .inner\n                .inner()\n                .get_ref()\n                .get_ref()\n                .get_ref()\n                .inner()\n                .connected();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    impl Connection for NativeTlsConn<TokioIo<MaybeHttpsStream<TokioIo<TcpStream>>>> {\n        fn connected(&self) -> Connected {\n            let connected = self\n                .inner\n                .inner()\n                .get_ref()\n                .get_ref()\n                .get_ref()\n                .inner()\n                .connected();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    #[cfg(unix)]\n    impl Connection for NativeTlsConn<TokioIo<TokioIo<tokio::net::UnixStream>>> {\n        fn connected(&self) -> Connected {\n            let connected = Connected::new();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    #[cfg(unix)]\n    impl Connection for NativeTlsConn<TokioIo<MaybeHttpsStream<TokioIo<tokio::net::UnixStream>>>> {\n        fn connected(&self) -> Connected {\n            let connected = Connected::new();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    #[cfg(target_os = \"windows\")]\n    impl Connection\n        for NativeTlsConn<TokioIo<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>>\n    {\n        fn connected(&self) -> Connected {\n            let connected = Connected::new();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    #[cfg(target_os = \"windows\")]\n    impl Connection\n        for NativeTlsConn<\n            TokioIo<MaybeHttpsStream<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>>,\n        >\n    {\n        fn connected(&self) -> Connected {\n            let connected = Connected::new();\n            #[cfg(feature = \"__native-tls-alpn\")]\n            match self.inner.inner().get_ref().negotiated_alpn().ok() {\n                Some(Some(alpn_protocol)) if alpn_protocol == b\"h2\" => connected.negotiated_h2(),\n                _ => connected,\n            }\n            #[cfg(not(feature = \"__native-tls-alpn\"))]\n            connected\n        }\n    }\n\n    impl<T: AsyncRead + AsyncWrite + Unpin> Read for NativeTlsConn<T> {\n        fn poll_read(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: ReadBufCursor<'_>,\n        ) -> Poll<tokio::io::Result<()>> {\n            let this = self.project();\n            Read::poll_read(this.inner, cx, buf)\n        }\n    }\n\n    impl<T: AsyncRead + AsyncWrite + Unpin> Write for NativeTlsConn<T> {\n        fn poll_write(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: &[u8],\n        ) -> Poll<Result<usize, tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_write(this.inner, cx, buf)\n        }\n\n        fn poll_write_vectored(\n            self: Pin<&mut Self>,\n            cx: &mut Context<'_>,\n            bufs: &[IoSlice<'_>],\n        ) -> Poll<Result<usize, io::Error>> {\n            let this = self.project();\n            Write::poll_write_vectored(this.inner, cx, bufs)\n        }\n\n        fn is_write_vectored(&self) -> bool {\n            self.inner.is_write_vectored()\n        }\n\n        fn poll_flush(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_flush(this.inner, cx)\n        }\n\n        fn poll_shutdown(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_shutdown(this.inner, cx)\n        }\n    }\n\n    impl<T> TlsInfoFactory for NativeTlsConn<T>\n    where\n        TokioIo<TlsStream<T>>: TlsInfoFactory,\n    {\n        fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n            self.inner.tls_info()\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nmod rustls_tls_conn {\n    use super::TlsInfoFactory;\n    use hyper::rt::{Read, ReadBufCursor, Write};\n    use hyper_rustls::MaybeHttpsStream;\n    use hyper_util::client::legacy::connect::{Connected, Connection};\n    use hyper_util::rt::TokioIo;\n    use pin_project_lite::pin_project;\n    use std::{\n        io::{self, IoSlice},\n        pin::Pin,\n        task::{Context, Poll},\n    };\n    use tokio::io::{AsyncRead, AsyncWrite};\n    use tokio::net::TcpStream;\n    use tokio_rustls::client::TlsStream;\n\n    pin_project! {\n        pub(super) struct RustlsTlsConn<T> {\n            #[pin] pub(super) inner: TokioIo<TlsStream<T>>,\n        }\n    }\n\n    impl Connection for RustlsTlsConn<TokioIo<TokioIo<TcpStream>>> {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n    impl Connection for RustlsTlsConn<TokioIo<MaybeHttpsStream<TokioIo<TcpStream>>>> {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n\n    #[cfg(unix)]\n    impl Connection for RustlsTlsConn<TokioIo<TokioIo<tokio::net::UnixStream>>> {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n\n    #[cfg(unix)]\n    impl Connection for RustlsTlsConn<TokioIo<MaybeHttpsStream<TokioIo<tokio::net::UnixStream>>>> {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n\n    #[cfg(target_os = \"windows\")]\n    impl Connection\n        for RustlsTlsConn<TokioIo<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>>\n    {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n\n    #[cfg(target_os = \"windows\")]\n    impl Connection\n        for RustlsTlsConn<\n            TokioIo<MaybeHttpsStream<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>>,\n        >\n    {\n        fn connected(&self) -> Connected {\n            if self.inner.inner().get_ref().1.alpn_protocol() == Some(b\"h2\") {\n                self.inner\n                    .inner()\n                    .get_ref()\n                    .0\n                    .inner()\n                    .connected()\n                    .negotiated_h2()\n            } else {\n                self.inner.inner().get_ref().0.inner().connected()\n            }\n        }\n    }\n\n    impl<T: AsyncRead + AsyncWrite + Unpin> Read for RustlsTlsConn<T> {\n        fn poll_read(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: ReadBufCursor<'_>,\n        ) -> Poll<tokio::io::Result<()>> {\n            let this = self.project();\n            Read::poll_read(this.inner, cx, buf)\n        }\n    }\n\n    impl<T: AsyncRead + AsyncWrite + Unpin> Write for RustlsTlsConn<T> {\n        fn poll_write(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: &[u8],\n        ) -> Poll<Result<usize, tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_write(this.inner, cx, buf)\n        }\n\n        fn poll_write_vectored(\n            self: Pin<&mut Self>,\n            cx: &mut Context<'_>,\n            bufs: &[IoSlice<'_>],\n        ) -> Poll<Result<usize, io::Error>> {\n            let this = self.project();\n            Write::poll_write_vectored(this.inner, cx, bufs)\n        }\n\n        fn is_write_vectored(&self) -> bool {\n            self.inner.is_write_vectored()\n        }\n\n        fn poll_flush(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_flush(this.inner, cx)\n        }\n\n        fn poll_shutdown(\n            self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), tokio::io::Error>> {\n            let this = self.project();\n            Write::poll_shutdown(this.inner, cx)\n        }\n    }\n    impl<T> TlsInfoFactory for RustlsTlsConn<T>\n    where\n        TokioIo<TlsStream<T>>: TlsInfoFactory,\n    {\n        fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n            self.inner.tls_info()\n        }\n    }\n}\n\n#[cfg(feature = \"socks\")]\nmod socks {\n    use tower_service::Service;\n\n    use http::uri::Scheme;\n    use http::Uri;\n    use hyper_util::client::legacy::connect::proxy::{SocksV4, SocksV5};\n    use tokio::net::TcpStream;\n\n    use super::BoxError;\n    use crate::proxy::Intercepted;\n\n    pub(super) enum DnsResolve {\n        Local,\n        Proxy,\n    }\n\n    #[derive(Debug)]\n    pub(super) enum SocksProxyError {\n        SocksNoHostInUrl,\n        SocksLocalResolve(BoxError),\n        SocksConnect(BoxError),\n    }\n\n    pub(super) async fn connect(\n        proxy: Intercepted,\n        dst: Uri,\n        dns_mode: DnsResolve,\n        resolver: &crate::dns::DynResolver,\n        http_connector: &mut crate::connect::HttpConnector,\n    ) -> Result<TcpStream, SocksProxyError> {\n        let https = dst.scheme() == Some(&Scheme::HTTPS);\n        let original_host = dst.host().ok_or(SocksProxyError::SocksNoHostInUrl)?;\n        let mut host = original_host.to_owned();\n        let port = match dst.port() {\n            Some(p) => p.as_u16(),\n            None if https => 443u16,\n            _ => 80u16,\n        };\n\n        if let DnsResolve::Local = dns_mode {\n            let maybe_new_target = resolver\n                .http_resolve(&dst)\n                .await\n                .map_err(SocksProxyError::SocksLocalResolve)?\n                .next();\n            if let Some(new_target) = maybe_new_target {\n                log::trace!(\"socks local dns resolved {new_target:?}\");\n                // If the resolved IP is IPv6, wrap it in brackets for URI formatting\n                let ip = new_target.ip();\n                if ip.is_ipv6() {\n                    host = format!(\"[{}]\", ip);\n                } else {\n                    host = ip.to_string();\n                }\n            }\n        }\n\n        let proxy_uri = proxy.uri().clone();\n        // Build a Uri for the destination\n        let dst_uri = format!(\n            \"{}://{}:{}\",\n            if https { \"https\" } else { \"http\" },\n            host,\n            port\n        )\n        .parse::<Uri>()\n        .map_err(|e| SocksProxyError::SocksConnect(e.into()))?;\n\n        // TODO: can `Scheme::from_static()` be const fn, compare with a SOCKS5 constant?\n        match proxy.uri().scheme_str() {\n            Some(\"socks4\") | Some(\"socks4a\") => {\n                let mut svc = SocksV4::new(proxy_uri, http_connector);\n                let stream = Service::call(&mut svc, dst_uri)\n                    .await\n                    .map_err(|e| SocksProxyError::SocksConnect(e.into()))?;\n                Ok(stream.into_inner())\n            }\n            Some(\"socks5\") | Some(\"socks5h\") => {\n                let mut svc = if let Some((username, password)) = proxy.raw_auth() {\n                    SocksV5::new(proxy_uri, http_connector)\n                        .with_auth(username.to_string(), password.to_string())\n                } else {\n                    SocksV5::new(proxy_uri, http_connector)\n                };\n                let stream = Service::call(&mut svc, dst_uri)\n                    .await\n                    .map_err(|e| SocksProxyError::SocksConnect(e.into()))?;\n                Ok(stream.into_inner())\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    impl std::fmt::Display for SocksProxyError {\n        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n            match self {\n                Self::SocksNoHostInUrl => f.write_str(\"socks proxy destination has no host\"),\n                Self::SocksLocalResolve(_) => f.write_str(\"error resolving for socks proxy\"),\n                Self::SocksConnect(_) => f.write_str(\"error connecting to socks proxy\"),\n            }\n        }\n    }\n\n    impl std::error::Error for SocksProxyError {\n        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n            match self {\n                Self::SocksNoHostInUrl => None,\n                Self::SocksLocalResolve(ref e) => Some(&**e),\n                Self::SocksConnect(ref e) => Some(&**e),\n            }\n        }\n    }\n}\n\nmod verbose {\n    use crate::util::Escape;\n    use hyper::rt::{Read, ReadBufCursor, Write};\n    use hyper_util::client::legacy::connect::{Connected, Connection};\n    use std::cmp::min;\n    use std::fmt;\n    use std::io::{self, IoSlice};\n    use std::pin::Pin;\n    use std::task::{Context, Poll};\n\n    pub(super) const OFF: Wrapper = Wrapper(false);\n\n    #[derive(Clone, Copy)]\n    pub(super) struct Wrapper(pub(super) bool);\n\n    impl Wrapper {\n        pub(super) fn wrap<T: super::AsyncConnWithInfo>(&self, conn: T) -> super::BoxConn {\n            if self.0 && log::log_enabled!(log::Level::Trace) {\n                Box::new(Verbose {\n                    // truncate is fine\n                    id: crate::util::fast_random() as u32,\n                    inner: conn,\n                })\n            } else {\n                Box::new(conn)\n            }\n        }\n    }\n\n    struct Verbose<T> {\n        id: u32,\n        inner: T,\n    }\n\n    impl<T: Connection + Read + Write + Unpin> Connection for Verbose<T> {\n        fn connected(&self) -> Connected {\n            self.inner.connected()\n        }\n    }\n\n    impl<T: Read + Write + Unpin> Read for Verbose<T> {\n        fn poll_read(\n            mut self: Pin<&mut Self>,\n            cx: &mut Context,\n            mut buf: ReadBufCursor<'_>,\n        ) -> Poll<std::io::Result<()>> {\n            // TODO: This _does_ forget the `init` len, so it could result in\n            // re-initializing twice. Needs upstream support, perhaps.\n            // SAFETY: Passing to a ReadBuf will never de-initialize any bytes.\n            let mut vbuf = hyper::rt::ReadBuf::uninit(unsafe { buf.as_mut() });\n            match Pin::new(&mut self.inner).poll_read(cx, vbuf.unfilled()) {\n                Poll::Ready(Ok(())) => {\n                    log::trace!(\"{:08x} read: {:?}\", self.id, Escape::new(vbuf.filled()));\n                    let len = vbuf.filled().len();\n                    // SAFETY: The two cursors were for the same buffer. What was\n                    // filled in one is safe in the other.\n                    unsafe {\n                        buf.advance(len);\n                    }\n                    Poll::Ready(Ok(()))\n                }\n                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),\n                Poll::Pending => Poll::Pending,\n            }\n        }\n    }\n\n    impl<T: Read + Write + Unpin> Write for Verbose<T> {\n        fn poll_write(\n            mut self: Pin<&mut Self>,\n            cx: &mut Context,\n            buf: &[u8],\n        ) -> Poll<Result<usize, std::io::Error>> {\n            match Pin::new(&mut self.inner).poll_write(cx, buf) {\n                Poll::Ready(Ok(n)) => {\n                    log::trace!(\"{:08x} write: {:?}\", self.id, Escape::new(&buf[..n]));\n                    Poll::Ready(Ok(n))\n                }\n                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),\n                Poll::Pending => Poll::Pending,\n            }\n        }\n\n        fn poll_write_vectored(\n            mut self: Pin<&mut Self>,\n            cx: &mut Context<'_>,\n            bufs: &[IoSlice<'_>],\n        ) -> Poll<Result<usize, io::Error>> {\n            match Pin::new(&mut self.inner).poll_write_vectored(cx, bufs) {\n                Poll::Ready(Ok(nwritten)) => {\n                    log::trace!(\n                        \"{:08x} write (vectored): {:?}\",\n                        self.id,\n                        Vectored { bufs, nwritten }\n                    );\n                    Poll::Ready(Ok(nwritten))\n                }\n                Poll::Ready(Err(e)) => Poll::Ready(Err(e)),\n                Poll::Pending => Poll::Pending,\n            }\n        }\n\n        fn is_write_vectored(&self) -> bool {\n            self.inner.is_write_vectored()\n        }\n\n        fn poll_flush(\n            mut self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), std::io::Error>> {\n            Pin::new(&mut self.inner).poll_flush(cx)\n        }\n\n        fn poll_shutdown(\n            mut self: Pin<&mut Self>,\n            cx: &mut Context,\n        ) -> Poll<Result<(), std::io::Error>> {\n            Pin::new(&mut self.inner).poll_shutdown(cx)\n        }\n    }\n\n    #[cfg(feature = \"__tls\")]\n    impl<T: super::TlsInfoFactory> super::TlsInfoFactory for Verbose<T> {\n        fn tls_info(&self) -> Option<crate::tls::TlsInfo> {\n            self.inner.tls_info()\n        }\n    }\n\n    struct Vectored<'a, 'b> {\n        bufs: &'a [IoSlice<'b>],\n        nwritten: usize,\n    }\n\n    impl fmt::Debug for Vectored<'_, '_> {\n        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n            let mut left = self.nwritten;\n            for buf in self.bufs.iter() {\n                if left == 0 {\n                    break;\n                }\n                let n = min(left, buf.len());\n                Escape::new(&buf[..n]).fmt(f)?;\n                left -= n;\n            }\n            Ok(())\n        }\n    }\n}\n"
  },
  {
    "path": "src/cookie.rs",
    "content": "//! HTTP Cookies\n\nuse crate::header::{HeaderValue, SET_COOKIE};\nuse bytes::Bytes;\nuse std::convert::TryInto;\nuse std::fmt;\nuse std::sync::RwLock;\nuse std::time::SystemTime;\n\n/// Actions for a persistent cookie store providing session support.\npub trait CookieStore: Send + Sync {\n    /// Store a set of Set-Cookie header values received from `url`\n    fn set_cookies(&self, cookie_headers: &mut dyn Iterator<Item = &HeaderValue>, url: &url::Url);\n    /// Get any Cookie values in the store for `url`\n    fn cookies(&self, url: &url::Url) -> Option<HeaderValue>;\n}\n\n/// A single HTTP cookie.\npub struct Cookie<'a>(cookie_crate::Cookie<'a>);\n\n/// A good default `CookieStore` implementation.\n///\n/// This is the implementation used when simply calling `cookie_store(true)`.\n/// This type is exposed to allow creating one and filling it with some\n/// existing cookies more easily, before creating a `Client`.\n///\n/// For more advanced scenarios, such as needing to serialize the store or\n/// manipulate it between requests, you may refer to the\n/// [reqwest_cookie_store crate](https://crates.io/crates/reqwest_cookie_store).\n#[derive(Debug, Default)]\npub struct Jar(RwLock<cookie_store::CookieStore>);\n\n// ===== impl Cookie =====\n\nimpl<'a> Cookie<'a> {\n    fn parse(value: &'a HeaderValue) -> Result<Cookie<'a>, CookieParseError> {\n        std::str::from_utf8(value.as_bytes())\n            .map_err(cookie_crate::ParseError::from)\n            .and_then(cookie_crate::Cookie::parse)\n            .map_err(CookieParseError)\n            .map(Cookie)\n    }\n\n    /// The name of the cookie.\n    pub fn name(&self) -> &str {\n        self.0.name()\n    }\n\n    /// The value of the cookie.\n    pub fn value(&self) -> &str {\n        self.0.value()\n    }\n\n    /// Returns true if the 'HttpOnly' directive is enabled.\n    pub fn http_only(&self) -> bool {\n        self.0.http_only().unwrap_or(false)\n    }\n\n    /// Returns true if the 'Secure' directive is enabled.\n    pub fn secure(&self) -> bool {\n        self.0.secure().unwrap_or(false)\n    }\n\n    /// Returns true if  'SameSite' directive is 'Lax'.\n    pub fn same_site_lax(&self) -> bool {\n        self.0.same_site() == Some(cookie_crate::SameSite::Lax)\n    }\n\n    /// Returns true if  'SameSite' directive is 'Strict'.\n    pub fn same_site_strict(&self) -> bool {\n        self.0.same_site() == Some(cookie_crate::SameSite::Strict)\n    }\n\n    /// Returns the path directive of the cookie, if set.\n    pub fn path(&self) -> Option<&str> {\n        self.0.path()\n    }\n\n    /// Returns the domain directive of the cookie, if set.\n    pub fn domain(&self) -> Option<&str> {\n        self.0.domain()\n    }\n\n    /// Get the Max-Age information.\n    pub fn max_age(&self) -> Option<std::time::Duration> {\n        self.0.max_age().map(|d| {\n            d.try_into()\n                .expect(\"time::Duration into std::time::Duration\")\n        })\n    }\n\n    /// The cookie expiration time.\n    pub fn expires(&self) -> Option<SystemTime> {\n        match self.0.expires() {\n            Some(cookie_crate::Expiration::DateTime(offset)) => Some(SystemTime::from(offset)),\n            None | Some(cookie_crate::Expiration::Session) => None,\n        }\n    }\n}\n\nimpl<'a> fmt::Debug for Cookie<'a> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\npub(crate) fn extract_response_cookie_headers<'a>(\n    headers: &'a hyper::HeaderMap,\n) -> impl Iterator<Item = &'a HeaderValue> + 'a {\n    headers.get_all(SET_COOKIE).iter()\n}\n\npub(crate) fn extract_response_cookies<'a>(\n    headers: &'a hyper::HeaderMap,\n) -> impl Iterator<Item = Result<Cookie<'a>, CookieParseError>> + 'a {\n    headers\n        .get_all(SET_COOKIE)\n        .iter()\n        .map(|value| Cookie::parse(value))\n}\n\n/// Error representing a parse failure of a 'Set-Cookie' header.\npub(crate) struct CookieParseError(cookie_crate::ParseError);\n\nimpl<'a> fmt::Debug for CookieParseError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl<'a> fmt::Display for CookieParseError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl std::error::Error for CookieParseError {}\n\n// ===== impl Jar =====\n\nimpl Jar {\n    /// Add a cookie to this jar.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use reqwest::{cookie::Jar, Url};\n    ///\n    /// let cookie = \"foo=bar; Domain=yolo.local\";\n    /// let url = \"https://yolo.local\".parse::<Url>().unwrap();\n    ///\n    /// let jar = Jar::default();\n    /// jar.add_cookie_str(cookie, &url);\n    ///\n    /// // and now add to a `ClientBuilder`?\n    /// ```\n    pub fn add_cookie_str(&self, cookie: &str, url: &url::Url) {\n        let cookies = cookie_crate::Cookie::parse(cookie)\n            .ok()\n            .map(|c| c.into_owned())\n            .into_iter();\n        self.0.write().unwrap().store_response_cookies(cookies, url);\n    }\n}\n\nimpl CookieStore for Jar {\n    fn set_cookies(&self, cookie_headers: &mut dyn Iterator<Item = &HeaderValue>, url: &url::Url) {\n        let iter =\n            cookie_headers.filter_map(|val| Cookie::parse(val).map(|c| c.0.into_owned()).ok());\n\n        self.0.write().unwrap().store_response_cookies(iter, url);\n    }\n\n    fn cookies(&self, url: &url::Url) -> Option<HeaderValue> {\n        let s = self\n            .0\n            .read()\n            .unwrap()\n            .get_request_values(url)\n            .map(|(name, value)| format!(\"{name}={value}\"))\n            .collect::<Vec<_>>()\n            .join(\"; \");\n\n        if s.is_empty() {\n            return None;\n        }\n\n        HeaderValue::from_maybe_shared(Bytes::from(s)).ok()\n    }\n}\n\npub(crate) mod service {\n    use crate::cookie;\n    use http::{Request, Response};\n    use http_body::Body;\n    use pin_project_lite::pin_project;\n    use std::future::Future;\n    use std::pin::Pin;\n    use std::sync::Arc;\n    use std::task::ready;\n    use std::task::Context;\n    use std::task::Poll;\n    use tower::Service;\n    use url::Url;\n\n    /// A [`Service`] that adds cookie support to a lower-level [`Service`].\n    #[derive(Clone)]\n    pub struct CookieService<S> {\n        inner: S,\n        cookie_store: Option<Arc<dyn cookie::CookieStore>>,\n    }\n\n    impl<S> CookieService<S> {\n        /// Create a new [`CookieService`].\n        pub fn new(inner: S, cookie_store: Option<Arc<dyn cookie::CookieStore>>) -> Self {\n            Self {\n                inner,\n                cookie_store,\n            }\n        }\n    }\n\n    impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for CookieService<S>\n    where\n        S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone,\n        ReqBody: Body + Default,\n    {\n        type Response = Response<ResBody>;\n        type Error = S::Error;\n        type Future = ResponseFuture<S, ReqBody>;\n\n        #[inline]\n        fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n            self.inner.poll_ready(cx)\n        }\n\n        fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {\n            let clone = self.inner.clone();\n            let mut inner = std::mem::replace(&mut self.inner, clone);\n            let url = Url::parse(req.uri().to_string().as_str()).expect(\"invalid URL\");\n            if let Some(cookie_store) = self.cookie_store.as_ref() {\n                if req.headers().get(crate::header::COOKIE).is_none() {\n                    let headers = req.headers_mut();\n                    crate::util::add_cookie_header(headers, &**cookie_store, &url);\n                }\n            }\n\n            let cookie_store = self.cookie_store.clone();\n            ResponseFuture {\n                future: inner.call(req),\n                cookie_store,\n                url,\n            }\n        }\n    }\n\n    pin_project! {\n        #[allow(missing_debug_implementations)]\n        #[derive(Clone)]\n        /// A [`Future`] that adds cookie support to a lower-level [`Future`].\n        pub struct ResponseFuture<S, B>\n        where\n            S: Service<Request<B>>,\n        {\n            #[pin]\n            future: S::Future,\n            cookie_store: Option<Arc<dyn cookie::CookieStore>>,\n            url: Url,\n        }\n    }\n\n    impl<S, ReqBody, ResBody> Future for ResponseFuture<S, ReqBody>\n    where\n        S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone,\n        ReqBody: Body + Default,\n    {\n        type Output = Result<Response<ResBody>, S::Error>;\n\n        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n            let cookie_store = self.cookie_store.clone();\n            let url = self.url.clone();\n            let res = ready!(self.project().future.as_mut().poll(cx)?);\n\n            if let Some(cookie_store) = cookie_store.as_ref() {\n                let mut cookies = cookie::extract_response_cookie_headers(res.headers()).peekable();\n                if cookies.peek().is_some() {\n                    cookie_store.set_cookies(&mut cookies, &url);\n                }\n            }\n            Poll::Ready(Ok(res))\n        }\n    }\n}\n"
  },
  {
    "path": "src/dns/gai.rs",
    "content": "use hyper_util::client::legacy::connect::dns::GaiResolver as HyperGaiResolver;\nuse tower_service::Service;\n\nuse crate::dns::{Addrs, Name, Resolve, Resolving};\nuse crate::error::BoxError;\n\n#[derive(Debug)]\npub struct GaiResolver(HyperGaiResolver);\n\nimpl GaiResolver {\n    pub fn new() -> Self {\n        Self(HyperGaiResolver::new())\n    }\n}\n\nimpl Default for GaiResolver {\n    fn default() -> Self {\n        GaiResolver::new()\n    }\n}\n\nimpl Resolve for GaiResolver {\n    fn resolve(&self, name: Name) -> Resolving {\n        let mut this = self.0.clone();\n        Box::pin(async move {\n            this.call(name.0)\n                .await\n                .map(|addrs| Box::new(addrs) as Addrs)\n                .map_err(|err| Box::new(err) as BoxError)\n        })\n    }\n}\n"
  },
  {
    "path": "src/dns/hickory.rs",
    "content": "//! DNS resolution via the [hickory-resolver](https://github.com/hickory-dns/hickory-dns) crate\n\nuse hickory_resolver::{\n    config::{LookupIpStrategy, ResolverConfig},\n    lookup_ip::LookupIpIntoIter,\n    name_server::TokioConnectionProvider,\n    TokioResolver,\n};\nuse once_cell::sync::OnceCell;\n\nuse std::net::SocketAddr;\nuse std::sync::Arc;\n\nuse super::{Addrs, Name, Resolve, Resolving};\n\n/// Wrapper around an `AsyncResolver`, which implements the `Resolve` trait.\n#[derive(Debug, Default, Clone)]\npub(crate) struct HickoryDnsResolver {\n    /// Since we might not have been called in the context of a\n    /// Tokio Runtime in initialization, so we must delay the actual\n    /// construction of the resolver.\n    state: Arc<OnceCell<TokioResolver>>,\n}\n\nstruct SocketAddrs {\n    iter: LookupIpIntoIter,\n}\n\nimpl Resolve for HickoryDnsResolver {\n    fn resolve(&self, name: Name) -> Resolving {\n        let resolver = self.clone();\n        Box::pin(async move {\n            let resolver = resolver.state.get_or_init(new_resolver);\n\n            let lookup = resolver.lookup_ip(name.as_str()).await?;\n            let addrs: Addrs = Box::new(SocketAddrs {\n                iter: lookup.into_iter(),\n            });\n            Ok(addrs)\n        })\n    }\n}\n\nimpl Iterator for SocketAddrs {\n    type Item = SocketAddr;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0))\n    }\n}\n\n/// Create a new resolver with the default configuration,\n/// which reads from `/etc/resolve.conf`. If reading `/etc/resolv.conf` fails,\n/// it fallbacks to hickory_resolver's default config.\n/// The options are overridden to look up for both IPv4 and IPv6 addresses\n/// to work with \"happy eyeballs\" algorithm.\nfn new_resolver() -> TokioResolver {\n    let mut builder = TokioResolver::builder_tokio().unwrap_or_else(|err| {\n        log::debug!(\n            \"hickory-dns: failed to load system DNS configuration; falling back to hickory_resolver defaults: {:?}\",\n            err\n        );\n        TokioResolver::builder_with_config(\n            ResolverConfig::default(),\n            TokioConnectionProvider::default(),\n        )\n    });\n    builder.options_mut().ip_strategy = LookupIpStrategy::Ipv4AndIpv6;\n    builder.build()\n}\n"
  },
  {
    "path": "src/dns/mod.rs",
    "content": "//! DNS resolution\n\npub use resolve::{Addrs, Name, Resolve, Resolving};\npub(crate) use resolve::{DnsResolverWithOverrides, DynResolver};\n\n#[cfg(docsrs)]\npub use resolve::IntoResolve;\n\npub(crate) mod gai;\n#[cfg(feature = \"hickory-dns\")]\npub(crate) mod hickory;\npub(crate) mod resolve;\n"
  },
  {
    "path": "src/dns/resolve.rs",
    "content": "use hyper_util::client::legacy::connect::dns::Name as HyperName;\nuse tower_service::Service;\n\nuse std::collections::HashMap;\nuse std::future::Future;\nuse std::net::SocketAddr;\nuse std::pin::Pin;\nuse std::str::FromStr;\nuse std::sync::Arc;\nuse std::task::{Context, Poll};\n\nuse crate::error::BoxError;\n\n/// Alias for an `Iterator` trait object over `SocketAddr`.\npub type Addrs = Box<dyn Iterator<Item = SocketAddr> + Send>;\n\n/// Alias for the `Future` type returned by a DNS resolver.\npub type Resolving = Pin<Box<dyn Future<Output = Result<Addrs, BoxError>> + Send>>;\n\n/// Trait for customizing DNS resolution in reqwest.\npub trait Resolve: Send + Sync {\n    /// Performs DNS resolution on a `Name`.\n    /// The return type is a future containing an iterator of `SocketAddr`.\n    ///\n    /// It differs from `tower_service::Service<Name>` in several ways:\n    ///  * It is assumed that `resolve` will always be ready to poll.\n    ///  * It does not need a mutable reference to `self`.\n    ///  * Since trait objects cannot make use of associated types, it requires\n    ///    wrapping the returned `Future` and its contained `Iterator` with `Box`.\n    ///\n    /// Explicitly specified port in the URL will override any port in the resolved `SocketAddr`s.\n    /// Otherwise, port `0` will be replaced by the conventional port for the given scheme (e.g. 80 for http).\n    fn resolve(&self, name: Name) -> Resolving;\n}\n\n/// A name that must be resolved to addresses.\n#[derive(Debug)]\npub struct Name(pub(super) HyperName);\n\n/// A more general trait implemented for types implementing `Resolve`.\n///\n/// Unnameable, only exported to aid seeing what implements this.\npub trait IntoResolve {\n    #[doc(hidden)]\n    fn into_resolve(self) -> Arc<dyn Resolve>;\n}\n\nimpl Name {\n    /// View the name as a string.\n    pub fn as_str(&self) -> &str {\n        self.0.as_str()\n    }\n}\n\nimpl FromStr for Name {\n    type Err = sealed::InvalidNameError;\n\n    fn from_str(host: &str) -> Result<Self, Self::Err> {\n        HyperName::from_str(host)\n            .map(Name)\n            .map_err(|_| sealed::InvalidNameError { _ext: () })\n    }\n}\n\n#[derive(Clone)]\npub(crate) struct DynResolver {\n    resolver: Arc<dyn Resolve>,\n}\n\nimpl DynResolver {\n    pub(crate) fn new(resolver: Arc<dyn Resolve>) -> Self {\n        Self { resolver }\n    }\n\n    #[cfg(feature = \"socks\")]\n    pub(crate) fn gai() -> Self {\n        Self::new(Arc::new(super::gai::GaiResolver::new()))\n    }\n\n    /// Resolve an HTTP host and port, not just a domain name.\n    ///\n    /// This does the same thing that hyper-util's HttpConnector does, before\n    /// calling out to its underlying DNS resolver.\n    #[cfg(feature = \"socks\")]\n    pub(crate) async fn http_resolve(\n        &self,\n        target: &http::Uri,\n    ) -> Result<impl Iterator<Item = std::net::SocketAddr>, BoxError> {\n        let host = target.host().ok_or(\"missing host\")?;\n        let port = target\n            .port_u16()\n            .unwrap_or_else(|| match target.scheme_str() {\n                Some(\"https\") => 443,\n                Some(\"socks4\") | Some(\"socks4a\") | Some(\"socks5\") | Some(\"socks5h\") => 1080,\n                _ => 80,\n            });\n\n        let explicit_port = target.port().is_some();\n\n        let addrs = self.resolver.resolve(host.parse()?).await?;\n\n        Ok(addrs.map(move |mut addr| {\n            if explicit_port || addr.port() == 0 {\n                addr.set_port(port);\n            }\n            addr\n        }))\n    }\n}\n\nimpl Service<HyperName> for DynResolver {\n    type Response = Addrs;\n    type Error = BoxError;\n    type Future = Resolving;\n\n    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, name: HyperName) -> Self::Future {\n        self.resolver.resolve(Name(name))\n    }\n}\n\npub(crate) struct DnsResolverWithOverrides {\n    dns_resolver: Arc<dyn Resolve>,\n    overrides: Arc<HashMap<String, Vec<SocketAddr>>>,\n}\n\nimpl DnsResolverWithOverrides {\n    pub(crate) fn new(\n        dns_resolver: Arc<dyn Resolve>,\n        overrides: HashMap<String, Vec<SocketAddr>>,\n    ) -> Self {\n        DnsResolverWithOverrides {\n            dns_resolver,\n            overrides: Arc::new(overrides),\n        }\n    }\n}\n\nimpl Resolve for DnsResolverWithOverrides {\n    fn resolve(&self, name: Name) -> Resolving {\n        match self.overrides.get(name.as_str()) {\n            Some(dest) => {\n                let addrs: Addrs = Box::new(dest.clone().into_iter());\n                Box::pin(std::future::ready(Ok(addrs)))\n            }\n            None => self.dns_resolver.resolve(name),\n        }\n    }\n}\n\nimpl IntoResolve for Arc<dyn Resolve> {\n    fn into_resolve(self) -> Arc<dyn Resolve> {\n        self\n    }\n}\n\nimpl<R> IntoResolve for Arc<R>\nwhere\n    R: Resolve + 'static,\n{\n    fn into_resolve(self) -> Arc<dyn Resolve> {\n        self\n    }\n}\n\nimpl<R> IntoResolve for R\nwhere\n    R: Resolve + 'static,\n{\n    fn into_resolve(self) -> Arc<dyn Resolve> {\n        Arc::new(self)\n    }\n}\n\nmod sealed {\n    use std::fmt;\n\n    #[derive(Debug)]\n    pub struct InvalidNameError {\n        pub(super) _ext: (),\n    }\n\n    impl fmt::Display for InvalidNameError {\n        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n            f.write_str(\"invalid DNS name\")\n        }\n    }\n\n    impl std::error::Error for InvalidNameError {}\n}\n"
  },
  {
    "path": "src/error.rs",
    "content": "#![cfg_attr(target_arch = \"wasm32\", allow(unused))]\nuse std::error::Error as StdError;\nuse std::fmt;\nuse std::io;\n\nuse crate::util::Escape;\nuse crate::{StatusCode, Url};\n\n/// A `Result` alias where the `Err` case is `reqwest::Error`.\npub type Result<T> = std::result::Result<T, Error>;\n\n/// The Errors that may occur when processing a `Request`.\n///\n/// Note: Errors may include the full URL used to make the `Request`. If the URL\n/// contains sensitive information (e.g. an API key as a query parameter), be\n/// sure to remove it ([`without_url`](Error::without_url))\npub struct Error {\n    inner: Box<Inner>,\n}\n\npub(crate) type BoxError = Box<dyn StdError + Send + Sync>;\n\nstruct Inner {\n    kind: Kind,\n    source: Option<BoxError>,\n    url: Option<Url>,\n}\n\nimpl Error {\n    pub(crate) fn new<E>(kind: Kind, source: Option<E>) -> Error\n    where\n        E: Into<BoxError>,\n    {\n        Error {\n            inner: Box::new(Inner {\n                kind,\n                source: source.map(Into::into),\n                url: None,\n            }),\n        }\n    }\n\n    /// Returns a possible URL related to this error.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # async fn run() {\n    /// // displays last stop of a redirect loop\n    /// let response = reqwest::get(\"http://site.with.redirect.loop\").await;\n    /// if let Err(e) = response {\n    ///     if e.is_redirect() {\n    ///         if let Some(final_stop) = e.url() {\n    ///             println!(\"redirect loop at {final_stop}\");\n    ///         }\n    ///     }\n    /// }\n    /// # }\n    /// ```\n    pub fn url(&self) -> Option<&Url> {\n        self.inner.url.as_ref()\n    }\n\n    /// Returns a mutable reference to the URL related to this error\n    ///\n    /// This is useful if you need to remove sensitive information from the URL\n    /// (e.g. an API key in the query), but do not want to remove the URL\n    /// entirely.\n    pub fn url_mut(&mut self) -> Option<&mut Url> {\n        self.inner.url.as_mut()\n    }\n\n    /// Add a url related to this error (overwriting any existing)\n    pub fn with_url(mut self, url: Url) -> Self {\n        self.inner.url = Some(url);\n        self\n    }\n\n    pub(crate) fn if_no_url(mut self, f: impl FnOnce() -> Url) -> Self {\n        if self.inner.url.is_none() {\n            self.inner.url = Some(f());\n        }\n        self\n    }\n\n    /// Strip the related url from this error (if, for example, it contains\n    /// sensitive information)\n    pub fn without_url(mut self) -> Self {\n        self.inner.url = None;\n        self\n    }\n\n    /// Returns true if the error is from a type Builder.\n    pub fn is_builder(&self) -> bool {\n        matches!(self.inner.kind, Kind::Builder)\n    }\n\n    /// Returns true if the error is from a `RedirectPolicy`.\n    pub fn is_redirect(&self) -> bool {\n        matches!(self.inner.kind, Kind::Redirect)\n    }\n\n    /// Returns true if the error is from `Response::error_for_status`.\n    pub fn is_status(&self) -> bool {\n        #[cfg(not(target_arch = \"wasm32\"))]\n        {\n            matches!(self.inner.kind, Kind::Status(_, _))\n        }\n        #[cfg(target_arch = \"wasm32\")]\n        {\n            matches!(self.inner.kind, Kind::Status(_))\n        }\n    }\n\n    /// Returns true if the error is related to a timeout.\n    pub fn is_timeout(&self) -> bool {\n        let mut source = self.source();\n\n        while let Some(err) = source {\n            if err.is::<TimedOut>() {\n                return true;\n            }\n            #[cfg(not(target_arch = \"wasm32\"))]\n            if let Some(hyper_err) = err.downcast_ref::<hyper::Error>() {\n                if hyper_err.is_timeout() {\n                    return true;\n                }\n            }\n            if let Some(io) = err.downcast_ref::<io::Error>() {\n                if io.kind() == io::ErrorKind::TimedOut {\n                    return true;\n                }\n            }\n            source = err.source();\n        }\n\n        false\n    }\n\n    /// Returns true if the error is related to the request\n    pub fn is_request(&self) -> bool {\n        matches!(self.inner.kind, Kind::Request)\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    /// Returns true if the error is related to connect\n    pub fn is_connect(&self) -> bool {\n        let mut source = self.source();\n\n        while let Some(err) = source {\n            if let Some(hyper_err) = err.downcast_ref::<hyper_util::client::legacy::Error>() {\n                if hyper_err.is_connect() {\n                    return true;\n                }\n            }\n\n            source = err.source();\n        }\n\n        false\n    }\n\n    /// Returns true if the error is related to the request or response body\n    pub fn is_body(&self) -> bool {\n        matches!(self.inner.kind, Kind::Body)\n    }\n\n    /// Returns true if the error is related to decoding the response's body\n    pub fn is_decode(&self) -> bool {\n        matches!(self.inner.kind, Kind::Decode)\n    }\n\n    /// Returns the status code, if the error was generated from a response.\n    pub fn status(&self) -> Option<StatusCode> {\n        match self.inner.kind {\n            #[cfg(target_arch = \"wasm32\")]\n            Kind::Status(code) => Some(code),\n            #[cfg(not(target_arch = \"wasm32\"))]\n            Kind::Status(code, _) => Some(code),\n            _ => None,\n        }\n    }\n\n    /// Returns true if the error is related to a protocol upgrade request\n    pub fn is_upgrade(&self) -> bool {\n        matches!(self.inner.kind, Kind::Upgrade)\n    }\n\n    // private\n\n    #[allow(unused)]\n    pub(crate) fn into_io(self) -> io::Error {\n        io::Error::new(io::ErrorKind::Other, self)\n    }\n}\n\n/// Converts from external types to reqwest's\n/// internal equivalents.\n///\n/// Currently only is used for `tower::timeout::error::Elapsed`.\n#[cfg(not(target_arch = \"wasm32\"))]\npub(crate) fn cast_to_internal_error(error: BoxError) -> BoxError {\n    if error.is::<tower::timeout::error::Elapsed>() {\n        Box::new(crate::error::TimedOut) as BoxError\n    } else {\n        error\n    }\n}\n\nimpl fmt::Debug for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"reqwest::Error\");\n\n        builder.field(\"kind\", &self.inner.kind);\n\n        if let Some(ref url) = self.inner.url {\n            builder.field(\"url\", &url.as_str());\n        }\n        if let Some(ref source) = self.inner.source {\n            builder.field(\"source\", source);\n        }\n\n        builder.finish()\n    }\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self.inner.kind {\n            Kind::Builder => f.write_str(\"builder error\")?,\n            Kind::Request => f.write_str(\"error sending request\")?,\n            Kind::Body => f.write_str(\"request or response body error\")?,\n            Kind::Decode => f.write_str(\"error decoding response body\")?,\n            Kind::Redirect => f.write_str(\"error following redirect\")?,\n            Kind::Upgrade => f.write_str(\"error upgrading connection\")?,\n            #[cfg(target_arch = \"wasm32\")]\n            Kind::Status(ref code) => {\n                let prefix = if code.is_client_error() {\n                    \"HTTP status client error\"\n                } else {\n                    debug_assert!(code.is_server_error());\n                    \"HTTP status server error\"\n                };\n                write!(f, \"{prefix} ({code})\")?;\n            }\n            #[cfg(not(target_arch = \"wasm32\"))]\n            Kind::Status(ref code, ref reason) => {\n                let prefix = if code.is_client_error() {\n                    \"HTTP status client error\"\n                } else {\n                    debug_assert!(code.is_server_error());\n                    \"HTTP status server error\"\n                };\n                if let Some(reason) = reason {\n                    write!(\n                        f,\n                        \"{prefix} ({} {})\",\n                        code.as_str(),\n                        Escape::new(reason.as_bytes())\n                    )?;\n                } else {\n                    write!(f, \"{prefix} ({code})\")?;\n                }\n            }\n        };\n\n        if let Some(url) = &self.inner.url {\n            write!(f, \" for url ({url})\")?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl StdError for Error {\n    fn source(&self) -> Option<&(dyn StdError + 'static)> {\n        self.inner.source.as_ref().map(|e| &**e as _)\n    }\n}\n\n#[cfg(target_arch = \"wasm32\")]\nimpl From<crate::error::Error> for wasm_bindgen::JsValue {\n    fn from(err: Error) -> wasm_bindgen::JsValue {\n        js_sys::Error::from(err).into()\n    }\n}\n\n#[cfg(target_arch = \"wasm32\")]\nimpl From<crate::error::Error> for js_sys::Error {\n    fn from(err: Error) -> js_sys::Error {\n        js_sys::Error::new(&format!(\"{err}\"))\n    }\n}\n\n#[derive(Debug)]\npub(crate) enum Kind {\n    Builder,\n    Request,\n    Redirect,\n    #[cfg(not(target_arch = \"wasm32\"))]\n    Status(StatusCode, Option<hyper::ext::ReasonPhrase>),\n    #[cfg(target_arch = \"wasm32\")]\n    Status(StatusCode),\n    Body,\n    Decode,\n    Upgrade,\n}\n\n// constructors\n\npub(crate) fn builder<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Builder, Some(e))\n}\n\npub(crate) fn body<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Body, Some(e))\n}\n\npub(crate) fn decode<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Decode, Some(e))\n}\n\npub(crate) fn request<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Request, Some(e))\n}\n\npub(crate) fn redirect<E: Into<BoxError>>(e: E, url: Url) -> Error {\n    Error::new(Kind::Redirect, Some(e)).with_url(url)\n}\n\npub(crate) fn status_code(\n    url: Url,\n    status: StatusCode,\n    #[cfg(not(target_arch = \"wasm32\"))] reason: Option<hyper::ext::ReasonPhrase>,\n) -> Error {\n    Error::new(\n        Kind::Status(\n            status,\n            #[cfg(not(target_arch = \"wasm32\"))]\n            reason,\n        ),\n        None::<Error>,\n    )\n    .with_url(url)\n}\n\npub(crate) fn url_bad_scheme(url: Url) -> Error {\n    Error::new(Kind::Builder, Some(BadScheme)).with_url(url)\n}\n\npub(crate) fn url_invalid_uri(url: Url) -> Error {\n    Error::new(Kind::Builder, Some(\"Parsed Url is not a valid Uri\")).with_url(url)\n}\n\nif_wasm! {\n    pub(crate) fn wasm(js_val: wasm_bindgen::JsValue) -> BoxError {\n        format!(\"{js_val:?}\").into()\n    }\n}\n\npub(crate) fn upgrade<E: Into<BoxError>>(e: E) -> Error {\n    Error::new(Kind::Upgrade, Some(e))\n}\n\n// io::Error helpers\n\n#[allow(unused)]\npub(crate) fn decode_io(e: io::Error) -> Error {\n    if e.get_ref().map(|r| r.is::<Error>()).unwrap_or(false) {\n        *e.into_inner()\n            .expect(\"io::Error::get_ref was Some(_)\")\n            .downcast::<Error>()\n            .expect(\"StdError::is() was true\")\n    } else {\n        decode(e)\n    }\n}\n\n// internal Error \"sources\"\n\n#[derive(Debug)]\npub(crate) struct TimedOut;\n\nimpl fmt::Display for TimedOut {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.write_str(\"operation timed out\")\n    }\n}\n\nimpl StdError for TimedOut {}\n\n#[derive(Debug)]\npub(crate) struct BadScheme;\n\nimpl fmt::Display for BadScheme {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.write_str(\"URL scheme is not allowed\")\n    }\n}\n\nimpl StdError for BadScheme {}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn assert_send<T: Send>() {}\n    fn assert_sync<T: Sync>() {}\n\n    #[test]\n    fn test_source_chain() {\n        let root = Error::new(Kind::Request, None::<Error>);\n        assert!(root.source().is_none());\n\n        let link = super::body(root);\n        assert!(link.source().is_some());\n        assert_send::<Error>();\n        assert_sync::<Error>();\n    }\n\n    #[test]\n    fn mem_size_of() {\n        use std::mem::size_of;\n        assert_eq!(size_of::<Error>(), size_of::<usize>());\n    }\n\n    #[test]\n    fn roundtrip_io_error() {\n        let orig = super::request(\"orig\");\n        // Convert reqwest::Error into an io::Error...\n        let io = orig.into_io();\n        // Convert that io::Error back into a reqwest::Error...\n        let err = super::decode_io(io);\n        // It should have pulled out the original, not nested it...\n        match err.inner.kind {\n            Kind::Request => (),\n            _ => panic!(\"{err:?}\"),\n        }\n    }\n\n    #[test]\n    fn from_unknown_io_error() {\n        let orig = io::Error::new(io::ErrorKind::Other, \"orly\");\n        let err = super::decode_io(orig);\n        match err.inner.kind {\n            Kind::Decode => (),\n            _ => panic!(\"{err:?}\"),\n        }\n    }\n\n    #[test]\n    fn is_timeout() {\n        let err = super::request(super::TimedOut);\n        assert!(err.is_timeout());\n\n        // todo: test `hyper::Error::is_timeout` when we can easily construct one\n\n        let io = io::Error::from(io::ErrorKind::TimedOut);\n        let nested = super::request(io);\n        assert!(nested.is_timeout());\n    }\n}\n"
  },
  {
    "path": "src/into_url.rs",
    "content": "use url::Url;\n\n/// A trait to try to convert some type into a `Url`.\n///\n/// This trait is \"sealed\", such that only types within reqwest can\n/// implement it.\npub trait IntoUrl: IntoUrlSealed {}\n\nimpl IntoUrl for Url {}\nimpl IntoUrl for String {}\nimpl<'a> IntoUrl for &'a str {}\nimpl<'a> IntoUrl for &'a String {}\n\npub trait IntoUrlSealed {\n    // Besides parsing as a valid `Url`, the `Url` must be a valid\n    // `http::Uri`, in that it makes sense to use in a network request.\n    fn into_url(self) -> crate::Result<Url>;\n\n    fn as_str(&self) -> &str;\n}\n\nimpl IntoUrlSealed for Url {\n    fn into_url(self) -> crate::Result<Url> {\n        // With blob url the `self.has_host()` check is always false, so we\n        // remove the `blob:` scheme and check again if the url is valid.\n        #[cfg(target_arch = \"wasm32\")]\n        if self.scheme() == \"blob\"\n            && self.path().starts_with(\"http\") // Check if the path starts with http or https to avoid validating a `blob:blob:...` url.\n            && self.as_str()[5..].into_url().is_ok()\n        {\n            return Ok(self);\n        }\n\n        if self.has_host() {\n            Ok(self)\n        } else {\n            Err(crate::error::url_bad_scheme(self))\n        }\n    }\n\n    fn as_str(&self) -> &str {\n        self.as_ref()\n    }\n}\n\nimpl<'a> IntoUrlSealed for &'a str {\n    fn into_url(self) -> crate::Result<Url> {\n        Url::parse(self).map_err(crate::error::builder)?.into_url()\n    }\n\n    fn as_str(&self) -> &str {\n        self\n    }\n}\n\nimpl<'a> IntoUrlSealed for &'a String {\n    fn into_url(self) -> crate::Result<Url> {\n        (&**self).into_url()\n    }\n\n    fn as_str(&self) -> &str {\n        self.as_ref()\n    }\n}\n\nimpl IntoUrlSealed for String {\n    fn into_url(self) -> crate::Result<Url> {\n        (&*self).into_url()\n    }\n\n    fn as_str(&self) -> &str {\n        self.as_ref()\n    }\n}\n\nif_hyper! {\n    pub(crate) fn try_uri(url: &Url) -> crate::Result<http::Uri> {\n        url.as_str()\n            .parse()\n            .map_err(|_| crate::error::url_invalid_uri(url.clone()))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use std::error::Error;\n\n    #[test]\n    fn into_url_file_scheme() {\n        let err = \"file:///etc/hosts\".into_url().unwrap_err();\n        assert_eq!(\n            err.source().unwrap().to_string(),\n            \"URL scheme is not allowed\"\n        );\n    }\n\n    #[test]\n    fn into_url_blob_scheme() {\n        let err = \"blob:https://example.com\".into_url().unwrap_err();\n        assert_eq!(\n            err.source().unwrap().to_string(),\n            \"URL scheme is not allowed\"\n        );\n    }\n\n    if_wasm! {\n        use wasm_bindgen_test::*;\n\n        #[wasm_bindgen_test]\n        fn into_url_blob_scheme_wasm() {\n            let url = \"blob:http://example.com\".into_url().unwrap();\n\n            assert_eq!(url.as_str(), \"blob:http://example.com\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "#![deny(missing_docs)]\n#![deny(missing_debug_implementations)]\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![cfg_attr(not(test), warn(unused_crate_dependencies))]\n#![cfg_attr(test, deny(warnings))]\n\n//! # reqwest\n//!\n//! The `reqwest` crate provides a convenient, higher-level HTTP\n//! [`Client`][client].\n//!\n//! It handles many of the things that most people just expect an HTTP client\n//! to do for them.\n//!\n//! - Async and [blocking] Clients\n//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart]\n//! - Customizable [redirect policy](#redirect-policies)\n//! - HTTP [Proxies](#proxies)\n//! - Uses [TLS](#tls) by default\n//! - Cookies\n//!\n//! The [`reqwest::Client`][client] is asynchronous (requiring Tokio). For\n//! applications wishing  to only make a few HTTP requests, the\n//! [`reqwest::blocking`](blocking) API may be more convenient.\n//!\n//! Additional learning resources include:\n//!\n//! - [The Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/web/clients.html)\n//! - [reqwest Repository Examples](https://github.com/seanmonstar/reqwest/tree/master/examples)\n//!\n//! ## Commercial Support\n//!\n//! For private advice, support, reviews, access to the maintainer, and the\n//! like, reach out for [commercial support][sponsor].\n//!\n//! ## Making a GET request\n//!\n//! For a single request, you can use the [`get`][get] shortcut method.\n//!\n//! ```rust\n//! # async fn run() -> Result<(), reqwest::Error> {\n//! let body = reqwest::get(\"https://www.rust-lang.org\")\n//!     .await?\n//!     .text()\n//!     .await?;\n//!\n//! println!(\"body = {body:?}\");\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! **NOTE**: If you plan to perform multiple requests, it is best to create a\n//! [`Client`][client] and reuse it, taking advantage of keep-alive connection\n//! pooling.\n//!\n//! ## Making POST requests (or setting request bodies)\n//!\n//! There are several ways you can set the body of a request. The basic one is\n//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the\n//! exact raw bytes of what the body should be. It accepts various types,\n//! including `String` and `Vec<u8>`. If you wish to pass a custom\n//! type, you can use the `reqwest::Body` constructors.\n//!\n//! ```rust\n//! # use reqwest::Error;\n//! #\n//! # async fn run() -> Result<(), Error> {\n//! let client = reqwest::Client::new();\n//! let res = client.post(\"http://httpbin.org/post\")\n//!     .body(\"the exact body that is sent\")\n//!     .send()\n//!     .await?;\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! ### Forms\n//!\n//! It's very common to want to send form data in a request body. This can be\n//! done with any type that can be serialized into form data.\n//!\n//! This can be an array of tuples, or a `HashMap`, or a custom type that\n//! implements [`Serialize`][serde].\n//!\n//! The feature `form` is required.\n//!\n//! ```rust\n//! # use reqwest::Error;\n//! #\n//! # #[cfg(feature = \"form\")]\n//! # async fn run() -> Result<(), Error> {\n//! // This will POST a body of `foo=bar&baz=quux`\n//! let params = [(\"foo\", \"bar\"), (\"baz\", \"quux\")];\n//! let client = reqwest::Client::new();\n//! let res = client.post(\"http://httpbin.org/post\")\n//!     .form(&params)\n//!     .send()\n//!     .await?;\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! ### JSON\n//!\n//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in\n//! a similar fashion the `form` method. It can take any value that can be\n//! serialized into JSON.\n//!\n//! The feature `json` is required.\n//!\n//! ```rust\n//! # use reqwest::Error;\n//! # use std::collections::HashMap;\n//! #\n//! # #[cfg(feature = \"json\")]\n//! # async fn run() -> Result<(), Error> {\n//! // This will POST a body of `{\"lang\":\"rust\",\"body\":\"json\"}`\n//! let mut map = HashMap::new();\n//! map.insert(\"lang\", \"rust\");\n//! map.insert(\"body\", \"json\");\n//!\n//! let client = reqwest::Client::new();\n//! let res = client.post(\"http://httpbin.org/post\")\n//!     .json(&map)\n//!     .send()\n//!     .await?;\n//! # Ok(())\n//! # }\n//! ```\n//!\n//! ## Redirect Policies\n//!\n//! By default, a `Client` will automatically handle HTTP redirects, having a\n//! maximum redirect chain of 10 hops. To customize this behavior, a\n//! [`redirect::Policy`][redirect] can be used with a `ClientBuilder`.\n//!\n//! ## Cookies\n//!\n//! The automatic storing and sending of session cookies can be enabled with\n//! the [`cookie_store`][ClientBuilder::cookie_store] method on `ClientBuilder`.\n//!\n//! ## Proxies\n//!\n//! **NOTE**: System proxies are enabled by default.\n//!\n//! System proxies look in environment variables to set HTTP or HTTPS proxies.\n//!\n//! `HTTP_PROXY` or `http_proxy` provide HTTP proxies for HTTP connections while\n//! `HTTPS_PROXY` or `https_proxy` provide HTTPS proxies for HTTPS connections.\n//! `ALL_PROXY` or `all_proxy` provide proxies for both HTTP and HTTPS connections.\n//! If both the all proxy and HTTP or HTTPS proxy variables are set the more specific\n//! HTTP or HTTPS proxies take precedence.\n//!\n//! These can be overwritten by adding a [`Proxy`] to `ClientBuilder`\n//! i.e. `let proxy = reqwest::Proxy::http(\"https://secure.example\")?;`\n//! or disabled by calling `ClientBuilder::no_proxy()`.\n//!\n//! `socks` feature is required if you have configured socks proxy like this:\n//!\n//! ```bash\n//! export https_proxy=socks5://127.0.0.1:1086\n//! ```\n//!\n//! ## TLS\n//!\n//! A `Client` will use transport layer security (TLS) by default to connect to\n//! HTTPS destinations.\n//!\n//! - Additional server certificates can be configured on a `ClientBuilder`\n//!   with the [`Certificate`] type.\n//! - Client certificates can be added to a `ClientBuilder` with the\n//!   [`Identity`] type.\n//! - Various parts of TLS can also be configured or even disabled on the\n//!   `ClientBuilder`.\n//!\n//! See more details in the [`tls`] module.\n//!\n//! ## WASM\n//!\n//! The Client implementation automatically switches to the WASM one when the target_arch is wasm32,\n//! the usage is basically the same as the async api. Some of the features are disabled in wasm\n//! : [`tls`], [`cookie`], [`blocking`], as well as various `ClientBuilder` methods such as `timeout()` and `connector_layer()`.\n//!\n//! TLS and cookies are provided through the browser environment, so reqwest can issue TLS requests with cookies,\n//! but has limited configuration.\n//!\n//! ## Optional Features\n//!\n//! The following are a list of [Cargo features][cargo-features] that can be\n//! enabled or disabled:\n//!\n//! - **http2** *(enabled by default)*: Enables HTTP/2 support.\n//! - **default-tls** *(enabled by default)*: Provides TLS support to connect\n//!   over HTTPS.\n//! - **rustls**: Enables TLS functionality provided by `rustls`.\n//! - **rustls-no-provider**: Enables TLS provided by `rustls` without specifying a crypto provider.\n//! - **native-tls**: Enables TLS functionality provided by `native-tls`.\n//! - **native-tls-vendored**: Enables the `vendored` feature of `native-tls`.\n//! - **native-tls-no-alpn**: Enables `native-tls` without its `alpn` feature.\n//! - **native-tls-vendored-no-alpn**: Enables `native-tls-vendored` without its `alpn` feature.\n//! - **blocking**: Provides the [blocking][] client API.\n//! - **charset** *(enabled by default)*: Improved support for decoding text.\n//! - **cookies**: Provides cookie session support.\n//! - **gzip**: Provides response body gzip decompression.\n//! - **brotli**: Provides response body brotli decompression.\n//! - **zstd**: Provides response body zstd decompression.\n//! - **deflate**: Provides response body deflate decompression.\n//! - **query**: Provides query parameter serialization.\n//! - **form**: Provides form data serialization.\n//! - **json**: Provides serialization and deserialization for JSON bodies.\n//! - **multipart**: Provides functionality for multipart forms.\n//! - **stream**: Adds support for `futures::Stream`.\n//! - **socks**: Provides SOCKS5 proxy support.\n//! - **hickory-dns**: Enables a hickory-dns async resolver instead of default\n//!   threadpool using `getaddrinfo`.\n//! - **system-proxy** *(enabled by default)*: Use Windows and macOS system\n//!   proxy settings automatically.\n//!\n//! ## Unstable Features\n//!\n//! Some feature flags require additional opt-in by the application, by setting\n//! a `reqwest_unstable` flag.\n//!\n//! - **http3** *(unstable)*: Enables support for sending HTTP/3 requests.\n//!\n//! These features are unstable, and experimental. Details about them may be\n//! changed in patch releases.\n//!\n//! You can pass such a flag to the compiler via `.cargo/config`, or\n//! environment variables, such as:\n//!\n//! ```notrust\n//! RUSTFLAGS=\"--cfg reqwest_unstable\" cargo build\n//! ```\n//!\n//! ## Sponsors\n//!\n//! Support this project by becoming a [sponsor][].\n//!\n//! [hyper]: https://hyper.rs\n//! [blocking]: ./blocking/index.html\n//! [client]: ./struct.Client.html\n//! [response]: ./struct.Response.html\n//! [get]: ./fn.get.html\n//! [builder]: ./struct.RequestBuilder.html\n//! [serde]: http://serde.rs\n//! [redirect]: crate::redirect\n//! [Proxy]: ./struct.Proxy.html\n//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section\n//! [sponsor]: https://seanmonstar.com/sponsor\n\n#[cfg(all(feature = \"http3\", not(reqwest_unstable)))]\ncompile_error!(\n    \"\\\n    The `http3` feature is unstable, and requires the \\\n    `RUSTFLAGS='--cfg reqwest_unstable'` environment variable to be set.\\\n\"\n);\n\n// Ignore `unused_crate_dependencies` warnings.\n// Used in many features that they're not worth making it optional.\nuse futures_core as _;\nuse sync_wrapper as _;\n\nmacro_rules! if_wasm {\n    ($($item:item)*) => {$(\n        #[cfg(target_arch = \"wasm32\")]\n        $item\n    )*}\n}\n\nmacro_rules! if_hyper {\n    ($($item:item)*) => {$(\n        #[cfg(not(target_arch = \"wasm32\"))]\n        $item\n    )*}\n}\n\npub use http::header;\npub use http::Method;\npub use http::{StatusCode, Version};\npub use url::Url;\n\n// universal mods\n#[macro_use]\nmod error;\n// TODO: remove `if_hyper` if wasm has been migrated to new config system.\nif_hyper! {\n    mod config;\n}\nmod into_url;\nmod response;\n\npub use self::error::{Error, Result};\npub use self::into_url::IntoUrl;\npub use self::response::ResponseBuilderExt;\n\n/// Shortcut method to quickly make a `GET` request.\n///\n/// See also the methods on the [`reqwest::Response`](./struct.Response.html)\n/// type.\n///\n/// **NOTE**: This function creates a new internal `Client` on each call,\n/// and so should not be used if making many requests. Create a\n/// [`Client`](./struct.Client.html) instead.\n///\n/// # Examples\n///\n/// ```rust\n/// # async fn run() -> Result<(), reqwest::Error> {\n/// let body = reqwest::get(\"https://www.rust-lang.org\").await?\n///     .text().await?;\n/// # Ok(())\n/// # }\n/// ```\n///\n/// # Errors\n///\n/// This function fails if:\n///\n/// - native TLS backend cannot be initialized\n/// - supplied `Url` cannot be parsed\n/// - there was an error while sending request\n/// - redirect limit was exhausted\npub async fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {\n    Client::builder().build()?.get(url).send().await\n}\n\nfn _assert_impls() {\n    fn assert_send<T: Send>() {}\n    fn assert_sync<T: Sync>() {}\n    fn assert_clone<T: Clone>() {}\n\n    assert_send::<Client>();\n    assert_sync::<Client>();\n    assert_clone::<Client>();\n\n    assert_send::<Request>();\n    assert_send::<RequestBuilder>();\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    {\n        assert_send::<Response>();\n    }\n\n    assert_send::<Error>();\n    assert_sync::<Error>();\n\n    assert_send::<Body>();\n    assert_sync::<Body>();\n}\n\nif_hyper! {\n    #[cfg(test)]\n    #[macro_use]\n    extern crate doc_comment;\n\n    #[cfg(test)]\n    doctest!(\"../README.md\");\n\n    pub use self::async_impl::{\n        Body, Client, ClientBuilder, Request, RequestBuilder, Response, Upgraded,\n    };\n    pub use self::proxy::{Proxy,NoProxy};\n    #[cfg(feature = \"__tls\")]\n    // Re-exports, to be removed in a future release\n    pub use tls::{Certificate, Identity};\n    #[cfg(feature = \"multipart\")]\n    pub use self::async_impl::multipart;\n\n\n    mod async_impl;\n    #[cfg(feature = \"blocking\")]\n    pub mod blocking;\n    mod connect;\n    #[cfg(feature = \"cookies\")]\n    pub mod cookie;\n    pub mod dns;\n    mod proxy;\n    pub mod redirect;\n    pub mod retry;\n    #[cfg(feature = \"__tls\")]\n    pub mod tls;\n    mod util;\n\n    #[cfg(docsrs)]\n    pub use connect::uds::UnixSocketProvider;\n}\n\nif_wasm! {\n    mod wasm;\n    mod util;\n\n    pub use self::wasm::{Body, Client, ClientBuilder, Request, RequestBuilder, Response};\n    #[cfg(feature = \"multipart\")]\n    pub use self::wasm::multipart;\n}\n"
  },
  {
    "path": "src/proxy.rs",
    "content": "use std::error::Error;\nuse std::fmt;\nuse std::sync::Arc;\n\nuse http::uri::Scheme;\nuse http::{header::HeaderValue, HeaderMap, Uri};\nuse hyper_util::client::proxy::matcher;\n\nuse crate::into_url::{IntoUrl, IntoUrlSealed};\nuse crate::Url;\n\n// # Internals\n//\n// This module is a couple pieces:\n//\n// - The public builder API\n// - The internal built types that our Connector knows how to use.\n//\n// The user creates a builder (`reqwest::Proxy`), and configures any extras.\n// Once that type is passed to the `ClientBuilder`, we convert it into the\n// built matcher types, making use of `hyper-util`'s matchers.\n\n/// Configuration of a proxy that a `Client` should pass requests to.\n///\n/// A `Proxy` has a couple pieces to it:\n///\n/// - a URL of how to talk to the proxy\n/// - rules on what `Client` requests should be directed to the proxy\n///\n/// For instance, let's look at `Proxy::http`:\n///\n/// ```rust\n/// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n/// let proxy = reqwest::Proxy::http(\"https://secure.example\")?;\n/// # Ok(())\n/// # }\n/// ```\n///\n/// This proxy will intercept all HTTP requests, and make use of the proxy\n/// at `https://secure.example`. A request to `http://hyper.rs` will talk\n/// to your proxy. A request to `https://hyper.rs` will not.\n///\n/// Multiple `Proxy` rules can be configured for a `Client`. The `Client` will\n/// check each `Proxy` in the order it was added. This could mean that a\n/// `Proxy` added first with eager intercept rules, such as `Proxy::all`,\n/// would prevent a `Proxy` later in the list from ever working, so take care.\n///\n/// By enabling the `\"socks\"` feature it is possible to use a socks proxy:\n/// ```rust\n/// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n/// let proxy = reqwest::Proxy::http(\"socks5://192.168.1.1:9000\")?;\n/// # Ok(())\n/// # }\n/// ```\n#[derive(Clone)]\npub struct Proxy {\n    extra: Extra,\n    intercept: Intercept,\n    no_proxy: Option<NoProxy>,\n}\n\n/// A configuration for filtering out requests that shouldn't be proxied\n#[derive(Clone, Debug, Default)]\npub struct NoProxy {\n    inner: String,\n}\n\n#[derive(Clone)]\nstruct Extra {\n    auth: Option<HeaderValue>,\n    misc: Option<HeaderMap>,\n}\n\n// ===== Internal =====\n\npub(crate) struct Matcher {\n    inner: Matcher_,\n    extra: Extra,\n    maybe_has_http_auth: bool,\n    maybe_has_http_custom_headers: bool,\n}\n\nenum Matcher_ {\n    Util(matcher::Matcher),\n    Custom(Custom),\n}\n\n/// Our own type, wrapping an `Intercept`, since we may have a few additional\n/// pieces attached thanks to `reqwest`s extra proxy configuration.\npub(crate) struct Intercepted {\n    inner: matcher::Intercept,\n    /// This is because of `reqwest::Proxy`'s design which allows configuring\n    /// an explicit auth, besides what might have been in the URL (or Custom).\n    extra: Extra,\n}\n\n/*\nimpl ProxyScheme {\n    fn maybe_http_auth(&self) -> Option<&HeaderValue> {\n        match self {\n            ProxyScheme::Http { auth, .. } | ProxyScheme::Https { auth, .. } => auth.as_ref(),\n            #[cfg(feature = \"socks\")]\n            _ => None,\n        }\n    }\n\n    fn maybe_http_custom_headers(&self) -> Option<&HeaderMap> {\n        match self {\n            ProxyScheme::Http { misc, .. } | ProxyScheme::Https { misc, .. } => misc.as_ref(),\n            #[cfg(feature = \"socks\")]\n            _ => None,\n        }\n    }\n}\n*/\n\n/// Trait used for converting into a proxy scheme. This trait supports\n/// parsing from a URL-like type, whilst also supporting proxy schemes\n/// built directly using the factory methods.\npub trait IntoProxy {\n    fn into_proxy(self) -> crate::Result<Url>;\n}\n\nimpl<S: IntoUrl> IntoProxy for S {\n    fn into_proxy(self) -> crate::Result<Url> {\n        match self.as_str().into_url() {\n            Ok(mut url) => {\n                // If the scheme is a SOCKS protocol and no port is specified, set the default\n                if url.port().is_none()\n                    && matches!(url.scheme(), \"socks4\" | \"socks4a\" | \"socks5\" | \"socks5h\")\n                {\n                    let _ = url.set_port(Some(1080));\n                }\n                Ok(url)\n            }\n            Err(e) => {\n                let mut presumed_to_have_scheme = true;\n                let mut source = e.source();\n                while let Some(err) = source {\n                    if let Some(parse_error) = err.downcast_ref::<url::ParseError>() {\n                        if *parse_error == url::ParseError::RelativeUrlWithoutBase {\n                            presumed_to_have_scheme = false;\n                            break;\n                        }\n                    } else if err.downcast_ref::<crate::error::BadScheme>().is_some() {\n                        presumed_to_have_scheme = false;\n                        break;\n                    }\n                    source = err.source();\n                }\n                if presumed_to_have_scheme {\n                    return Err(crate::error::builder(e));\n                }\n                // the issue could have been caused by a missing scheme, so we try adding http://\n                let try_this = format!(\"http://{}\", self.as_str());\n                try_this.into_url().map_err(|_| {\n                    // return the original error\n                    crate::error::builder(e)\n                })\n            }\n        }\n    }\n}\n\n// These bounds are accidentally leaked by the blanket impl of IntoProxy\n// for all types that implement IntoUrl. So, this function exists to detect\n// if we were to break those bounds for a user.\nfn _implied_bounds() {\n    fn prox<T: IntoProxy>(_t: T) {}\n\n    fn url<T: IntoUrl>(t: T) {\n        prox(t);\n    }\n}\n\nimpl Proxy {\n    /// Proxy all HTTP traffic to the passed URL.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::Client::builder()\n    ///     .proxy(reqwest::Proxy::http(\"https://my.prox\")?)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn http<U: IntoProxy>(proxy_scheme: U) -> crate::Result<Proxy> {\n        Ok(Proxy::new(Intercept::Http(proxy_scheme.into_proxy()?)))\n    }\n\n    /// Proxy all HTTPS traffic to the passed URL.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::Client::builder()\n    ///     .proxy(reqwest::Proxy::https(\"https://example.prox:4545\")?)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn https<U: IntoProxy>(proxy_scheme: U) -> crate::Result<Proxy> {\n        Ok(Proxy::new(Intercept::Https(proxy_scheme.into_proxy()?)))\n    }\n\n    /// Proxy **all** traffic to the passed URL.\n    ///\n    /// \"All\" refers to `https` and `http` URLs. Other schemes are not\n    /// recognized by reqwest.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let client = reqwest::Client::builder()\n    ///     .proxy(reqwest::Proxy::all(\"http://pro.xy\")?)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn all<U: IntoProxy>(proxy_scheme: U) -> crate::Result<Proxy> {\n        Ok(Proxy::new(Intercept::All(proxy_scheme.into_proxy()?)))\n    }\n\n    /// Provide a custom function to determine what traffic to proxy to where.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let target = reqwest::Url::parse(\"https://my.prox\")?;\n    /// let client = reqwest::Client::builder()\n    ///     .proxy(reqwest::Proxy::custom(move |url| {\n    ///         if url.host_str() == Some(\"hyper.rs\") {\n    ///             Some(target.clone())\n    ///         } else {\n    ///             None\n    ///         }\n    ///     }))\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn custom<F, U: IntoProxy>(fun: F) -> Proxy\n    where\n        F: Fn(&Url) -> Option<U> + Send + Sync + 'static,\n    {\n        Proxy::new(Intercept::Custom(Custom {\n            func: Arc::new(move |url| fun(url).map(IntoProxy::into_proxy)),\n            no_proxy: None,\n        }))\n    }\n\n    fn new(intercept: Intercept) -> Proxy {\n        Proxy {\n            extra: Extra {\n                auth: None,\n                misc: None,\n            },\n            intercept,\n            no_proxy: None,\n        }\n    }\n\n    /// Set the `Proxy-Authorization` header using Basic auth.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let proxy = reqwest::Proxy::https(\"http://localhost:1234\")?\n    ///     .basic_auth(\"Aladdin\", \"open sesame\");\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn basic_auth(mut self, username: &str, password: &str) -> Proxy {\n        match self.intercept {\n            Intercept::All(ref mut s)\n            | Intercept::Http(ref mut s)\n            | Intercept::Https(ref mut s) => url_auth(s, username, password),\n            Intercept::Custom(_) => {\n                let header = encode_basic_auth(username, password);\n                self.extra.auth = Some(header);\n            }\n        }\n\n        self\n    }\n\n    /// Set the `Proxy-Authorization` header to a specified value.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # use reqwest::header::*;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let proxy = reqwest::Proxy::https(\"http://localhost:1234\")?\n    ///     .custom_http_auth(HeaderValue::from_static(\"justletmeinalreadyplease\"));\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn custom_http_auth(mut self, header_value: HeaderValue) -> Proxy {\n        self.extra.auth = Some(header_value);\n        self\n    }\n\n    /// Adds a Custom Headers to Proxy\n    /// Adds custom headers to this Proxy\n    ///\n    /// # Example\n    /// ```\n    /// # extern crate reqwest;\n    /// # use reqwest::header::*;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut headers = HeaderMap::new();\n    /// headers.insert(USER_AGENT, \"reqwest\".parse().unwrap());\n    /// let proxy = reqwest::Proxy::https(\"http://localhost:1234\")?\n    ///     .headers(headers);\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn headers(mut self, headers: HeaderMap) -> Proxy {\n        match self.intercept {\n            Intercept::All(_) | Intercept::Http(_) | Intercept::Https(_) | Intercept::Custom(_) => {\n                self.extra.misc = Some(headers);\n            }\n        }\n\n        self\n    }\n\n    /// Adds a `No Proxy` exclusion list to this Proxy\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate reqwest;\n    /// # fn run() -> Result<(), Box<dyn std::error::Error>> {\n    /// let proxy = reqwest::Proxy::https(\"http://localhost:1234\")?\n    ///     .no_proxy(reqwest::NoProxy::from_string(\"direct.tld, sub.direct2.tld\"));\n    /// # Ok(())\n    /// # }\n    /// # fn main() {}\n    /// ```\n    pub fn no_proxy(mut self, no_proxy: Option<NoProxy>) -> Proxy {\n        self.no_proxy = no_proxy;\n        self\n    }\n\n    pub(crate) fn into_matcher(self) -> Matcher {\n        let Proxy {\n            intercept,\n            extra,\n            no_proxy,\n        } = self;\n\n        let maybe_has_http_auth;\n        let maybe_has_http_custom_headers;\n\n        let inner = match intercept {\n            Intercept::All(url) => {\n                maybe_has_http_auth = cache_maybe_has_http_auth(&url, &extra.auth);\n                maybe_has_http_custom_headers =\n                    cache_maybe_has_http_custom_headers(&url, &extra.misc);\n                Matcher_::Util(\n                    matcher::Matcher::builder()\n                        .all(String::from(url))\n                        .no(no_proxy.as_ref().map(|n| n.inner.as_ref()).unwrap_or(\"\"))\n                        .build(),\n                )\n            }\n            Intercept::Http(url) => {\n                maybe_has_http_auth = cache_maybe_has_http_auth(&url, &extra.auth);\n                maybe_has_http_custom_headers =\n                    cache_maybe_has_http_custom_headers(&url, &extra.misc);\n                Matcher_::Util(\n                    matcher::Matcher::builder()\n                        .http(String::from(url))\n                        .no(no_proxy.as_ref().map(|n| n.inner.as_ref()).unwrap_or(\"\"))\n                        .build(),\n                )\n            }\n            Intercept::Https(url) => {\n                maybe_has_http_auth = cache_maybe_has_http_auth(&url, &extra.auth);\n                maybe_has_http_custom_headers =\n                    cache_maybe_has_http_custom_headers(&url, &extra.misc);\n                Matcher_::Util(\n                    matcher::Matcher::builder()\n                        .https(String::from(url))\n                        .no(no_proxy.as_ref().map(|n| n.inner.as_ref()).unwrap_or(\"\"))\n                        .build(),\n                )\n            }\n            Intercept::Custom(mut custom) => {\n                maybe_has_http_auth = true; // never know\n                maybe_has_http_custom_headers = true;\n                custom.no_proxy = no_proxy;\n                Matcher_::Custom(custom)\n            }\n        };\n\n        Matcher {\n            inner,\n            extra,\n            maybe_has_http_auth,\n            maybe_has_http_custom_headers,\n        }\n    }\n\n    /*\n    pub(crate) fn maybe_has_http_auth(&self) -> bool {\n        match &self.intercept {\n            Intercept::All(p) | Intercept::Http(p) => p.maybe_http_auth().is_some(),\n            // Custom *may* match 'http', so assume so.\n            Intercept::Custom(_) => true,\n            Intercept::System(system) => system\n                .get(\"http\")\n                .and_then(|s| s.maybe_http_auth())\n                .is_some(),\n            Intercept::Https(_) => false,\n        }\n    }\n\n    pub(crate) fn http_basic_auth<D: Dst>(&self, uri: &D) -> Option<HeaderValue> {\n        match &self.intercept {\n            Intercept::All(p) | Intercept::Http(p) => p.maybe_http_auth().cloned(),\n            Intercept::System(system) => system\n                .get(\"http\")\n                .and_then(|s| s.maybe_http_auth().cloned()),\n            Intercept::Custom(custom) => {\n                custom.call(uri).and_then(|s| s.maybe_http_auth().cloned())\n            }\n            Intercept::Https(_) => None,\n        }\n    }\n    */\n}\n\nfn cache_maybe_has_http_auth(url: &Url, extra: &Option<HeaderValue>) -> bool {\n    (url.scheme() == \"http\" || url.scheme() == \"https\")\n        && (url.username().len() > 0 || url.password().is_some() || extra.is_some())\n}\n\nfn cache_maybe_has_http_custom_headers(url: &Url, extra: &Option<HeaderMap>) -> bool {\n    (url.scheme() == \"http\" || url.scheme() == \"https\") && extra.is_some()\n}\n\nimpl fmt::Debug for Proxy {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_tuple(\"Proxy\")\n            .field(&self.intercept)\n            .field(&self.no_proxy)\n            .finish()\n    }\n}\n\nimpl NoProxy {\n    /// Returns a new no-proxy configuration based on environment variables (or `None` if no variables are set)\n    /// see [self::NoProxy::from_string()] for the string format\n    pub fn from_env() -> Option<NoProxy> {\n        let raw = std::env::var(\"NO_PROXY\")\n            .or_else(|_| std::env::var(\"no_proxy\"))\n            .ok()?;\n\n        // Per the docs, this returns `None` if no environment variable is set. We can only reach\n        // here if an env var is set, so we return `Some(NoProxy::default)` if `from_string`\n        // returns None, which occurs with an empty string.\n        Some(Self::from_string(&raw).unwrap_or_default())\n    }\n\n    /// Returns a new no-proxy configuration based on a `no_proxy` string (or `None` if no variables\n    /// are set)\n    /// The rules are as follows:\n    /// * The environment variable `NO_PROXY` is checked, if it is not set, `no_proxy` is checked\n    /// * If neither environment variable is set, `None` is returned\n    /// * Entries are expected to be comma-separated (whitespace between entries is ignored)\n    /// * IP addresses (both IPv4 and IPv6) are allowed, as are optional subnet masks (by adding /size,\n    ///   for example \"`192.168.1.0/24`\").\n    /// * An entry \"`*`\" matches all hostnames (this is the only wildcard allowed)\n    /// * Any other entry is considered a domain name (and may contain a leading dot, for example `google.com`\n    ///   and `.google.com` are equivalent) and would match both that domain AND all subdomains.\n    ///\n    /// For example, if `\"NO_PROXY=google.com, 192.168.1.0/24\"` was set, all the following would match\n    /// (and therefore would bypass the proxy):\n    /// * `http://google.com/`\n    /// * `http://www.google.com/`\n    /// * `http://192.168.1.42/`\n    ///\n    /// The URL `http://notgoogle.com/` would not match.\n    pub fn from_string(no_proxy_list: &str) -> Option<Self> {\n        // lazy parsed, to not make the type public in hyper-util\n        Some(NoProxy {\n            inner: no_proxy_list.into(),\n        })\n    }\n}\n\nimpl Matcher {\n    pub(crate) fn system() -> Self {\n        Self {\n            inner: Matcher_::Util(matcher::Matcher::from_system()),\n            extra: Extra {\n                auth: None,\n                misc: None,\n            },\n            // maybe env vars have auth!\n            maybe_has_http_auth: true,\n            maybe_has_http_custom_headers: true,\n        }\n    }\n\n    pub(crate) fn intercept(&self, dst: &Uri) -> Option<Intercepted> {\n        let inner = match self.inner {\n            Matcher_::Util(ref m) => m.intercept(dst),\n            Matcher_::Custom(ref c) => c.call(dst),\n        };\n\n        inner.map(|inner| Intercepted {\n            inner,\n            extra: self.extra.clone(),\n        })\n    }\n\n    /// Return whether this matcher might provide HTTP (not s) auth.\n    ///\n    /// This is very specific. If this proxy needs auth to be part of a Forward\n    /// request (instead of a tunnel), this should return true.\n    ///\n    /// If it's not sure, this should return true.\n    ///\n    /// This is meant as a hint to allow skipping a more expensive check\n    /// (calling `intercept()`) if it will never need auth when Forwarding.\n    pub(crate) fn maybe_has_http_auth(&self) -> bool {\n        self.maybe_has_http_auth\n    }\n\n    pub(crate) fn http_non_tunnel_basic_auth(&self, dst: &Uri) -> Option<HeaderValue> {\n        if let Some(proxy) = self.intercept(dst) {\n            let scheme = proxy.uri().scheme();\n            if scheme == Some(&Scheme::HTTP) || scheme == Some(&Scheme::HTTPS) {\n                return proxy.basic_auth().cloned();\n            }\n        }\n\n        None\n    }\n\n    pub(crate) fn maybe_has_http_custom_headers(&self) -> bool {\n        self.maybe_has_http_custom_headers\n    }\n\n    pub(crate) fn http_non_tunnel_custom_headers(&self, dst: &Uri) -> Option<HeaderMap> {\n        if let Some(proxy) = self.intercept(dst) {\n            let scheme = proxy.uri().scheme();\n            if scheme == Some(&Scheme::HTTP) || scheme == Some(&Scheme::HTTPS) {\n                return proxy.custom_headers().cloned();\n            }\n        }\n\n        None\n    }\n}\n\nimpl fmt::Debug for Matcher {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.inner {\n            Matcher_::Util(ref m) => m.fmt(f),\n            Matcher_::Custom(ref m) => m.fmt(f),\n        }\n    }\n}\n\nimpl Intercepted {\n    pub(crate) fn uri(&self) -> &http::Uri {\n        self.inner.uri()\n    }\n\n    pub(crate) fn basic_auth(&self) -> Option<&HeaderValue> {\n        if let Some(ref val) = self.extra.auth {\n            return Some(val);\n        }\n        self.inner.basic_auth()\n    }\n\n    pub(crate) fn custom_headers(&self) -> Option<&HeaderMap> {\n        if let Some(ref val) = self.extra.misc {\n            return Some(val);\n        }\n        None\n    }\n\n    #[cfg(feature = \"socks\")]\n    pub(crate) fn raw_auth(&self) -> Option<(&str, &str)> {\n        self.inner.raw_auth()\n    }\n}\n\nimpl fmt::Debug for Intercepted {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.uri().fmt(f)\n    }\n}\n\n/*\nimpl ProxyScheme {\n    /// Use a username and password when connecting to the proxy server\n    fn with_basic_auth<T: Into<String>, U: Into<String>>(\n        mut self,\n        username: T,\n        password: U,\n    ) -> Self {\n        self.set_basic_auth(username, password);\n        self\n    }\n\n    fn set_basic_auth<T: Into<String>, U: Into<String>>(&mut self, username: T, password: U) {\n        match *self {\n            ProxyScheme::Http { ref mut auth, .. } => {\n                let header = encode_basic_auth(&username.into(), &password.into());\n                *auth = Some(header);\n            }\n            ProxyScheme::Https { ref mut auth, .. } => {\n                let header = encode_basic_auth(&username.into(), &password.into());\n                *auth = Some(header);\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks4 { .. } => {\n                panic!(\"Socks4 is not supported for this method\")\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks5 { ref mut auth, .. } => {\n                *auth = Some((username.into(), password.into()));\n            }\n        }\n    }\n\n    fn set_custom_http_auth(&mut self, header_value: HeaderValue) {\n        match *self {\n            ProxyScheme::Http { ref mut auth, .. } => {\n                *auth = Some(header_value);\n            }\n            ProxyScheme::Https { ref mut auth, .. } => {\n                *auth = Some(header_value);\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks4 { .. } => {\n                panic!(\"Socks4 is not supported for this method\")\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks5 { .. } => {\n                panic!(\"Socks5 is not supported for this method\")\n            }\n        }\n    }\n\n    fn set_custom_headers(&mut self, headers: HeaderMap) {\n        match *self {\n            ProxyScheme::Http { ref mut misc, .. } => {\n                misc.get_or_insert_with(HeaderMap::new).extend(headers)\n            }\n            ProxyScheme::Https { ref mut misc, .. } => {\n                misc.get_or_insert_with(HeaderMap::new).extend(headers)\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks4 { .. } => {\n                panic!(\"Socks4 is not supported for this method\")\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks5 { .. } => {\n                panic!(\"Socks5 is not supported for this method\")\n            }\n        }\n    }\n\n    fn if_no_auth(mut self, update: &Option<HeaderValue>) -> Self {\n        match self {\n            ProxyScheme::Http { ref mut auth, .. } => {\n                if auth.is_none() {\n                    *auth = update.clone();\n                }\n            }\n            ProxyScheme::Https { ref mut auth, .. } => {\n                if auth.is_none() {\n                    *auth = update.clone();\n                }\n            }\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks4 { .. } => {}\n            #[cfg(feature = \"socks\")]\n            ProxyScheme::Socks5 { .. } => {}\n        }\n\n        self\n    }\n\n    /// Convert a URL into a proxy scheme\n    ///\n    /// Supported schemes: HTTP, HTTPS, (SOCKS4, SOCKS5, SOCKS5H if `socks` feature is enabled).\n    // Private for now...\n    fn parse(url: Url) -> crate::Result<Self> {\n        use url::Position;\n\n        // Resolve URL to a host and port\n        #[cfg(feature = \"socks\")]\n        let to_addr = || {\n            let addrs = url\n                .socket_addrs(|| match url.scheme() {\n                    \"socks4\" | \"socks4a\" | \"socks5\" | \"socks5h\" => Some(1080),\n                    _ => None,\n                })\n                .map_err(crate::error::builder)?;\n            addrs\n                .into_iter()\n                .next()\n                .ok_or_else(|| crate::error::builder(\"unknown proxy scheme\"))\n        };\n\n        let mut scheme = match url.scheme() {\n            \"http\" => Self::http(&url[Position::BeforeHost..Position::AfterPort])?,\n            \"https\" => Self::https(&url[Position::BeforeHost..Position::AfterPort])?,\n            #[cfg(feature = \"socks\")]\n            \"socks4\" => Self::socks4(to_addr()?)?,\n            #[cfg(feature = \"socks\")]\n            \"socks4a\" => Self::socks4a(to_addr()?)?,\n            #[cfg(feature = \"socks\")]\n            \"socks5\" => Self::socks5(to_addr()?)?,\n            #[cfg(feature = \"socks\")]\n            \"socks5h\" => Self::socks5h(to_addr()?)?,\n            _ => return Err(crate::error::builder(\"unknown proxy scheme\")),\n        };\n\n        if let Some(pwd) = url.password() {\n            let decoded_username = percent_decode(url.username().as_bytes()).decode_utf8_lossy();\n            let decoded_password = percent_decode(pwd.as_bytes()).decode_utf8_lossy();\n            scheme = scheme.with_basic_auth(decoded_username, decoded_password);\n        }\n\n        Ok(scheme)\n    }\n}\n*/\n\n#[derive(Clone, Debug)]\nenum Intercept {\n    All(Url),\n    Http(Url),\n    Https(Url),\n    Custom(Custom),\n}\n\nfn url_auth(url: &mut Url, username: &str, password: &str) {\n    url.set_username(username).expect(\"is a base\");\n    url.set_password(Some(password)).expect(\"is a base\");\n}\n\n#[derive(Clone)]\nstruct Custom {\n    func: Arc<dyn Fn(&Url) -> Option<crate::Result<Url>> + Send + Sync + 'static>,\n    no_proxy: Option<NoProxy>,\n}\n\nimpl Custom {\n    fn call(&self, uri: &http::Uri) -> Option<matcher::Intercept> {\n        let url = format!(\n            \"{}://{}{}{}\",\n            uri.scheme()?,\n            uri.host()?,\n            uri.port().map_or(\"\", |_| \":\"),\n            uri.port().map_or(String::new(), |p| p.to_string())\n        )\n        .parse()\n        .expect(\"should be valid Url\");\n\n        (self.func)(&url)\n            .and_then(|result| result.ok())\n            .and_then(|target| {\n                let m = matcher::Matcher::builder()\n                    .all(String::from(target))\n                    .build();\n\n                m.intercept(uri)\n            })\n        //.map(|scheme| scheme.if_no_auth(&self.auth))\n    }\n}\n\nimpl fmt::Debug for Custom {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.write_str(\"_\")\n    }\n}\n\npub(crate) fn encode_basic_auth(username: &str, password: &str) -> HeaderValue {\n    crate::util::basic_auth(username, Some(password))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn url(s: &str) -> http::Uri {\n        s.parse().unwrap()\n    }\n\n    fn intercepted_uri(p: &Matcher, s: &str) -> Uri {\n        p.intercept(&s.parse().unwrap()).unwrap().uri().clone()\n    }\n\n    #[test]\n    fn test_http() {\n        let target = \"http://example.domain/\";\n        let p = Proxy::http(target).unwrap().into_matcher();\n\n        let http = \"http://hyper.rs\";\n        let other = \"https://hyper.rs\";\n\n        assert_eq!(intercepted_uri(&p, http), target);\n        assert!(p.intercept(&url(other)).is_none());\n    }\n\n    #[test]\n    fn test_https() {\n        let target = \"http://example.domain/\";\n        let p = Proxy::https(target).unwrap().into_matcher();\n\n        let http = \"http://hyper.rs\";\n        let other = \"https://hyper.rs\";\n\n        assert!(p.intercept(&url(http)).is_none());\n        assert_eq!(intercepted_uri(&p, other), target);\n    }\n\n    #[test]\n    fn test_all() {\n        let target = \"http://example.domain/\";\n        let p = Proxy::all(target).unwrap().into_matcher();\n\n        let http = \"http://hyper.rs\";\n        let https = \"https://hyper.rs\";\n        // no longer supported\n        //let other = \"x-youve-never-heard-of-me-mr-proxy://hyper.rs\";\n\n        assert_eq!(intercepted_uri(&p, http), target);\n        assert_eq!(intercepted_uri(&p, https), target);\n        //assert_eq!(intercepted_uri(&p, other), target);\n    }\n\n    #[test]\n    fn test_custom() {\n        let target1 = \"http://example.domain/\";\n        let target2 = \"https://example.domain/\";\n        let p = Proxy::custom(move |url| {\n            if url.host_str() == Some(\"hyper.rs\") {\n                target1.parse().ok()\n            } else if url.scheme() == \"http\" {\n                target2.parse().ok()\n            } else {\n                None::<Url>\n            }\n        })\n        .into_matcher();\n\n        let http = \"http://seanmonstar.com\";\n        let https = \"https://hyper.rs\";\n        let other = \"x-youve-never-heard-of-me-mr-proxy://seanmonstar.com\";\n\n        assert_eq!(intercepted_uri(&p, http), target2);\n        assert_eq!(intercepted_uri(&p, https), target1);\n        assert!(p.intercept(&url(other)).is_none());\n    }\n\n    #[test]\n    fn test_standard_with_custom_auth_header() {\n        let target = \"http://example.domain/\";\n        let p = Proxy::all(target)\n            .unwrap()\n            .custom_http_auth(http::HeaderValue::from_static(\"testme\"))\n            .into_matcher();\n\n        let got = p.intercept(&url(\"http://anywhere.local\")).unwrap();\n        let auth = got.basic_auth().unwrap();\n        assert_eq!(auth, \"testme\");\n    }\n\n    #[test]\n    fn test_custom_with_custom_auth_header() {\n        let target = \"http://example.domain/\";\n        let p = Proxy::custom(move |_| target.parse::<Url>().ok())\n            .custom_http_auth(http::HeaderValue::from_static(\"testme\"))\n            .into_matcher();\n\n        let got = p.intercept(&url(\"http://anywhere.local\")).unwrap();\n        let auth = got.basic_auth().unwrap();\n        assert_eq!(auth, \"testme\");\n    }\n\n    #[test]\n    fn test_maybe_has_http_auth() {\n        let m = Proxy::all(\"https://letme:in@yo.local\")\n            .unwrap()\n            .into_matcher();\n        assert!(m.maybe_has_http_auth(), \"https forwards\");\n\n        let m = Proxy::all(\"http://letme:in@yo.local\")\n            .unwrap()\n            .into_matcher();\n        assert!(m.maybe_has_http_auth(), \"http forwards\");\n\n        let m = Proxy::all(\"http://:in@yo.local\").unwrap().into_matcher();\n        assert!(m.maybe_has_http_auth(), \"http forwards with empty username\");\n\n        let m = Proxy::all(\"http://letme:@yo.local\").unwrap().into_matcher();\n        assert!(m.maybe_has_http_auth(), \"http forwards with empty password\");\n    }\n\n    #[test]\n    fn test_socks_proxy_default_port() {\n        {\n            let m = Proxy::all(\"socks5://example.com\").unwrap().into_matcher();\n\n            let http = \"http://hyper.rs\";\n            let https = \"https://hyper.rs\";\n\n            assert_eq!(intercepted_uri(&m, http).port_u16(), Some(1080));\n            assert_eq!(intercepted_uri(&m, https).port_u16(), Some(1080));\n\n            // custom port\n            let m = Proxy::all(\"socks5://example.com:1234\")\n                .unwrap()\n                .into_matcher();\n\n            assert_eq!(intercepted_uri(&m, http).port_u16(), Some(1234));\n            assert_eq!(intercepted_uri(&m, https).port_u16(), Some(1234));\n        }\n    }\n}\n"
  },
  {
    "path": "src/redirect.rs",
    "content": "//! Redirect Handling\n//!\n//! By default, a `Client` will automatically handle HTTP redirects, having a\n//! maximum redirect chain of 10 hops. To customize this behavior, a\n//! `redirect::Policy` can be used with a `ClientBuilder`.\n\nuse std::fmt;\nuse std::{error::Error as StdError, sync::Arc};\n\nuse crate::header::{AUTHORIZATION, COOKIE, PROXY_AUTHORIZATION, REFERER, WWW_AUTHENTICATE};\nuse http::{HeaderMap, HeaderValue};\nuse hyper::StatusCode;\n\nuse crate::{async_impl, Url};\nuse tower_http::follow_redirect::policy::{\n    Action as TowerAction, Attempt as TowerAttempt, Policy as TowerPolicy,\n};\n\n/// A type that controls the policy on how to handle the following of redirects.\n///\n/// The default value will catch redirect loops, and has a maximum of 10\n/// redirects it will follow in a chain before returning an error.\n///\n/// - `limited` can be used have the same as the default behavior, but adjust\n///   the allowed maximum redirect hops in a chain.\n/// - `none` can be used to disable all redirect behavior.\n/// - `custom` can be used to create a customized policy.\npub struct Policy {\n    inner: PolicyKind,\n}\n\n/// A type that holds information on the next request and previous requests\n/// in redirect chain.\n#[derive(Debug)]\npub struct Attempt<'a> {\n    status: StatusCode,\n    next: &'a Url,\n    previous: &'a [Url],\n}\n\n/// An action to perform when a redirect status code is found.\n#[derive(Debug)]\npub struct Action {\n    inner: ActionKind,\n}\n\nimpl Policy {\n    /// Create a `Policy` with a maximum number of redirects.\n    ///\n    /// An `Error` will be returned if the max is reached.\n    pub fn limited(max: usize) -> Self {\n        Self {\n            inner: PolicyKind::Limit(max),\n        }\n    }\n\n    /// Create a `Policy` that does not follow any redirect.\n    pub fn none() -> Self {\n        Self {\n            inner: PolicyKind::None,\n        }\n    }\n\n    /// Create a custom `Policy` using the passed function.\n    ///\n    /// # Note\n    ///\n    /// The default `Policy` handles a maximum loop\n    /// chain, but the custom variant does not do that for you automatically.\n    /// The custom policy should have some way of handling those.\n    ///\n    /// Information on the next request and previous requests can be found\n    /// on the [`Attempt`] argument passed to the closure.\n    ///\n    /// Actions can be conveniently created from methods on the\n    /// [`Attempt`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use reqwest::{Error, redirect};\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let custom = redirect::Policy::custom(|attempt| {\n    ///     if attempt.previous().len() > 5 {\n    ///         attempt.error(\"too many redirects\")\n    ///     } else if attempt.url().host_str() == Some(\"example.domain\") {\n    ///         // prevent redirects to 'example.domain'\n    ///         attempt.stop()\n    ///     } else {\n    ///         attempt.follow()\n    ///     }\n    /// });\n    /// let client = reqwest::Client::builder()\n    ///     .redirect(custom)\n    ///     .build()?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// [`Attempt`]: struct.Attempt.html\n    pub fn custom<T>(policy: T) -> Self\n    where\n        T: Fn(Attempt) -> Action + Send + Sync + 'static,\n    {\n        Self {\n            inner: PolicyKind::Custom(Box::new(policy)),\n        }\n    }\n\n    /// Apply this policy to a given [`Attempt`] to produce a [`Action`].\n    ///\n    /// # Note\n    ///\n    /// This method can be used together with `Policy::custom()`\n    /// to construct one `Policy` that wraps another.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use reqwest::{Error, redirect};\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let custom = redirect::Policy::custom(|attempt| {\n    ///     eprintln!(\"{}, Location: {:?}\", attempt.status(), attempt.url());\n    ///     redirect::Policy::default().redirect(attempt)\n    /// });\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn redirect(&self, attempt: Attempt) -> Action {\n        match self.inner {\n            PolicyKind::Custom(ref custom) => custom(attempt),\n            PolicyKind::Limit(max) => {\n                // The first URL in the previous is the initial URL and not a redirection. It needs to be excluded.\n                if attempt.previous.len() > max {\n                    attempt.error(TooManyRedirects)\n                } else {\n                    attempt.follow()\n                }\n            }\n            PolicyKind::None => attempt.stop(),\n        }\n    }\n\n    pub(crate) fn check(&self, status: StatusCode, next: &Url, previous: &[Url]) -> ActionKind {\n        self.redirect(Attempt {\n            status,\n            next,\n            previous,\n        })\n        .inner\n    }\n\n    pub(crate) fn is_default(&self) -> bool {\n        matches!(self.inner, PolicyKind::Limit(10))\n    }\n}\n\nimpl Default for Policy {\n    fn default() -> Policy {\n        // Keep `is_default` in sync\n        Policy::limited(10)\n    }\n}\n\nimpl<'a> Attempt<'a> {\n    /// Get the type of redirect.\n    pub fn status(&self) -> StatusCode {\n        self.status\n    }\n\n    /// Get the next URL to redirect to.\n    pub fn url(&self) -> &Url {\n        self.next\n    }\n\n    /// Get the list of previous URLs that have already been requested in this chain.\n    pub fn previous(&self) -> &[Url] {\n        self.previous\n    }\n    /// Returns an action meaning reqwest should follow the next URL.\n    pub fn follow(self) -> Action {\n        Action {\n            inner: ActionKind::Follow,\n        }\n    }\n\n    /// Returns an action meaning reqwest should not follow the next URL.\n    ///\n    /// The 30x response will be returned as the `Ok` result.\n    pub fn stop(self) -> Action {\n        Action {\n            inner: ActionKind::Stop,\n        }\n    }\n\n    /// Returns an action failing the redirect with an error.\n    ///\n    /// The `Error` will be returned for the result of the sent request.\n    pub fn error<E: Into<Box<dyn StdError + Send + Sync>>>(self, error: E) -> Action {\n        Action {\n            inner: ActionKind::Error(error.into()),\n        }\n    }\n}\n\nenum PolicyKind {\n    Custom(Box<dyn Fn(Attempt) -> Action + Send + Sync + 'static>),\n    Limit(usize),\n    None,\n}\n\nimpl fmt::Debug for Policy {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_tuple(\"Policy\").field(&self.inner).finish()\n    }\n}\n\nimpl fmt::Debug for PolicyKind {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match *self {\n            PolicyKind::Custom(..) => f.pad(\"Custom\"),\n            PolicyKind::Limit(max) => f.debug_tuple(\"Limit\").field(&max).finish(),\n            PolicyKind::None => f.pad(\"None\"),\n        }\n    }\n}\n\n// pub(crate)\n\n#[derive(Debug)]\npub(crate) enum ActionKind {\n    Follow,\n    Stop,\n    Error(Box<dyn StdError + Send + Sync>),\n}\n\npub(crate) fn remove_sensitive_headers(headers: &mut HeaderMap, next: &Url, previous: &[Url]) {\n    if let Some(previous) = previous.last() {\n        let cross_host = next.host_str() != previous.host_str()\n            || next.port_or_known_default() != previous.port_or_known_default();\n        if cross_host {\n            headers.remove(AUTHORIZATION);\n            headers.remove(COOKIE);\n            headers.remove(\"cookie2\");\n            headers.remove(PROXY_AUTHORIZATION);\n            headers.remove(WWW_AUTHENTICATE);\n        }\n    }\n}\n\n#[derive(Debug)]\nstruct TooManyRedirects;\n\nimpl fmt::Display for TooManyRedirects {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"too many redirects\")\n    }\n}\n\nimpl StdError for TooManyRedirects {}\n\n#[derive(Clone)]\npub(crate) struct TowerRedirectPolicy {\n    policy: Arc<Policy>,\n    referer: bool,\n    urls: Vec<Url>,\n    https_only: bool,\n}\n\nimpl TowerRedirectPolicy {\n    pub(crate) fn new(policy: Policy) -> Self {\n        Self {\n            policy: Arc::new(policy),\n            referer: false,\n            urls: Vec::new(),\n            https_only: false,\n        }\n    }\n\n    pub(crate) fn with_referer(&mut self, referer: bool) -> &mut Self {\n        self.referer = referer;\n        self\n    }\n\n    pub(crate) fn with_https_only(&mut self, https_only: bool) -> &mut Self {\n        self.https_only = https_only;\n        self\n    }\n}\n\nfn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {\n    if next.scheme() == \"http\" && previous.scheme() == \"https\" {\n        return None;\n    }\n\n    let mut referer = previous.clone();\n    let _ = referer.set_username(\"\");\n    let _ = referer.set_password(None);\n    referer.set_fragment(None);\n    referer.as_str().parse().ok()\n}\n\nimpl TowerPolicy<async_impl::body::Body, crate::Error> for TowerRedirectPolicy {\n    fn redirect(&mut self, attempt: &TowerAttempt<'_>) -> Result<TowerAction, crate::Error> {\n        let previous_url =\n            Url::parse(&attempt.previous().to_string()).expect(\"Previous URL must be valid\");\n\n        let next_url = match Url::parse(&attempt.location().to_string()) {\n            Ok(url) => url,\n            Err(e) => return Err(crate::error::builder(e)),\n        };\n\n        self.urls.push(previous_url.clone());\n\n        match self.policy.check(attempt.status(), &next_url, &self.urls) {\n            ActionKind::Follow => {\n                if next_url.scheme() != \"http\" && next_url.scheme() != \"https\" {\n                    return Err(crate::error::url_bad_scheme(next_url));\n                }\n\n                if self.https_only && next_url.scheme() != \"https\" {\n                    return Err(crate::error::redirect(\n                        crate::error::url_bad_scheme(next_url.clone()),\n                        next_url,\n                    ));\n                }\n                Ok(TowerAction::Follow)\n            }\n            ActionKind::Stop => Ok(TowerAction::Stop),\n            ActionKind::Error(e) => Err(crate::error::redirect(e, previous_url)),\n        }\n    }\n\n    fn on_request(&mut self, req: &mut http::Request<async_impl::body::Body>) {\n        if let Ok(next_url) = Url::parse(&req.uri().to_string()) {\n            remove_sensitive_headers(req.headers_mut(), &next_url, &self.urls);\n            if self.referer {\n                if let Some(previous_url) = self.urls.last() {\n                    if let Some(v) = make_referer(&next_url, previous_url) {\n                        req.headers_mut().insert(REFERER, v);\n                    }\n                }\n            }\n        };\n    }\n\n    // This must be implemented to make 307 and 308 redirects work\n    fn clone_body(&self, body: &async_impl::body::Body) -> Option<async_impl::body::Body> {\n        body.try_clone()\n    }\n}\n\n#[test]\nfn test_redirect_policy_limit() {\n    let policy = Policy::default();\n    let next = Url::parse(\"http://x.y/z\").unwrap();\n    let mut previous = (0..=9)\n        .map(|i| Url::parse(&format!(\"http://a.b/c/{i}\")).unwrap())\n        .collect::<Vec<_>>();\n\n    match policy.check(StatusCode::FOUND, &next, &previous) {\n        ActionKind::Follow => (),\n        other => panic!(\"unexpected {other:?}\"),\n    }\n\n    previous.push(Url::parse(\"http://a.b.d/e/33\").unwrap());\n\n    match policy.check(StatusCode::FOUND, &next, &previous) {\n        ActionKind::Error(err) if err.is::<TooManyRedirects>() => (),\n        other => panic!(\"unexpected {other:?}\"),\n    }\n}\n\n#[test]\nfn test_redirect_policy_limit_to_0() {\n    let policy = Policy::limited(0);\n    let next = Url::parse(\"http://x.y/z\").unwrap();\n    let previous = vec![Url::parse(\"http://a.b/c\").unwrap()];\n\n    match policy.check(StatusCode::FOUND, &next, &previous) {\n        ActionKind::Error(err) if err.is::<TooManyRedirects>() => (),\n        other => panic!(\"unexpected {other:?}\"),\n    }\n}\n\n#[test]\nfn test_redirect_policy_custom() {\n    let policy = Policy::custom(|attempt| {\n        if attempt.url().host_str() == Some(\"foo\") {\n            attempt.stop()\n        } else {\n            attempt.follow()\n        }\n    });\n\n    let next = Url::parse(\"http://bar/baz\").unwrap();\n    match policy.check(StatusCode::FOUND, &next, &[]) {\n        ActionKind::Follow => (),\n        other => panic!(\"unexpected {other:?}\"),\n    }\n\n    let next = Url::parse(\"http://foo/baz\").unwrap();\n    match policy.check(StatusCode::FOUND, &next, &[]) {\n        ActionKind::Stop => (),\n        other => panic!(\"unexpected {other:?}\"),\n    }\n}\n\n#[test]\nfn test_remove_sensitive_headers() {\n    use hyper::header::{HeaderValue, ACCEPT, AUTHORIZATION, COOKIE};\n\n    let mut headers = HeaderMap::new();\n    headers.insert(ACCEPT, HeaderValue::from_static(\"*/*\"));\n    headers.insert(AUTHORIZATION, HeaderValue::from_static(\"let me in\"));\n    headers.insert(COOKIE, HeaderValue::from_static(\"foo=bar\"));\n\n    let next = Url::parse(\"http://initial-domain.com/path\").unwrap();\n    let mut prev = vec![Url::parse(\"http://initial-domain.com/new_path\").unwrap()];\n    let mut filtered_headers = headers.clone();\n\n    remove_sensitive_headers(&mut headers, &next, &prev);\n    assert_eq!(headers, filtered_headers);\n\n    prev.push(Url::parse(\"http://new-domain.com/path\").unwrap());\n    filtered_headers.remove(AUTHORIZATION);\n    filtered_headers.remove(COOKIE);\n\n    remove_sensitive_headers(&mut headers, &next, &prev);\n    assert_eq!(headers, filtered_headers);\n}\n"
  },
  {
    "path": "src/response.rs",
    "content": "use url::Url;\n\n#[derive(Debug, Clone, PartialEq)]\npub(crate) struct ResponseUrl(pub Url);\n\n/// Extension trait for http::response::Builder objects\n///\n/// Allows the user to add a `Url` to the http::Response\npub trait ResponseBuilderExt {\n    /// A builder method for the `http::response::Builder` type that allows the user to add a `Url`\n    /// to the `http::Response`\n    fn url(self, url: Url) -> Self;\n}\n\nimpl ResponseBuilderExt for http::response::Builder {\n    fn url(self, url: Url) -> Self {\n        self.extension(ResponseUrl(url))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{ResponseBuilderExt, ResponseUrl};\n    use http::response::Builder;\n    use url::Url;\n\n    #[test]\n    fn test_response_builder_ext() {\n        let url = Url::parse(\"http://example.com\").unwrap();\n        let response = Builder::new()\n            .status(200)\n            .url(url.clone())\n            .body(())\n            .unwrap();\n\n        assert_eq!(\n            response.extensions().get::<ResponseUrl>(),\n            Some(&ResponseUrl(url))\n        );\n    }\n}\n"
  },
  {
    "path": "src/retry.rs",
    "content": "//! Retry requests\n//!\n//! A `Client` has the ability to retry requests, by sending additional copies\n//! to the server if a response is considered retryable.\n//!\n//! The [`Builder`] makes it easier to configure what requests to retry, along\n//! with including best practices by default, such as a retry budget.\n//!\n//! # Defaults\n//!\n//! The default retry behavior of a `Client` is to only retry requests where an\n//! error or low-level protocol NACK is encountered that is known to be safe to\n//! retry. Note however that providing a specific retry policy will override\n//! the default, and you will need to explicitly include that behavior.\n//!\n//! All policies default to including a retry budget that permits 20% extra\n//! requests to be sent.\n//!\n//! # Scoped\n//!\n//! A client's retry policy is scoped. That means that the policy doesn't\n//! apply to all requests, but only those within a user-defined scope.\n//!\n//! Since all policies include a budget by default, it doesn't make sense to\n//! apply it on _all_ requests. Rather, the retry history applied by a budget\n//! should likely only be applied to the same host.\n//!\n//! # Classifiers\n//!\n//! A retry policy needs to be configured with a classifier that determines\n//! if a request should be retried. Knowledge of the destination server's\n//! behavior is required to make a safe classifier. **Requests should not be\n//! retried** if the server cannot safely handle the same request twice, or if\n//! it causes side effects.\n//!\n//! Some common properties to check include if the request method is\n//! idempotent, or if the response status code indicates a transient error.\n\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse tower::retry::budget::{Budget as _, TpsBudget as Budget};\n\n/// Builder to configure retries\n///\n/// Construct with [`for_host()`].\n#[derive(Debug)]\npub struct Builder {\n    //backoff: Backoff,\n    budget: Option<f32>,\n    classifier: classify::Classifier,\n    max_retries_per_request: u32,\n    scope: scope::Scoped,\n}\n\n/// The internal type that we convert the builder into, that implements\n/// tower::retry::Policy privately.\n#[derive(Clone, Debug)]\npub(crate) struct Policy {\n    budget: Option<Arc<Budget>>,\n    classifier: classify::Classifier,\n    max_retries_per_request: u32,\n    retry_cnt: u32,\n    scope: scope::Scoped,\n}\n\n//#[derive(Debug)]\n//struct Backoff;\n\n/// Create a retry builder with a request scope.\n///\n/// To provide a scope that isn't a closure, use the more general\n/// [`Builder::scoped()`].\npub fn for_host<S>(host: S) -> Builder\nwhere\n    S: for<'a> PartialEq<&'a str> + Send + Sync + 'static,\n{\n    scoped(move |req| host == req.uri().host().unwrap_or(\"\"))\n}\n\n/// Create a retry policy that will never retry any request.\n///\n/// This is useful for disabling the `Client`s default behavior of retrying\n/// protocol nacks.\npub fn never() -> Builder {\n    scoped(|_| false).no_budget()\n}\n\nfn scoped<F>(func: F) -> Builder\nwhere\n    F: Fn(&Req) -> bool + Send + Sync + 'static,\n{\n    Builder::scoped(scope::ScopeFn(func))\n}\n\n// ===== impl Builder =====\n\nimpl Builder {\n    /// Create a scoped retry policy.\n    ///\n    /// For a more convenient constructor, see [`for_host()`].\n    pub fn scoped(scope: impl scope::Scope) -> Self {\n        Self {\n            budget: Some(0.2),\n            classifier: classify::Classifier::Never,\n            max_retries_per_request: 2, // on top of the original\n            scope: scope::Scoped::Dyn(Arc::new(scope)),\n        }\n    }\n\n    /// Set no retry budget.\n    ///\n    /// Sets that no budget will be enforced. This could also be considered\n    /// to be an infinite budget.\n    ///\n    /// This is NOT recommended. Disabling the budget can make your system more\n    /// susceptible to retry storms.\n    pub fn no_budget(mut self) -> Self {\n        self.budget = None;\n        self\n    }\n\n    /// Sets the max extra load the budget will allow.\n    ///\n    /// Think of the amount of requests your client generates, and how much\n    /// load that puts on the server. This option configures as a percentage\n    /// how much extra load is allowed via retries.\n    ///\n    /// For example, if you send 1,000 requests per second, setting a maximum\n    /// extra load value of `0.3` would allow 300 more requests per second\n    /// in retries. A value of `2.5` would allow 2,500 more requests.\n    ///\n    /// # Panics\n    ///\n    /// The `extra_percent` value must be within reasonable values for a\n    /// percentage. This method will panic if it is less than `0.0`, or greater\n    /// than `1000.0`.\n    pub fn max_extra_load(mut self, extra_percent: f32) -> Self {\n        assert!(extra_percent >= 0.0);\n        assert!(extra_percent <= 1000.0);\n        self.budget = Some(extra_percent);\n        self\n    }\n\n    // pub fn max_replay_body\n\n    /// Set the max retries allowed per request.\n    ///\n    /// For each logical (initial) request, only retry up to `max` times.\n    ///\n    /// This value is used in combination with a token budget that is applied\n    /// to all requests. Even if the budget would allow more requests, this\n    /// limit will prevent. Likewise, the budget may prevent retrying up to\n    /// `max` times. This setting prevents a single request from consuming\n    /// the entire budget.\n    ///\n    /// Default is currently 2 retries.\n    pub fn max_retries_per_request(mut self, max: u32) -> Self {\n        self.max_retries_per_request = max;\n        self\n    }\n\n    /// Provide a classifier to determine if a request should be retried.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # fn with_builder(builder: reqwest::retry::Builder) -> reqwest::retry::Builder {\n    /// builder.classify_fn(|req_rep| {\n    ///     match (req_rep.method(), req_rep.status()) {\n    ///         (&http::Method::GET, Some(http::StatusCode::SERVICE_UNAVAILABLE)) => {\n    ///             req_rep.retryable()\n    ///         },\n    ///         _ => req_rep.success()\n    ///     }\n    /// })\n    /// # }\n    /// ```\n    pub fn classify_fn<F>(self, func: F) -> Self\n    where\n        F: Fn(classify::ReqRep<'_>) -> classify::Action + Send + Sync + 'static,\n    {\n        self.classify(classify::ClassifyFn(func))\n    }\n\n    /// Provide a classifier to determine if a request should be retried.\n    pub fn classify(mut self, classifier: impl classify::Classify) -> Self {\n        self.classifier = classify::Classifier::Dyn(Arc::new(classifier));\n        self\n    }\n\n    pub(crate) fn default() -> Builder {\n        Self {\n            // unscoped protocols nacks doesn't need a budget\n            budget: None,\n            classifier: classify::Classifier::ProtocolNacks,\n            max_retries_per_request: 2, // on top of the original\n            scope: scope::Scoped::Unscoped,\n        }\n    }\n\n    pub(crate) fn into_policy(self) -> Policy {\n        let budget = self\n            .budget\n            .map(|p| Arc::new(Budget::new(Duration::from_secs(10), 10, p)));\n        Policy {\n            budget,\n            classifier: self.classifier,\n            max_retries_per_request: self.max_retries_per_request,\n            retry_cnt: 0,\n            scope: self.scope,\n        }\n    }\n}\n\n// ===== internal ======\n\ntype Req = http::Request<crate::async_impl::body::Body>;\n\nimpl<B> tower::retry::Policy<Req, http::Response<B>, crate::Error> for Policy {\n    // TODO? backoff futures...\n    type Future = std::future::Ready<()>;\n\n    fn retry(\n        &mut self,\n        req: &mut Req,\n        result: &mut crate::Result<http::Response<B>>,\n    ) -> Option<Self::Future> {\n        match self.classifier.classify(req, result) {\n            classify::Action::Success => {\n                log::trace!(\"shouldn't retry!\");\n                if let Some(ref budget) = self.budget {\n                    budget.deposit();\n                }\n                None\n            }\n            classify::Action::Retryable => {\n                log::trace!(\"could retry!\");\n                if self.budget.as_ref().map(|b| b.withdraw()).unwrap_or(true) {\n                    self.retry_cnt += 1;\n                    Some(std::future::ready(()))\n                } else {\n                    log::debug!(\"retryable but could not withdraw from budget\");\n                    None\n                }\n            }\n        }\n    }\n\n    fn clone_request(&mut self, req: &Req) -> Option<Req> {\n        if self.retry_cnt > 0 && !self.scope.applies_to(req) {\n            return None;\n        }\n        if self.retry_cnt >= self.max_retries_per_request {\n            log::trace!(\"max_retries_per_request hit\");\n            return None;\n        }\n        let body = req.body().try_clone()?;\n        let mut new = http::Request::new(body);\n        *new.method_mut() = req.method().clone();\n        *new.uri_mut() = req.uri().clone();\n        *new.version_mut() = req.version();\n        *new.headers_mut() = req.headers().clone();\n        *new.extensions_mut() = req.extensions().clone();\n\n        Some(new)\n    }\n}\n\nfn is_retryable_error(err: &crate::Error) -> bool {\n    use std::error::Error as _;\n\n    // pop the reqwest::Error\n    let err = if let Some(err) = err.source() {\n        err\n    } else {\n        return false;\n    };\n    // pop the legacy::Error\n    let err = if let Some(err) = err.source() {\n        err\n    } else {\n        return false;\n    };\n\n    #[cfg(not(any(feature = \"http3\", feature = \"http2\")))]\n    let _err = err;\n\n    #[cfg(feature = \"http3\")]\n    if let Some(cause) = err.source() {\n        if let Some(err) = cause.downcast_ref::<h3::error::ConnectionError>() {\n            log::trace!(\"determining if HTTP/3 error {err} can be retried\");\n            // TODO: Does h3 provide an API for checking the error?\n            return err.to_string().as_str() == \"timeout\";\n        }\n    }\n\n    #[cfg(feature = \"http2\")]\n    if let Some(cause) = err.source() {\n        if let Some(err) = cause.downcast_ref::<h2::Error>() {\n            // They sent us a graceful shutdown, try with a new connection!\n            if err.is_go_away() && err.is_remote() && err.reason() == Some(h2::Reason::NO_ERROR) {\n                return true;\n            }\n\n            // REFUSED_STREAM was sent from the server, which is safe to retry.\n            // https://www.rfc-editor.org/rfc/rfc9113.html#section-8.7-3.2\n            if err.is_reset() && err.is_remote() && err.reason() == Some(h2::Reason::REFUSED_STREAM)\n            {\n                return true;\n            }\n        }\n    }\n    false\n}\n\n// sealed types and traits on purpose while exploring design space\nmod scope {\n    pub trait Scope: Send + Sync + 'static {\n        fn applies_to(&self, req: &super::Req) -> bool;\n    }\n\n    // I think scopes likely make the most sense being to hosts.\n    // If that's the case, then it should probably be easiest to check for\n    // the host. Perhaps also considering the ability to add more things\n    // to scope off in the future...\n\n    // For Future Whoever: making a blanket impl for any closure sounds nice,\n    // but it causes inference issues at the call site. Every closure would\n    // need to include `: ReqRep` in the arguments.\n    //\n    // An alternative is to make things like `ScopeFn`. Slightly more annoying,\n    // but also more forwards-compatible. :shrug:\n\n    pub struct ScopeFn<F>(pub(super) F);\n\n    impl<F> Scope for ScopeFn<F>\n    where\n        F: Fn(&super::Req) -> bool + Send + Sync + 'static,\n    {\n        fn applies_to(&self, req: &super::Req) -> bool {\n            (self.0)(req)\n        }\n    }\n\n    #[derive(Clone)]\n    pub(super) enum Scoped {\n        Unscoped,\n        Dyn(std::sync::Arc<dyn Scope>),\n    }\n\n    impl Scoped {\n        pub(super) fn applies_to(&self, req: &super::Req) -> bool {\n            let ret = match self {\n                Self::Unscoped => true,\n                Self::Dyn(s) => s.applies_to(req),\n            };\n            log::trace!(\"retry in scope: {ret}\");\n            ret\n        }\n    }\n\n    impl std::fmt::Debug for Scoped {\n        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n            match self {\n                Self::Unscoped => f.write_str(\"Unscoped\"),\n                Self::Dyn(_) => f.write_str(\"Scoped\"),\n            }\n        }\n    }\n}\n\n// sealed types and traits on purpose while exploring design space\nmod classify {\n    pub trait Classify: Send + Sync + 'static {\n        fn classify(&self, req_rep: ReqRep<'_>) -> Action;\n    }\n\n    // For Future Whoever: making a blanket impl for any closure sounds nice,\n    // but it causes inference issues at the call site. Every closure would\n    // need to include `: ReqRep` in the arguments.\n    //\n    // An alternative is to make things like `ClassifyFn`. Slightly more\n    // annoying, but also more forwards-compatible. :shrug:\n    pub struct ClassifyFn<F>(pub(super) F);\n\n    impl<F> Classify for ClassifyFn<F>\n    where\n        F: Fn(ReqRep<'_>) -> Action + Send + Sync + 'static,\n    {\n        fn classify(&self, req_rep: ReqRep<'_>) -> Action {\n            (self.0)(req_rep)\n        }\n    }\n\n    #[derive(Debug)]\n    pub struct ReqRep<'a>(&'a super::Req, Result<http::StatusCode, &'a crate::Error>);\n\n    impl ReqRep<'_> {\n        pub fn method(&self) -> &http::Method {\n            self.0.method()\n        }\n\n        pub fn uri(&self) -> &http::Uri {\n            self.0.uri()\n        }\n\n        pub fn status(&self) -> Option<http::StatusCode> {\n            self.1.ok()\n        }\n\n        pub fn error(&self) -> Option<&(dyn std::error::Error + 'static)> {\n            self.1.as_ref().err().map(|e| &**e as _)\n        }\n\n        pub fn retryable(self) -> Action {\n            Action::Retryable\n        }\n\n        pub fn success(self) -> Action {\n            Action::Success\n        }\n\n        fn is_protocol_nack(&self) -> bool {\n            self.1\n                .as_ref()\n                .err()\n                .map(|&e| super::is_retryable_error(e))\n                .unwrap_or(false)\n        }\n    }\n\n    #[must_use]\n    #[derive(Debug)]\n    pub enum Action {\n        Success,\n        Retryable,\n    }\n\n    #[derive(Clone)]\n    pub(super) enum Classifier {\n        Never,\n        ProtocolNacks,\n        Dyn(std::sync::Arc<dyn Classify>),\n    }\n\n    impl Classifier {\n        pub(super) fn classify<B>(\n            &self,\n            req: &super::Req,\n            res: &Result<http::Response<B>, crate::Error>,\n        ) -> Action {\n            let req_rep = ReqRep(req, res.as_ref().map(|r| r.status()));\n            match self {\n                Self::Never => Action::Success,\n                Self::ProtocolNacks => {\n                    if req_rep.is_protocol_nack() {\n                        Action::Retryable\n                    } else {\n                        Action::Success\n                    }\n                }\n                Self::Dyn(c) => c.classify(req_rep),\n            }\n        }\n    }\n\n    impl std::fmt::Debug for Classifier {\n        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n            match self {\n                Self::Never => f.write_str(\"Never\"),\n                Self::ProtocolNacks => f.write_str(\"ProtocolNacks\"),\n                Self::Dyn(_) => f.write_str(\"Classifier\"),\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/tls.rs",
    "content": "//! TLS configuration and types\n//!\n//! A `Client` will use transport layer security (TLS) by default to connect to\n//! HTTPS destinations.\n//!\n//! # Backends\n//!\n//! reqwest supports several TLS backends, enabled with Cargo features.\n//!\n//! ## default-tls\n//!\n//! reqwest will pick a TLS backend by default. This is true when the\n//! `default-tls` feature is enabled.\n//!\n//! While it currently uses `rustls`, the feature set is designed to only\n//! enable configuration that is shared among available backends. This allows\n//! reqwest to change the default to `native-tls` (or another) by configuration.\n//!\n//! <div class=\"warning\">This feature is enabled by default, and takes\n//! precedence if any other crate enables it. This is true even if you declare\n//! `features = []`. You must set `default-features = false` instead.</div>\n//!\n//! Since Cargo features are additive, other crates in your dependency tree can\n//! cause the default backend to be enabled. If you wish to ensure your\n//! `Client` uses a specific backend, call the appropriate builder methods\n//! (such as [`tls_backend_rustls()`][]).\n//!\n//! [`tls_backend_rustls()`]: crate::ClientBuilder::tls_backend_rustls()\n//!\n//! ## native-tls\n//!\n//! This backend uses the [native-tls][] crate. That will try to use the system\n//! TLS on Windows and Mac, and OpenSSL on Linux targets.\n//!\n//! Enabling the feature explicitly allows for `native-tls`-specific\n//! configuration options.\n//!\n//! [native-tls]: https://crates.io/crates/native-tls\n//!\n//! ## rustls\n//!\n//! This backend uses the [rustls][] crate, a TLS library written in Rust.\n//!\n//! [rustls]: https://crates.io/crates/rustls\n\n#[cfg(feature = \"__rustls\")]\nuse rustls::{\n    client::danger::HandshakeSignatureValid, client::danger::ServerCertVerified,\n    client::danger::ServerCertVerifier, crypto::WebPkiSupportedAlgorithms,\n    server::ParsedCertificate, DigitallySignedStruct, Error as TLSError, RootCertStore,\n    SignatureScheme,\n};\nuse rustls_pki_types::pem::PemObject;\n#[cfg(feature = \"__rustls\")]\nuse rustls_pki_types::{ServerName, UnixTime};\nuse std::{\n    fmt,\n    io::{BufRead, BufReader},\n};\n\n/// Represents a X509 certificate revocation list.\n#[cfg(feature = \"__rustls\")]\npub struct CertificateRevocationList {\n    #[cfg(feature = \"__rustls\")]\n    inner: rustls_pki_types::CertificateRevocationListDer<'static>,\n}\n\n/// Represents a server X509 certificate.\n#[derive(Clone)]\npub struct Certificate {\n    #[cfg(feature = \"__native-tls\")]\n    native: native_tls_crate::Certificate,\n    #[cfg(feature = \"__rustls\")]\n    original: Cert,\n}\n\n#[cfg(feature = \"__rustls\")]\n#[derive(Clone)]\nenum Cert {\n    Der(Vec<u8>),\n    Pem(Vec<u8>),\n}\n\n/// Represents a private key and X509 cert as a client certificate.\n#[derive(Clone)]\npub struct Identity {\n    #[cfg_attr(\n        not(any(feature = \"__native-tls\", feature = \"__rustls\")),\n        allow(unused)\n    )]\n    inner: ClientCert,\n}\n\nenum ClientCert {\n    #[cfg(feature = \"__native-tls\")]\n    Pkcs12(native_tls_crate::Identity),\n    #[cfg(feature = \"__native-tls\")]\n    Pkcs8(native_tls_crate::Identity),\n    #[cfg(feature = \"__rustls\")]\n    Pem {\n        key: rustls_pki_types::PrivateKeyDer<'static>,\n        certs: Vec<rustls_pki_types::CertificateDer<'static>>,\n    },\n}\n\nimpl Clone for ClientCert {\n    fn clone(&self) -> Self {\n        match self {\n            #[cfg(feature = \"__native-tls\")]\n            Self::Pkcs8(i) => Self::Pkcs8(i.clone()),\n            #[cfg(feature = \"__native-tls\")]\n            Self::Pkcs12(i) => Self::Pkcs12(i.clone()),\n            #[cfg(feature = \"__rustls\")]\n            ClientCert::Pem { key, certs } => ClientCert::Pem {\n                key: key.clone_key(),\n                certs: certs.clone(),\n            },\n            #[cfg_attr(\n                any(feature = \"__native-tls\", feature = \"__rustls\"),\n                allow(unreachable_patterns)\n            )]\n            _ => unreachable!(),\n        }\n    }\n}\n\nimpl Certificate {\n    /// Create a `Certificate` from a binary DER encoded certificate\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn cert() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"my_cert.der\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let cert = reqwest::Certificate::from_der(&buf)?;\n    /// # drop(cert);\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn from_der(der: &[u8]) -> crate::Result<Certificate> {\n        Ok(Certificate {\n            #[cfg(feature = \"__native-tls\")]\n            native: native_tls_crate::Certificate::from_der(der).map_err(crate::error::builder)?,\n            #[cfg(feature = \"__rustls\")]\n            original: Cert::Der(der.to_owned()),\n        })\n    }\n\n    /// Create a `Certificate` from a PEM encoded certificate\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn cert() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"my_cert.pem\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let cert = reqwest::Certificate::from_pem(&buf)?;\n    /// # drop(cert);\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn from_pem(pem: &[u8]) -> crate::Result<Certificate> {\n        Ok(Certificate {\n            #[cfg(feature = \"__native-tls\")]\n            native: native_tls_crate::Certificate::from_pem(pem).map_err(crate::error::builder)?,\n            #[cfg(feature = \"__rustls\")]\n            original: Cert::Pem(pem.to_owned()),\n        })\n    }\n\n    /// Create a collection of `Certificate`s from a PEM encoded certificate bundle.\n    /// Example byte sources may be `.crt`, `.cer` or `.pem` files.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn cert() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"ca-bundle.crt\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let certs = reqwest::Certificate::from_pem_bundle(&buf)?;\n    /// # drop(certs);\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<Certificate>> {\n        let mut reader = BufReader::new(pem_bundle);\n\n        Self::read_pem_certs(&mut reader)?\n            .iter()\n            .map(|cert_vec| Certificate::from_der(cert_vec))\n            .collect::<crate::Result<Vec<Certificate>>>()\n    }\n\n    /*\n    #[cfg(feature = \"rustls\")]\n    pub fn from_trust_anchor() -> Self {\n\n    }\n    */\n\n    #[cfg(feature = \"__native-tls\")]\n    pub(crate) fn add_to_native_tls(self, tls: &mut native_tls_crate::TlsConnectorBuilder) {\n        tls.add_root_certificate(self.native);\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    pub(crate) fn add_to_rustls(\n        self,\n        root_cert_store: &mut rustls::RootCertStore,\n    ) -> crate::Result<()> {\n        use std::io::Cursor;\n\n        match self.original {\n            Cert::Der(buf) => root_cert_store\n                .add(buf.into())\n                .map_err(crate::error::builder)?,\n            Cert::Pem(buf) => {\n                let mut reader = Cursor::new(buf);\n                let certs = Self::read_pem_certs(&mut reader)?;\n                for c in certs {\n                    root_cert_store\n                        .add(c.into())\n                        .map_err(crate::error::builder)?;\n                }\n            }\n        }\n        Ok(())\n    }\n\n    fn read_pem_certs(reader: &mut impl BufRead) -> crate::Result<Vec<Vec<u8>>> {\n        rustls_pki_types::CertificateDer::pem_reader_iter(reader)\n            .map(|result| match result {\n                Ok(cert) => Ok(cert.as_ref().to_vec()),\n                Err(_) => Err(crate::error::builder(\"invalid certificate encoding\")),\n            })\n            .collect()\n    }\n}\n\nimpl Identity {\n    /// Parses a DER-formatted PKCS #12 archive, using the specified password to decrypt the key.\n    ///\n    /// The archive should contain a leaf certificate and its private key, as well any intermediate\n    /// certificates that allow clients to build a chain to a trusted root.\n    /// The chain certificates should be in order from the leaf certificate towards the root.\n    ///\n    /// PKCS #12 archives typically have the file extension `.p12` or `.pfx`, and can be created\n    /// with the OpenSSL `pkcs12` tool:\n    ///\n    /// ```bash\n    /// openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem -certfile chain_certs.pem\n    /// ```\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn pkcs12() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"my-ident.pfx\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let pkcs12 = reqwest::Identity::from_pkcs12_der(&buf, \"my-privkey-password\")?;\n    /// # drop(pkcs12);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `native-tls` Cargo feature enabled.\n    #[cfg(feature = \"__native-tls\")]\n    pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> {\n        Ok(Identity {\n            inner: ClientCert::Pkcs12(\n                native_tls_crate::Identity::from_pkcs12(der, password)\n                    .map_err(crate::error::builder)?,\n            ),\n        })\n    }\n\n    /// Parses a chain of PEM encoded X509 certificates, with the leaf certificate first.\n    /// `key` is a PEM encoded PKCS #8 formatted private key for the leaf certificate.\n    ///\n    /// The certificate chain should contain any intermediate certificates that should be sent to\n    /// clients to allow them to build a chain to a trusted root.\n    ///\n    /// A certificate chain here means a series of PEM encoded certificates concatenated together.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs;\n    /// # fn pkcs8() -> Result<(), Box<dyn std::error::Error>> {\n    /// let cert = fs::read(\"client.pem\")?;\n    /// let key = fs::read(\"key.pem\")?;\n    /// let pkcs8 = reqwest::Identity::from_pkcs8_pem(&cert, &key)?;\n    /// # drop(pkcs8);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `native-tls` Cargo feature enabled.\n    #[cfg(feature = \"__native-tls\")]\n    pub fn from_pkcs8_pem(pem: &[u8], key: &[u8]) -> crate::Result<Identity> {\n        Ok(Identity {\n            inner: ClientCert::Pkcs8(\n                native_tls_crate::Identity::from_pkcs8(pem, key).map_err(crate::error::builder)?,\n            ),\n        })\n    }\n\n    /// Parses PEM encoded private key and certificate.\n    ///\n    /// The input should contain a PEM encoded private key\n    /// and at least one PEM encoded certificate.\n    ///\n    /// Note: The private key must be in RSA, SEC1 Elliptic Curve or PKCS#8 format.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn pem() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"my-ident.pem\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let id = reqwest::Identity::from_pem(&buf)?;\n    /// # drop(id);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `rustls(-...)` Cargo feature enabled.\n    #[cfg(feature = \"__rustls\")]\n    pub fn from_pem(buf: &[u8]) -> crate::Result<Identity> {\n        use rustls_pki_types::{pem::SectionKind, PrivateKeyDer};\n        use std::io::Cursor;\n\n        let (key, certs) = {\n            let mut pem = Cursor::new(buf);\n            let mut sk = Vec::<rustls_pki_types::PrivateKeyDer>::new();\n            let mut certs = Vec::<rustls_pki_types::CertificateDer>::new();\n\n            while let Some((kind, data)) =\n                rustls_pki_types::pem::from_buf(&mut pem).map_err(|_| {\n                    crate::error::builder(TLSError::General(String::from(\n                        \"Invalid identity PEM file\",\n                    )))\n                })?\n            {\n                match kind {\n                    SectionKind::Certificate => certs.push(data.into()),\n                    SectionKind::PrivateKey => sk.push(PrivateKeyDer::Pkcs8(data.into())),\n                    SectionKind::RsaPrivateKey => sk.push(PrivateKeyDer::Pkcs1(data.into())),\n                    SectionKind::EcPrivateKey => sk.push(PrivateKeyDer::Sec1(data.into())),\n                    _ => {\n                        return Err(crate::error::builder(TLSError::General(String::from(\n                            \"No valid certificate was found\",\n                        ))))\n                    }\n                }\n            }\n\n            if let (Some(sk), false) = (sk.pop(), certs.is_empty()) {\n                (sk, certs)\n            } else {\n                return Err(crate::error::builder(TLSError::General(String::from(\n                    \"private key or certificate not found\",\n                ))));\n            }\n        };\n\n        Ok(Identity {\n            inner: ClientCert::Pem { key, certs },\n        })\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    pub(crate) fn add_to_native_tls(\n        self,\n        tls: &mut native_tls_crate::TlsConnectorBuilder,\n    ) -> crate::Result<()> {\n        match self.inner {\n            ClientCert::Pkcs12(id) | ClientCert::Pkcs8(id) => {\n                tls.identity(id);\n                Ok(())\n            }\n            #[cfg(feature = \"__rustls\")]\n            ClientCert::Pem { .. } => Err(crate::error::builder(\"incompatible TLS identity type\")),\n        }\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    pub(crate) fn add_to_rustls(\n        self,\n        config_builder: rustls::ConfigBuilder<\n            rustls::ClientConfig,\n            // Not sure here\n            rustls::client::WantsClientCert,\n        >,\n    ) -> crate::Result<rustls::ClientConfig> {\n        match self.inner {\n            ClientCert::Pem { key, certs } => config_builder\n                .with_client_auth_cert(certs, key)\n                .map_err(crate::error::builder),\n            #[cfg(feature = \"__native-tls\")]\n            ClientCert::Pkcs12(..) | ClientCert::Pkcs8(..) => {\n                Err(crate::error::builder(\"incompatible TLS identity type\"))\n            }\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl CertificateRevocationList {\n    /// Parses a PEM encoded CRL.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn crl() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"my_crl.pem\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let crl = reqwest::tls::CertificateRevocationList::from_pem(&buf)?;\n    /// # drop(crl);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `rustls(-...)` Cargo feature enabled.\n    #[cfg(feature = \"__rustls\")]\n    pub fn from_pem(pem: &[u8]) -> crate::Result<CertificateRevocationList> {\n        Ok(CertificateRevocationList {\n            #[cfg(feature = \"__rustls\")]\n            inner: rustls_pki_types::CertificateRevocationListDer::from(pem.to_vec()),\n        })\n    }\n\n    /// Creates a collection of `CertificateRevocationList`s from a PEM encoded CRL bundle.\n    /// Example byte sources may be `.crl` or `.pem` files.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use std::fs::File;\n    /// # use std::io::Read;\n    /// # fn crls() -> Result<(), Box<dyn std::error::Error>> {\n    /// let mut buf = Vec::new();\n    /// File::open(\"crl-bundle.crl\")?\n    ///     .read_to_end(&mut buf)?;\n    /// let crls = reqwest::tls::CertificateRevocationList::from_pem_bundle(&buf)?;\n    /// # drop(crls);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Optional\n    ///\n    /// This requires the `rustls(-...)` Cargo feature enabled.\n    #[cfg(feature = \"__rustls\")]\n    pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<CertificateRevocationList>> {\n        rustls_pki_types::CertificateRevocationListDer::pem_slice_iter(pem_bundle)\n            .map(|result| match result {\n                Ok(crl) => Ok(CertificateRevocationList { inner: crl }),\n                Err(_) => Err(crate::error::builder(\"invalid crl encoding\")),\n            })\n            .collect::<crate::Result<Vec<CertificateRevocationList>>>()\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    pub(crate) fn as_rustls_crl<'a>(&self) -> rustls_pki_types::CertificateRevocationListDer<'a> {\n        self.inner.clone()\n    }\n}\n\nimpl fmt::Debug for Certificate {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Certificate\").finish()\n    }\n}\n\nimpl fmt::Debug for Identity {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Identity\").finish()\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl fmt::Debug for CertificateRevocationList {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"CertificateRevocationList\").finish()\n    }\n}\n\n/// A TLS protocol version.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]\npub struct Version(InnerVersion);\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]\n#[non_exhaustive]\nenum InnerVersion {\n    Tls1_0,\n    Tls1_1,\n    Tls1_2,\n    Tls1_3,\n}\n\n// These could perhaps be From/TryFrom implementations, but those would be\n// part of the public API so let's be careful\nimpl Version {\n    /// Version 1.0 of the TLS protocol.\n    pub const TLS_1_0: Version = Version(InnerVersion::Tls1_0);\n    /// Version 1.1 of the TLS protocol.\n    pub const TLS_1_1: Version = Version(InnerVersion::Tls1_1);\n    /// Version 1.2 of the TLS protocol.\n    pub const TLS_1_2: Version = Version(InnerVersion::Tls1_2);\n    /// Version 1.3 of the TLS protocol.\n    pub const TLS_1_3: Version = Version(InnerVersion::Tls1_3);\n\n    #[cfg(feature = \"__native-tls\")]\n    pub(crate) fn to_native_tls(self) -> Option<native_tls_crate::Protocol> {\n        match self.0 {\n            InnerVersion::Tls1_0 => Some(native_tls_crate::Protocol::Tlsv10),\n            InnerVersion::Tls1_1 => Some(native_tls_crate::Protocol::Tlsv11),\n            InnerVersion::Tls1_2 => Some(native_tls_crate::Protocol::Tlsv12),\n            InnerVersion::Tls1_3 => None,\n        }\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    pub(crate) fn from_rustls(version: rustls::ProtocolVersion) -> Option<Self> {\n        match version {\n            rustls::ProtocolVersion::SSLv2 => None,\n            rustls::ProtocolVersion::SSLv3 => None,\n            rustls::ProtocolVersion::TLSv1_0 => Some(Self(InnerVersion::Tls1_0)),\n            rustls::ProtocolVersion::TLSv1_1 => Some(Self(InnerVersion::Tls1_1)),\n            rustls::ProtocolVersion::TLSv1_2 => Some(Self(InnerVersion::Tls1_2)),\n            rustls::ProtocolVersion::TLSv1_3 => Some(Self(InnerVersion::Tls1_3)),\n            _ => None,\n        }\n    }\n}\n\npub(crate) enum TlsBackend {\n    // This is the default and HTTP/3 feature does not use it so suppress it.\n    #[allow(dead_code)]\n    #[cfg(feature = \"__native-tls\")]\n    NativeTls,\n    #[cfg(feature = \"__native-tls\")]\n    BuiltNativeTls(native_tls_crate::TlsConnector),\n    #[cfg(feature = \"__rustls\")]\n    Rustls,\n    #[cfg(feature = \"__rustls\")]\n    BuiltRustls(rustls::ClientConfig),\n    #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n    UnknownPreconfigured,\n}\n\nimpl fmt::Debug for TlsBackend {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            #[cfg(feature = \"__native-tls\")]\n            TlsBackend::NativeTls => write!(f, \"NativeTls\"),\n            #[cfg(feature = \"__native-tls\")]\n            TlsBackend::BuiltNativeTls(_) => write!(f, \"BuiltNativeTls\"),\n            #[cfg(feature = \"__rustls\")]\n            TlsBackend::Rustls => write!(f, \"Rustls\"),\n            #[cfg(feature = \"__rustls\")]\n            TlsBackend::BuiltRustls(_) => write!(f, \"BuiltRustls\"),\n            #[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n            TlsBackend::UnknownPreconfigured => write!(f, \"UnknownPreconfigured\"),\n        }\n    }\n}\n\n#[allow(clippy::derivable_impls)]\nimpl Default for TlsBackend {\n    fn default() -> TlsBackend {\n        #[cfg(any(\n            all(feature = \"__rustls\", not(feature = \"__native-tls\")),\n            feature = \"http3\"\n        ))]\n        {\n            TlsBackend::Rustls\n        }\n\n        #[cfg(all(feature = \"__native-tls\", not(feature = \"http3\")))]\n        {\n            TlsBackend::NativeTls\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\npub(crate) fn rustls_store(certs: Vec<Certificate>) -> crate::Result<RootCertStore> {\n    let mut root_cert_store = rustls::RootCertStore::empty();\n    for cert in certs {\n        cert.add_to_rustls(&mut root_cert_store)?;\n    }\n    Ok(root_cert_store)\n}\n\n#[cfg(feature = \"__rustls\")]\n#[cfg(any(all(unix, not(target_os = \"android\")), target_os = \"windows\"))]\npub(crate) fn rustls_der(\n    certs: Vec<Certificate>,\n) -> crate::Result<Vec<rustls_pki_types::CertificateDer<'static>>> {\n    let mut ders = Vec::with_capacity(certs.len());\n    for cert in certs {\n        match cert.original {\n            Cert::Der(buf) => ders.push(buf.into()),\n            Cert::Pem(buf) => {\n                let mut reader = std::io::Cursor::new(buf);\n                let pems = Certificate::read_pem_certs(&mut reader)?;\n                for c in pems {\n                    ders.push(c.into());\n                }\n            }\n        }\n    }\n    Ok(ders)\n}\n\n#[cfg(feature = \"__rustls\")]\n#[derive(Debug)]\npub(crate) struct NoVerifier;\n\n#[cfg(feature = \"__rustls\")]\nimpl ServerCertVerifier for NoVerifier {\n    fn verify_server_cert(\n        &self,\n        _end_entity: &rustls_pki_types::CertificateDer,\n        _intermediates: &[rustls_pki_types::CertificateDer],\n        _server_name: &ServerName,\n        _ocsp_response: &[u8],\n        _now: UnixTime,\n    ) -> Result<ServerCertVerified, TLSError> {\n        Ok(ServerCertVerified::assertion())\n    }\n\n    fn verify_tls12_signature(\n        &self,\n        _message: &[u8],\n        _cert: &rustls_pki_types::CertificateDer,\n        _dss: &DigitallySignedStruct,\n    ) -> Result<HandshakeSignatureValid, TLSError> {\n        Ok(HandshakeSignatureValid::assertion())\n    }\n\n    fn verify_tls13_signature(\n        &self,\n        _message: &[u8],\n        _cert: &rustls_pki_types::CertificateDer,\n        _dss: &DigitallySignedStruct,\n    ) -> Result<HandshakeSignatureValid, TLSError> {\n        Ok(HandshakeSignatureValid::assertion())\n    }\n\n    fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {\n        vec![\n            SignatureScheme::RSA_PKCS1_SHA1,\n            SignatureScheme::ECDSA_SHA1_Legacy,\n            SignatureScheme::RSA_PKCS1_SHA256,\n            SignatureScheme::ECDSA_NISTP256_SHA256,\n            SignatureScheme::RSA_PKCS1_SHA384,\n            SignatureScheme::ECDSA_NISTP384_SHA384,\n            SignatureScheme::RSA_PKCS1_SHA512,\n            SignatureScheme::ECDSA_NISTP521_SHA512,\n            SignatureScheme::RSA_PSS_SHA256,\n            SignatureScheme::RSA_PSS_SHA384,\n            SignatureScheme::RSA_PSS_SHA512,\n            SignatureScheme::ED25519,\n            SignatureScheme::ED448,\n        ]\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\n#[derive(Debug)]\npub(crate) struct IgnoreHostname {\n    roots: RootCertStore,\n    signature_algorithms: WebPkiSupportedAlgorithms,\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl IgnoreHostname {\n    pub(crate) fn new(\n        roots: RootCertStore,\n        signature_algorithms: WebPkiSupportedAlgorithms,\n    ) -> Self {\n        Self {\n            roots,\n            signature_algorithms,\n        }\n    }\n}\n\n#[cfg(feature = \"__rustls\")]\nimpl ServerCertVerifier for IgnoreHostname {\n    fn verify_server_cert(\n        &self,\n        end_entity: &rustls_pki_types::CertificateDer<'_>,\n        intermediates: &[rustls_pki_types::CertificateDer<'_>],\n        _server_name: &ServerName<'_>,\n        _ocsp_response: &[u8],\n        now: UnixTime,\n    ) -> Result<ServerCertVerified, TLSError> {\n        let cert = ParsedCertificate::try_from(end_entity)?;\n\n        rustls::client::verify_server_cert_signed_by_trust_anchor(\n            &cert,\n            &self.roots,\n            intermediates,\n            now,\n            self.signature_algorithms.all,\n        )?;\n        Ok(ServerCertVerified::assertion())\n    }\n\n    fn verify_tls12_signature(\n        &self,\n        message: &[u8],\n        cert: &rustls_pki_types::CertificateDer<'_>,\n        dss: &DigitallySignedStruct,\n    ) -> Result<HandshakeSignatureValid, TLSError> {\n        rustls::crypto::verify_tls12_signature(message, cert, dss, &self.signature_algorithms)\n    }\n\n    fn verify_tls13_signature(\n        &self,\n        message: &[u8],\n        cert: &rustls_pki_types::CertificateDer<'_>,\n        dss: &DigitallySignedStruct,\n    ) -> Result<HandshakeSignatureValid, TLSError> {\n        rustls::crypto::verify_tls13_signature(message, cert, dss, &self.signature_algorithms)\n    }\n\n    fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {\n        self.signature_algorithms.supported_schemes()\n    }\n}\n\n/// Hyper extension carrying extra TLS layer information.\n/// Made available to clients on responses when `tls_info` is set.\n#[derive(Clone)]\npub struct TlsInfo {\n    pub(crate) peer_certificate: Option<Vec<u8>>,\n}\n\nimpl TlsInfo {\n    /// Get the DER encoded leaf certificate of the peer.\n    pub fn peer_certificate(&self) -> Option<&[u8]> {\n        self.peer_certificate.as_ref().map(|der| &der[..])\n    }\n}\n\nimpl std::fmt::Debug for TlsInfo {\n    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n        f.debug_struct(\"TlsInfo\").finish()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[cfg(feature = \"__native-tls\")]\n    #[test]\n    fn certificate_from_der_invalid() {\n        Certificate::from_der(b\"not der\").unwrap_err();\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    #[test]\n    fn certificate_from_pem_invalid() {\n        Certificate::from_pem(b\"not pem\").unwrap_err();\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    #[test]\n    fn identity_from_pkcs12_der_invalid() {\n        Identity::from_pkcs12_der(b\"not der\", \"nope\").unwrap_err();\n    }\n\n    #[cfg(feature = \"__native-tls\")]\n    #[test]\n    fn identity_from_pkcs8_pem_invalid() {\n        Identity::from_pkcs8_pem(b\"not pem\", b\"not key\").unwrap_err();\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    #[test]\n    fn identity_from_pem_invalid() {\n        Identity::from_pem(b\"not pem\").unwrap_err();\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    #[test]\n    fn identity_from_pem_pkcs1_key() {\n        let pem = b\"-----BEGIN CERTIFICATE-----\\n\\\n            -----END CERTIFICATE-----\\n\\\n            -----BEGIN RSA PRIVATE KEY-----\\n\\\n            -----END RSA PRIVATE KEY-----\\n\";\n\n        Identity::from_pem(pem).unwrap();\n    }\n\n    #[test]\n    fn certificates_from_pem_bundle() {\n        const PEM_BUNDLE: &[u8] = b\"\n            -----BEGIN CERTIFICATE-----\n            MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n            MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n            Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n            A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n            Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n            ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n            QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n            ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n            BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n            YyRIHN8wfdVoOw==\n            -----END CERTIFICATE-----\n\n            -----BEGIN CERTIFICATE-----\n            MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n            MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n            Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n            A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n            Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n            9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n            M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n            /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n            MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n            CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n            1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n            -----END CERTIFICATE-----\n        \";\n\n        assert!(Certificate::from_pem_bundle(PEM_BUNDLE).is_ok())\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    #[test]\n    fn crl_from_pem() {\n        let pem = b\"-----BEGIN X509 CRL-----\\n-----END X509 CRL-----\\n\";\n\n        CertificateRevocationList::from_pem(pem).unwrap();\n    }\n\n    #[cfg(feature = \"__rustls\")]\n    #[test]\n    fn crl_from_pem_bundle() {\n        let pem_bundle = std::fs::read(\"tests/support/crl.pem\").unwrap();\n\n        let result = CertificateRevocationList::from_pem_bundle(&pem_bundle);\n\n        assert!(result.is_ok());\n        let result = result.unwrap();\n        assert_eq!(result.len(), 1);\n    }\n}\n"
  },
  {
    "path": "src/util.rs",
    "content": "use crate::header::{Entry, HeaderMap, HeaderValue, OccupiedEntry};\nuse std::fmt;\n\npub fn basic_auth<U, P>(username: U, password: Option<P>) -> HeaderValue\nwhere\n    U: fmt::Display,\n    P: fmt::Display,\n{\n    use base64::prelude::BASE64_STANDARD;\n    use base64::write::EncoderWriter;\n    use std::io::Write;\n\n    let mut buf = b\"Basic \".to_vec();\n    {\n        let mut encoder = EncoderWriter::new(&mut buf, &BASE64_STANDARD);\n        let _ = write!(encoder, \"{username}:\");\n        if let Some(password) = password {\n            let _ = write!(encoder, \"{password}\");\n        }\n    }\n    let mut header = HeaderValue::from_maybe_shared(bytes::Bytes::from(buf))\n        .expect(\"base64 is always valid HeaderValue\");\n    header.set_sensitive(true);\n    header\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\npub(crate) fn fast_random() -> u64 {\n    use std::cell::Cell;\n    use std::collections::hash_map::RandomState;\n    use std::hash::{BuildHasher, Hasher};\n\n    thread_local! {\n        static KEY: RandomState = RandomState::new();\n        static COUNTER: Cell<u64> = Cell::new(0);\n    }\n\n    KEY.with(|key| {\n        COUNTER.with(|ctr| {\n            let n = ctr.get().wrapping_add(1);\n            ctr.set(n);\n\n            let mut h = key.build_hasher();\n            h.write_u64(n);\n            h.finish()\n        })\n    })\n}\n\npub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) {\n    // IntoIter of HeaderMap yields (Option<HeaderName>, HeaderValue).\n    // The first time a name is yielded, it will be Some(name), and if\n    // there are more values with the same name, the next yield will be\n    // None.\n\n    let mut prev_entry: Option<OccupiedEntry<_>> = None;\n    for (key, value) in src {\n        match key {\n            Some(key) => match dst.entry(key) {\n                Entry::Occupied(mut e) => {\n                    e.insert(value);\n                    prev_entry = Some(e);\n                }\n                Entry::Vacant(e) => {\n                    let e = e.insert_entry(value);\n                    prev_entry = Some(e);\n                }\n            },\n            None => match prev_entry {\n                Some(ref mut entry) => {\n                    entry.append(value);\n                }\n                None => unreachable!(\"HeaderMap::into_iter yielded None first\"),\n            },\n        }\n    }\n}\n\n#[cfg(feature = \"cookies\")]\n#[cfg(not(target_arch = \"wasm32\"))]\npub(crate) fn add_cookie_header(\n    headers: &mut HeaderMap,\n    cookie_store: &dyn crate::cookie::CookieStore,\n    url: &url::Url,\n) {\n    if let Some(header) = cookie_store.cookies(url) {\n        headers.insert(crate::header::COOKIE, header);\n    }\n}\n\npub(crate) struct Escape<'a>(&'a [u8]);\n\n#[cfg(not(target_arch = \"wasm32\"))]\nimpl<'a> Escape<'a> {\n    pub(crate) fn new(bytes: &'a [u8]) -> Self {\n        Escape(bytes)\n    }\n}\n\nimpl fmt::Debug for Escape<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"b\\\"{}\\\"\", self)?;\n        Ok(())\n    }\n}\n\nimpl fmt::Display for Escape<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        for &c in self.0 {\n            // https://doc.rust-lang.org/reference/tokens.html#byte-escapes\n            if c == b'\\n' {\n                write!(f, \"\\\\n\")?;\n            } else if c == b'\\r' {\n                write!(f, \"\\\\r\")?;\n            } else if c == b'\\t' {\n                write!(f, \"\\\\t\")?;\n            } else if c == b'\\\\' || c == b'\"' {\n                write!(f, \"\\\\{}\", c as char)?;\n            } else if c == b'\\0' {\n                write!(f, \"\\\\0\")?;\n            // ASCII printable\n            } else if c >= 0x20 && c < 0x7f {\n                write!(f, \"{}\", c as char)?;\n            } else {\n                write!(f, \"\\\\x{c:02x}\")?;\n            }\n        }\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/wasm/body.rs",
    "content": "#[cfg(feature = \"multipart\")]\nuse super::multipart::Form;\n/// dox\nuse bytes::Bytes;\nuse js_sys::Uint8Array;\nuse std::{borrow::Cow, fmt};\nuse wasm_bindgen::JsValue;\n\n/// The body of a `Request`.\n///\n/// In most cases, this is not needed directly, as the\n/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows\n/// passing many things (like a string or vector of bytes).\n///\n/// [builder]: ./struct.RequestBuilder.html#method.body\npub struct Body {\n    inner: Inner,\n}\n\nenum Inner {\n    Single(Single),\n    /// MultipartForm holds a multipart/form-data body.\n    #[cfg(feature = \"multipart\")]\n    MultipartForm(Form),\n}\n\n#[derive(Clone)]\npub(crate) enum Single {\n    Bytes(Bytes),\n    Text(Cow<'static, str>),\n}\n\nimpl Single {\n    fn as_bytes(&self) -> &[u8] {\n        match self {\n            Single::Bytes(bytes) => bytes.as_ref(),\n            Single::Text(text) => text.as_bytes(),\n        }\n    }\n\n    pub(crate) fn to_js_value(&self) -> JsValue {\n        match self {\n            Single::Bytes(bytes) => {\n                let body_bytes: &[u8] = bytes.as_ref();\n                let body_uint8_array: Uint8Array = body_bytes.into();\n                let js_value: &JsValue = body_uint8_array.as_ref();\n                js_value.to_owned()\n            }\n            Single::Text(text) => JsValue::from_str(text),\n        }\n    }\n\n    fn is_empty(&self) -> bool {\n        match self {\n            Single::Bytes(bytes) => bytes.is_empty(),\n            Single::Text(text) => text.is_empty(),\n        }\n    }\n}\n\nimpl Body {\n    /// Returns a reference to the internal data of the `Body`.\n    ///\n    /// `None` is returned, if the underlying data is a multipart form.\n    #[inline]\n    pub fn as_bytes(&self) -> Option<&[u8]> {\n        match &self.inner {\n            Inner::Single(single) => Some(single.as_bytes()),\n            #[cfg(feature = \"multipart\")]\n            Inner::MultipartForm(_) => None,\n        }\n    }\n\n    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {\n        match &self.inner {\n            Inner::Single(single) => Ok(single.to_js_value()),\n            #[cfg(feature = \"multipart\")]\n            Inner::MultipartForm(form) => {\n                let form_data = form.to_form_data()?;\n                let js_value: &JsValue = form_data.as_ref();\n                Ok(js_value.to_owned())\n            }\n        }\n    }\n\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn as_single(&self) -> Option<&Single> {\n        match &self.inner {\n            Inner::Single(single) => Some(single),\n            Inner::MultipartForm(_) => None,\n        }\n    }\n\n    #[inline]\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn from_form(f: Form) -> Body {\n        Self {\n            inner: Inner::MultipartForm(f),\n        }\n    }\n\n    /// into_part turns a regular body into the body of a multipart/form-data part.\n    #[cfg(feature = \"multipart\")]\n    pub(crate) fn into_part(self) -> Body {\n        match self.inner {\n            Inner::Single(single) => Self {\n                inner: Inner::Single(single),\n            },\n            Inner::MultipartForm(form) => Self {\n                inner: Inner::MultipartForm(form),\n            },\n        }\n    }\n\n    pub(crate) fn is_empty(&self) -> bool {\n        match &self.inner {\n            Inner::Single(single) => single.is_empty(),\n            #[cfg(feature = \"multipart\")]\n            Inner::MultipartForm(form) => form.is_empty(),\n        }\n    }\n\n    pub(crate) fn try_clone(&self) -> Option<Body> {\n        match &self.inner {\n            Inner::Single(single) => Some(Self {\n                inner: Inner::Single(single.clone()),\n            }),\n            #[cfg(feature = \"multipart\")]\n            Inner::MultipartForm(_) => None,\n        }\n    }\n}\n\nimpl From<Bytes> for Body {\n    #[inline]\n    fn from(bytes: Bytes) -> Body {\n        Body {\n            inner: Inner::Single(Single::Bytes(bytes)),\n        }\n    }\n}\n\nimpl From<Vec<u8>> for Body {\n    #[inline]\n    fn from(vec: Vec<u8>) -> Body {\n        Body {\n            inner: Inner::Single(Single::Bytes(vec.into())),\n        }\n    }\n}\n\nimpl From<&'static [u8]> for Body {\n    #[inline]\n    fn from(s: &'static [u8]) -> Body {\n        Body {\n            inner: Inner::Single(Single::Bytes(Bytes::from_static(s))),\n        }\n    }\n}\n\nimpl From<String> for Body {\n    #[inline]\n    fn from(s: String) -> Body {\n        Body {\n            inner: Inner::Single(Single::Text(s.into())),\n        }\n    }\n}\n\nimpl From<&'static str> for Body {\n    #[inline]\n    fn from(s: &'static str) -> Body {\n        Body {\n            inner: Inner::Single(Single::Text(s.into())),\n        }\n    }\n}\n\nimpl fmt::Debug for Body {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Body\").finish()\n    }\n}\n\nimpl Default for Body {\n    fn default() -> Body {\n        Body {\n            inner: Inner::Single(Single::Bytes(Bytes::new())),\n        }\n    }\n}\n\n// Can use new methods in web-sys when requiring v0.2.93.\n// > `init.method(m)` to `init.set_method(m)`\n// For now, ignore their deprecation.\n#[allow(deprecated)]\n#[cfg(test)]\nmod tests {\n    use crate::Body;\n    use js_sys::Uint8Array;\n    use wasm_bindgen::prelude::*;\n    use wasm_bindgen_test::*;\n\n    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);\n\n    #[wasm_bindgen]\n    extern \"C\" {\n        // Use `js_namespace` here to bind `console.log(..)` instead of just\n        // `log(..)`\n        #[wasm_bindgen(js_namespace = console)]\n        fn log(s: String);\n    }\n\n    #[wasm_bindgen_test]\n    async fn test_body() {\n        let body = Body::from(\"TEST\");\n        assert_eq!([84, 69, 83, 84], body.as_bytes().unwrap());\n    }\n\n    #[wasm_bindgen_test]\n    async fn test_body_js_static_str() {\n        let body_value = \"TEST\";\n        let body = Body::from(body_value);\n\n        let mut init = web_sys::RequestInit::new();\n        init.method(\"POST\");\n        init.body(Some(\n            body.to_js_value()\n                .expect(\"could not convert body to JsValue\")\n                .as_ref(),\n        ));\n\n        let js_req = web_sys::Request::new_with_str_and_init(\"\", &init)\n            .expect(\"could not create JS request\");\n        let text_promise = js_req.text().expect(\"could not get text promise\");\n        let text = crate::wasm::promise::<JsValue>(text_promise)\n            .await\n            .expect(\"could not get request body as text\");\n\n        assert_eq!(text.as_string().expect(\"text is not a string\"), body_value);\n    }\n    #[wasm_bindgen_test]\n    async fn test_body_js_string() {\n        let body_value = \"TEST\".to_string();\n        let body = Body::from(body_value.clone());\n\n        let mut init = web_sys::RequestInit::new();\n        init.method(\"POST\");\n        init.body(Some(\n            body.to_js_value()\n                .expect(\"could not convert body to JsValue\")\n                .as_ref(),\n        ));\n\n        let js_req = web_sys::Request::new_with_str_and_init(\"\", &init)\n            .expect(\"could not create JS request\");\n        let text_promise = js_req.text().expect(\"could not get text promise\");\n        let text = crate::wasm::promise::<JsValue>(text_promise)\n            .await\n            .expect(\"could not get request body as text\");\n\n        assert_eq!(text.as_string().expect(\"text is not a string\"), body_value);\n    }\n\n    #[wasm_bindgen_test]\n    async fn test_body_js_static_u8_slice() {\n        let body_value: &'static [u8] = b\"\\x00\\x42\";\n        let body = Body::from(body_value);\n\n        let mut init = web_sys::RequestInit::new();\n        init.method(\"POST\");\n        init.body(Some(\n            body.to_js_value()\n                .expect(\"could not convert body to JsValue\")\n                .as_ref(),\n        ));\n\n        let js_req = web_sys::Request::new_with_str_and_init(\"\", &init)\n            .expect(\"could not create JS request\");\n\n        let array_buffer_promise = js_req\n            .array_buffer()\n            .expect(\"could not get array_buffer promise\");\n        let array_buffer = crate::wasm::promise::<JsValue>(array_buffer_promise)\n            .await\n            .expect(\"could not get request body as array buffer\");\n\n        let v = Uint8Array::new(&array_buffer).to_vec();\n\n        assert_eq!(v, body_value);\n    }\n\n    #[wasm_bindgen_test]\n    async fn test_body_js_vec_u8() {\n        let body_value = vec![0u8, 42];\n        let body = Body::from(body_value.clone());\n\n        let mut init = web_sys::RequestInit::new();\n        init.method(\"POST\");\n        init.body(Some(\n            body.to_js_value()\n                .expect(\"could not convert body to JsValue\")\n                .as_ref(),\n        ));\n\n        let js_req = web_sys::Request::new_with_str_and_init(\"\", &init)\n            .expect(\"could not create JS request\");\n\n        let array_buffer_promise = js_req\n            .array_buffer()\n            .expect(\"could not get array_buffer promise\");\n        let array_buffer = crate::wasm::promise::<JsValue>(array_buffer_promise)\n            .await\n            .expect(\"could not get request body as array buffer\");\n\n        let v = Uint8Array::new(&array_buffer).to_vec();\n\n        assert_eq!(v, body_value);\n    }\n}\n"
  },
  {
    "path": "src/wasm/client.rs",
    "content": "use http::header::USER_AGENT;\nuse http::{HeaderMap, HeaderValue, Method};\nuse js_sys::Promise;\nuse std::convert::TryInto;\nuse std::{fmt, future::Future, sync::Arc};\nuse url::Url;\nuse wasm_bindgen::prelude::{wasm_bindgen, UnwrapThrowExt as _};\nuse wasm_bindgen::JsCast;\n\nuse super::{AbortGuard, Request, RequestBuilder, Response};\nuse crate::IntoUrl;\n\n#[wasm_bindgen]\nextern \"C\" {\n    #[wasm_bindgen(js_name = fetch)]\n    fn fetch_with_request(input: &web_sys::Request) -> Promise;\n}\n\nfn js_fetch(req: &web_sys::Request) -> Promise {\n    use wasm_bindgen::{JsCast, JsValue};\n    let global = js_sys::global();\n\n    if let Ok(true) = js_sys::Reflect::has(&global, &JsValue::from_str(\"ServiceWorkerGlobalScope\"))\n    {\n        global\n            .unchecked_into::<web_sys::ServiceWorkerGlobalScope>()\n            .fetch_with_request(req)\n    } else {\n        // browser\n        fetch_with_request(req)\n    }\n}\n\n/// An HTTP Client for WebAssembly.\n///\n/// Uses the browser's Fetch API to make requests. The `Client` holds\n/// configuration that applies to all requests. To configure a `Client`,\n/// use `Client::builder()`.\n#[derive(Clone)]\npub struct Client {\n    config: Arc<Config>,\n}\n\n/// A `ClientBuilder` can be used to create a `Client` with custom configuration.\npub struct ClientBuilder {\n    config: Config,\n}\n\nimpl Client {\n    /// Constructs a new `Client`.\n    pub fn new() -> Self {\n        Client::builder().build().unwrap_throw()\n    }\n\n    /// Creates a `ClientBuilder` to configure a `Client`.\n    ///\n    /// This is the same as `ClientBuilder::new()`.\n    pub fn builder() -> ClientBuilder {\n        ClientBuilder::new()\n    }\n\n    /// Convenience method to make a `GET` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::GET, url)\n    }\n\n    /// Convenience method to make a `POST` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::POST, url)\n    }\n\n    /// Convenience method to make a `PUT` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PUT, url)\n    }\n\n    /// Convenience method to make a `PATCH` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::PATCH, url)\n    }\n\n    /// Convenience method to make a `DELETE` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::DELETE, url)\n    }\n\n    /// Convenience method to make a `HEAD` request to a URL.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {\n        self.request(Method::HEAD, url)\n    }\n\n    /// Start building a `Request` with the `Method` and `Url`.\n    ///\n    /// Returns a `RequestBuilder`, which will allow setting headers and\n    /// request body before sending.\n    ///\n    /// # Errors\n    ///\n    /// This method fails whenever supplied `Url` cannot be parsed.\n    pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {\n        let req = url.into_url().map(move |url| Request::new(method, url));\n        RequestBuilder::new(self.clone(), req)\n    }\n\n    /// Executes a `Request`.\n    ///\n    /// A `Request` can be built manually with `Request::new()` or obtained\n    /// from a RequestBuilder with `RequestBuilder::build()`.\n    ///\n    /// You should prefer to use the `RequestBuilder` and\n    /// `RequestBuilder::send()`.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request,\n    /// redirect loop was detected or redirect limit was exhausted.\n    pub fn execute(\n        &self,\n        request: Request,\n    ) -> impl Future<Output = Result<Response, crate::Error>> {\n        self.execute_request(request)\n    }\n\n    // merge request headers with Client default_headers, prior to external http fetch\n    fn merge_headers(&self, req: &mut Request) {\n        use http::header::Entry;\n        let headers: &mut HeaderMap = req.headers_mut();\n        // insert default headers in the request headers\n        // without overwriting already appended headers.\n        for (key, value) in self.config.headers.iter() {\n            if let Entry::Vacant(entry) = headers.entry(key) {\n                entry.insert(value.clone());\n            }\n        }\n    }\n\n    pub(super) fn execute_request(\n        &self,\n        mut req: Request,\n    ) -> impl Future<Output = crate::Result<Response>> {\n        self.merge_headers(&mut req);\n        fetch(req)\n    }\n}\n\nimpl Default for Client {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl fmt::Debug for Client {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"Client\");\n        self.config.fmt_fields(&mut builder);\n        builder.finish()\n    }\n}\n\nimpl fmt::Debug for ClientBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"ClientBuilder\");\n        self.config.fmt_fields(&mut builder);\n        builder.finish()\n    }\n}\n\n// Can use new methods in web-sys when requiring v0.2.93.\n// > `init.method(m)` to `init.set_method(m)`\n// For now, ignore their deprecation.\n#[allow(deprecated)]\nasync fn fetch(req: Request) -> crate::Result<Response> {\n    // Build the js Request\n    let mut init = web_sys::RequestInit::new();\n    init.method(req.method().as_str());\n\n    // convert HeaderMap to Headers\n    let js_headers = web_sys::Headers::new()\n        .map_err(crate::error::wasm)\n        .map_err(crate::error::builder)?;\n\n    for (name, value) in req.headers() {\n        js_headers\n            .append(\n                name.as_str(),\n                value.to_str().map_err(crate::error::builder)?,\n            )\n            .map_err(crate::error::wasm)\n            .map_err(crate::error::builder)?;\n    }\n    init.headers(&js_headers.into());\n\n    // When req.cors is true, do nothing because the default mode is 'cors'\n    if !req.cors {\n        init.mode(web_sys::RequestMode::NoCors);\n    }\n\n    if let Some(creds) = req.credentials {\n        init.credentials(creds);\n    }\n\n    if let Some(cache) = req.cache {\n        init.set_cache(cache);\n    }\n\n    if let Some(body) = req.body() {\n        if !body.is_empty() {\n            init.body(Some(body.to_js_value()?.as_ref()));\n        }\n    }\n\n    let mut abort = AbortGuard::new()?;\n    if let Some(timeout) = req.timeout() {\n        abort.timeout(*timeout);\n    }\n    init.signal(Some(&abort.signal()));\n\n    let js_req = web_sys::Request::new_with_str_and_init(req.url().as_str(), &init)\n        .map_err(crate::error::wasm)\n        .map_err(crate::error::builder)?;\n\n    // Await the fetch() promise\n    let p = js_fetch(&js_req);\n    let js_resp = super::promise::<web_sys::Response>(p)\n        .await\n        .map_err(|error| {\n            if error.to_string() == \"JsValue(\\\"reqwest::errors::TimedOut\\\")\" {\n                crate::error::TimedOut.into()\n            } else {\n                error\n            }\n        })\n        .map_err(crate::error::request)?;\n\n    // Convert from the js Response\n    let mut resp = http::Response::builder().status(js_resp.status());\n\n    let url = Url::parse(&js_resp.url()).expect_throw(\"url parse\");\n\n    let js_headers = js_resp.headers();\n    for item in js_headers.entries() {\n        let item = item.expect_throw(\"headers iterator doesn't throw\");\n        let item: js_sys::Array = item.dyn_into().expect_throw(\"header item is an array\");\n\n        let name = item\n            .get(0)\n            .as_string()\n            .expect_throw(\"header name is a string\");\n\n        let value = item\n            .get(1)\n            .as_string()\n            .expect_throw(\"header value is a string\");\n\n        resp = resp.header(&name, &value);\n    }\n\n    resp.body(js_resp)\n        .map(|resp| Response::new(resp, url, abort))\n        .map_err(crate::error::request)\n}\n\n// ===== impl ClientBuilder =====\n\nimpl ClientBuilder {\n    /// Constructs a new `ClientBuilder`.\n    ///\n    /// This is the same as `Client::builder()`.\n    pub fn new() -> Self {\n        ClientBuilder {\n            config: Config::default(),\n        }\n    }\n\n    /// Returns a 'Client' that uses this ClientBuilder configuration\n    pub fn build(mut self) -> Result<Client, crate::Error> {\n        if let Some(err) = self.config.error {\n            return Err(err);\n        }\n\n        let config = std::mem::take(&mut self.config);\n        Ok(Client {\n            config: Arc::new(config),\n        })\n    }\n\n    /// Sets the `User-Agent` header to be used by this client.\n    pub fn user_agent<V>(mut self, value: V) -> ClientBuilder\n    where\n        V: TryInto<HeaderValue>,\n        V::Error: Into<http::Error>,\n    {\n        match value.try_into() {\n            Ok(value) => {\n                self.config.headers.insert(USER_AGENT, value);\n            }\n            Err(e) => {\n                self.config.error = Some(crate::error::builder(e.into()));\n            }\n        }\n        self\n    }\n\n    /// Sets the default headers for every request\n    pub fn default_headers(mut self, headers: HeaderMap) -> ClientBuilder {\n        for (key, value) in headers.iter() {\n            self.config.headers.insert(key, value.clone());\n        }\n        self\n    }\n}\n\nimpl Default for ClientBuilder {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n#[derive(Debug)]\nstruct Config {\n    headers: HeaderMap,\n    error: Option<crate::Error>,\n}\n\nimpl Default for Config {\n    fn default() -> Config {\n        Config {\n            headers: HeaderMap::new(),\n            error: None,\n        }\n    }\n}\n\nimpl Config {\n    fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {\n        f.field(\"default_headers\", &self.headers);\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use wasm_bindgen_test::*;\n\n    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);\n\n    #[wasm_bindgen_test]\n    async fn default_headers() {\n        use crate::header::{HeaderMap, HeaderValue, CONTENT_TYPE};\n\n        let mut headers = HeaderMap::new();\n        headers.insert(CONTENT_TYPE, HeaderValue::from_static(\"application/json\"));\n        headers.insert(\"x-custom\", HeaderValue::from_static(\"flibbertigibbet\"));\n        let client = crate::Client::builder()\n            .default_headers(headers)\n            .build()\n            .expect(\"client\");\n        let mut req = client\n            .get(\"https://www.example.com\")\n            .build()\n            .expect(\"request\");\n        // merge headers as if client were about to issue fetch\n        client.merge_headers(&mut req);\n\n        let test_headers = req.headers();\n        assert!(test_headers.get(CONTENT_TYPE).is_some(), \"content-type\");\n        assert!(test_headers.get(\"x-custom\").is_some(), \"custom header\");\n        assert!(test_headers.get(\"accept\").is_none(), \"no accept header\");\n    }\n\n    #[wasm_bindgen_test]\n    async fn default_headers_clone() {\n        use crate::header::{HeaderMap, HeaderValue, CONTENT_TYPE};\n\n        let mut headers = HeaderMap::new();\n        headers.insert(CONTENT_TYPE, HeaderValue::from_static(\"application/json\"));\n        headers.insert(\"x-custom\", HeaderValue::from_static(\"flibbertigibbet\"));\n        let client = crate::Client::builder()\n            .default_headers(headers)\n            .build()\n            .expect(\"client\");\n\n        let mut req = client\n            .get(\"https://www.example.com\")\n            .header(CONTENT_TYPE, \"text/plain\")\n            .build()\n            .expect(\"request\");\n        client.merge_headers(&mut req);\n        let headers1 = req.headers();\n\n        // confirm that request headers override defaults\n        assert_eq!(\n            headers1.get(CONTENT_TYPE).unwrap(),\n            \"text/plain\",\n            \"request headers override defaults\"\n        );\n\n        // confirm that request headers don't change client defaults\n        let mut req2 = client\n            .get(\"https://www.example.com/x\")\n            .build()\n            .expect(\"req 2\");\n        client.merge_headers(&mut req2);\n        let headers2 = req2.headers();\n        assert_eq!(\n            headers2.get(CONTENT_TYPE).unwrap(),\n            \"application/json\",\n            \"request headers don't change client defaults\"\n        );\n    }\n\n    #[wasm_bindgen_test]\n    fn user_agent_header() {\n        use crate::header::USER_AGENT;\n\n        let client = crate::Client::builder()\n            .user_agent(\"FooBar/1.2.3\")\n            .build()\n            .expect(\"client\");\n\n        let mut req = client\n            .get(\"https://www.example.com\")\n            .build()\n            .expect(\"request\");\n\n        // Merge the client headers with the request's one.\n        client.merge_headers(&mut req);\n        let headers1 = req.headers();\n\n        // Confirm that we have the `User-Agent` header set\n        assert_eq!(\n            headers1.get(USER_AGENT).unwrap(),\n            \"FooBar/1.2.3\",\n            \"The user-agent header was not set: {req:#?}\"\n        );\n\n        // Now we try to overwrite the `User-Agent` value\n\n        let mut req2 = client\n            .get(\"https://www.example.com\")\n            .header(USER_AGENT, \"Another-User-Agent/42\")\n            .build()\n            .expect(\"request 2\");\n\n        client.merge_headers(&mut req2);\n        let headers2 = req2.headers();\n\n        assert_eq!(\n            headers2.get(USER_AGENT).expect(\"headers2 user agent\"),\n            \"Another-User-Agent/42\",\n            \"Was not able to overwrite the User-Agent value on the request-builder\"\n        );\n    }\n}\n"
  },
  {
    "path": "src/wasm/mod.rs",
    "content": "use std::convert::TryInto;\nuse std::time::Duration;\n\nuse js_sys::Function;\nuse wasm_bindgen::prelude::{wasm_bindgen, Closure};\nuse wasm_bindgen::{JsCast, JsValue};\nuse web_sys::{AbortController, AbortSignal};\n\nmod body;\nmod client;\n/// TODO\n#[cfg(feature = \"multipart\")]\npub mod multipart;\nmod request;\nmod response;\n\npub use self::body::Body;\npub use self::client::{Client, ClientBuilder};\npub use self::request::{Request, RequestBuilder};\npub use self::response::Response;\n\n#[wasm_bindgen]\nextern \"C\" {\n    #[wasm_bindgen(js_name = \"setTimeout\")]\n    fn set_timeout(handler: &Function, timeout: i32) -> JsValue;\n\n    #[wasm_bindgen(js_name = \"clearTimeout\")]\n    fn clear_timeout(handle: JsValue) -> JsValue;\n}\n\nasync fn promise<T>(promise: js_sys::Promise) -> Result<T, crate::error::BoxError>\nwhere\n    T: JsCast,\n{\n    use wasm_bindgen_futures::JsFuture;\n\n    let js_val = JsFuture::from(promise).await.map_err(crate::error::wasm)?;\n\n    js_val\n        .dyn_into::<T>()\n        .map_err(|_js_val| \"promise resolved to unexpected type\".into())\n}\n\n/// A guard that cancels a fetch request when dropped.\nstruct AbortGuard {\n    ctrl: AbortController,\n    timeout: Option<(JsValue, Closure<dyn FnMut()>)>,\n}\n\nimpl AbortGuard {\n    fn new() -> crate::Result<Self> {\n        Ok(AbortGuard {\n            ctrl: AbortController::new()\n                .map_err(crate::error::wasm)\n                .map_err(crate::error::builder)?,\n            timeout: None,\n        })\n    }\n\n    fn signal(&self) -> AbortSignal {\n        self.ctrl.signal()\n    }\n\n    fn timeout(&mut self, timeout: Duration) {\n        let ctrl = self.ctrl.clone();\n        let abort =\n            Closure::once(move || ctrl.abort_with_reason(&\"reqwest::errors::TimedOut\".into()));\n        let timeout = set_timeout(\n            abort.as_ref().unchecked_ref::<js_sys::Function>(),\n            timeout.as_millis().try_into().expect(\"timeout\"),\n        );\n        if let Some((id, _)) = self.timeout.replace((timeout, abort)) {\n            clear_timeout(id);\n        }\n    }\n}\n\nimpl Drop for AbortGuard {\n    fn drop(&mut self) {\n        self.ctrl.abort();\n        if let Some((id, _)) = self.timeout.take() {\n            clear_timeout(id);\n        }\n    }\n}\n"
  },
  {
    "path": "src/wasm/multipart.rs",
    "content": "//! multipart/form-data\nuse std::borrow::Cow;\nuse std::fmt;\n\nuse http::HeaderMap;\nuse mime_guess::Mime;\nuse web_sys::FormData;\n\nuse super::Body;\n\n/// An async multipart/form-data request.\npub struct Form {\n    inner: FormParts<Part>,\n}\n\nimpl Form {\n    pub(crate) fn is_empty(&self) -> bool {\n        self.inner.fields.is_empty()\n    }\n}\n\n/// A field in a multipart form.\npub struct Part {\n    meta: PartMetadata,\n    value: Body,\n}\n\npub(crate) struct FormParts<P> {\n    pub(crate) fields: Vec<(Cow<'static, str>, P)>,\n}\n\npub(crate) struct PartMetadata {\n    mime: Option<Mime>,\n    file_name: Option<Cow<'static, str>>,\n    pub(crate) headers: HeaderMap,\n}\n\npub(crate) trait PartProps {\n    fn metadata(&self) -> &PartMetadata;\n}\n\n// ===== impl Form =====\n\nimpl Default for Form {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl Form {\n    /// Creates a new async Form without any content.\n    pub fn new() -> Form {\n        Form {\n            inner: FormParts::new(),\n        }\n    }\n\n    /// Add a data field with supplied name and value.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// let form = reqwest::multipart::Form::new()\n    ///     .text(\"username\", \"seanmonstar\")\n    ///     .text(\"password\", \"secret\");\n    /// ```\n    pub fn text<T, U>(self, name: T, value: U) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n        U: Into<Cow<'static, str>>,\n    {\n        self.part(name, Part::text(value))\n    }\n\n    /// Adds a customized Part.\n    pub fn part<T>(self, name: T, part: Part) -> Form\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.part(name, part))\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(FormParts<Part>) -> FormParts<Part>,\n    {\n        Form {\n            inner: func(self.inner),\n        }\n    }\n\n    pub(crate) fn to_form_data(&self) -> crate::Result<FormData> {\n        let form = FormData::new()\n            .map_err(crate::error::wasm)\n            .map_err(crate::error::builder)?;\n\n        for (name, part) in self.inner.fields.iter() {\n            part.append_to_form(name, &form)\n                .map_err(crate::error::wasm)\n                .map_err(crate::error::builder)?;\n        }\n        Ok(form)\n    }\n}\n\nimpl fmt::Debug for Form {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.inner.fmt_fields(\"Form\", f)\n    }\n}\n\n// ===== impl Part =====\n\nimpl Part {\n    /// Makes a text parameter.\n    pub fn text<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(string) => Body::from(string),\n        };\n        Part::new(body)\n    }\n\n    /// Makes a new parameter from arbitrary bytes.\n    pub fn bytes<T>(value: T) -> Part\n    where\n        T: Into<Cow<'static, [u8]>>,\n    {\n        let body = match value.into() {\n            Cow::Borrowed(slice) => Body::from(slice),\n            Cow::Owned(vec) => Body::from(vec),\n        };\n        Part::new(body)\n    }\n\n    /// Makes a new parameter from an arbitrary stream.\n    pub fn stream<T: Into<Body>>(value: T) -> Part {\n        Part::new(value.into())\n    }\n\n    fn new(value: Body) -> Part {\n        Part {\n            meta: PartMetadata::new(),\n            value: value.into_part(),\n        }\n    }\n\n    /// Tries to set the mime of this part.\n    pub fn mime_str(self, mime: &str) -> crate::Result<Part> {\n        Ok(self.mime(mime.parse().map_err(crate::error::builder)?))\n    }\n\n    // Re-export when mime 0.4 is available, with split MediaType/MediaRange.\n    fn mime(self, mime: Mime) -> Part {\n        self.with_inner(move |inner| inner.mime(mime))\n    }\n\n    /// Sets the filename, builder style.\n    pub fn file_name<T>(self, filename: T) -> Part\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.with_inner(move |inner| inner.file_name(filename))\n    }\n\n    /// Sets custom headers for the part.\n    pub fn headers(self, headers: HeaderMap) -> Part {\n        self.with_inner(move |inner| inner.headers(headers))\n    }\n\n    fn with_inner<F>(self, func: F) -> Self\n    where\n        F: FnOnce(PartMetadata) -> PartMetadata,\n    {\n        Part {\n            meta: func(self.meta),\n            value: self.value,\n        }\n    }\n\n    fn append_to_form(\n        &self,\n        name: &str,\n        form: &web_sys::FormData,\n    ) -> Result<(), wasm_bindgen::JsValue> {\n        let single = self\n            .value\n            .as_single()\n            .expect(\"A part's body can't be multipart itself\");\n\n        let mut mime_type = self.metadata().mime.as_ref();\n\n        // The JS fetch API doesn't support file names and mime types for strings. So we do our best\n        // effort to use `append_with_str` and fallback to `append_with_blob_*` if that's not\n        // possible.\n        if let super::body::Single::Text(text) = single {\n            if mime_type.is_none() || mime_type == Some(&mime_guess::mime::TEXT_PLAIN) {\n                if self.metadata().file_name.is_none() {\n                    return form.append_with_str(name, text);\n                }\n            } else {\n                mime_type = Some(&mime_guess::mime::TEXT_PLAIN);\n            }\n        }\n\n        let blob = self.blob(mime_type)?;\n\n        if let Some(file_name) = &self.metadata().file_name {\n            form.append_with_blob_and_filename(name, &blob, file_name)\n        } else {\n            form.append_with_blob(name, &blob)\n        }\n    }\n\n    fn blob(&self, mime_type: Option<&Mime>) -> crate::Result<web_sys::Blob> {\n        use web_sys::Blob;\n        use web_sys::BlobPropertyBag;\n        let mut properties = BlobPropertyBag::new();\n        if let Some(mime) = mime_type {\n            properties.type_(mime.as_ref());\n        }\n\n        let js_value = self\n            .value\n            .as_single()\n            .expect(\"A part's body can't be set to a multipart body\")\n            .to_js_value();\n\n        let body_array = js_sys::Array::new();\n        body_array.push(&js_value);\n\n        Blob::new_with_u8_array_sequence_and_options(body_array.as_ref(), &properties)\n            .map_err(crate::error::wasm)\n            .map_err(crate::error::builder)\n    }\n}\n\nimpl fmt::Debug for Part {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut dbg = f.debug_struct(\"Part\");\n        dbg.field(\"value\", &self.value);\n        self.meta.fmt_fields(&mut dbg);\n        dbg.finish()\n    }\n}\n\nimpl PartProps for Part {\n    fn metadata(&self) -> &PartMetadata {\n        &self.meta\n    }\n}\n\n// ===== impl FormParts =====\n\nimpl<P: PartProps> FormParts<P> {\n    pub(crate) fn new() -> Self {\n        FormParts { fields: Vec::new() }\n    }\n\n    /// Adds a customized Part.\n    pub(crate) fn part<T>(mut self, name: T, part: P) -> Self\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.fields.push((name.into(), part));\n        self\n    }\n}\n\nimpl<P: fmt::Debug> FormParts<P> {\n    pub(crate) fn fmt_fields(&self, ty_name: &'static str, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(ty_name)\n            .field(\"parts\", &self.fields)\n            .finish()\n    }\n}\n\n// ===== impl PartMetadata =====\n\nimpl PartMetadata {\n    pub(crate) fn new() -> Self {\n        PartMetadata {\n            mime: None,\n            file_name: None,\n            headers: HeaderMap::default(),\n        }\n    }\n\n    pub(crate) fn mime(mut self, mime: Mime) -> Self {\n        self.mime = Some(mime);\n        self\n    }\n\n    pub(crate) fn file_name<T>(mut self, filename: T) -> Self\n    where\n        T: Into<Cow<'static, str>>,\n    {\n        self.file_name = Some(filename.into());\n        self\n    }\n\n    pub(crate) fn headers<T>(mut self, headers: T) -> Self\n    where\n        T: Into<HeaderMap>,\n    {\n        self.headers = headers.into();\n        self\n    }\n}\n\nimpl PartMetadata {\n    pub(crate) fn fmt_fields<'f, 'fa, 'fb>(\n        &self,\n        debug_struct: &'f mut fmt::DebugStruct<'fa, 'fb>,\n    ) -> &'f mut fmt::DebugStruct<'fa, 'fb> {\n        debug_struct\n            .field(\"mime\", &self.mime)\n            .field(\"file_name\", &self.file_name)\n            .field(\"headers\", &self.headers)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n\n    use wasm_bindgen_test::*;\n\n    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);\n\n    #[wasm_bindgen_test]\n    async fn test_multipart_js() {\n        use super::{Form, Part};\n        use js_sys::Uint8Array;\n        use wasm_bindgen::JsValue;\n        use web_sys::{File, FormData};\n\n        let text_file_name = \"test.txt\";\n        let text_file_type = \"text/plain\";\n        let text_content = \"TEST\";\n        let text_part = Part::text(text_content)\n            .file_name(text_file_name)\n            .mime_str(text_file_type)\n            .expect(\"invalid mime type\");\n\n        let binary_file_name = \"binary.bin\";\n        let binary_file_type = \"application/octet-stream\";\n        let binary_content = vec![0u8, 42];\n        let binary_part = Part::bytes(binary_content.clone())\n            .file_name(binary_file_name)\n            .mime_str(binary_file_type)\n            .expect(\"invalid mime type\");\n\n        let string_name = \"string\";\n        let string_content = \"CONTENT\";\n        let string_part = Part::text(string_content);\n\n        let text_name = \"text part\";\n        let binary_name = \"binary part\";\n        let form = Form::new()\n            .part(text_name, text_part)\n            .part(binary_name, binary_part)\n            .part(string_name, string_part);\n\n        let mut init = web_sys::RequestInit::new();\n        init.method(\"POST\");\n        init.body(Some(\n            form.to_form_data()\n                .expect(\"could not convert to FormData\")\n                .as_ref(),\n        ));\n\n        let js_req = web_sys::Request::new_with_str_and_init(\"\", &init)\n            .expect(\"could not create JS request\");\n\n        let form_data_promise = js_req.form_data().expect(\"could not get form_data promise\");\n\n        let form_data = crate::wasm::promise::<FormData>(form_data_promise)\n            .await\n            .expect(\"could not get body as form data\");\n\n        // check text part\n        let text_file = File::from(form_data.get(text_name));\n        assert_eq!(text_file.name(), text_file_name);\n        assert_eq!(text_file.type_(), text_file_type);\n\n        let text_promise = text_file.text();\n        let text = crate::wasm::promise::<JsValue>(text_promise)\n            .await\n            .expect(\"could not get text body as text\");\n        assert_eq!(\n            text.as_string().expect(\"text is not a string\"),\n            text_content\n        );\n\n        // check binary part\n        let binary_file = File::from(form_data.get(binary_name));\n        assert_eq!(binary_file.name(), binary_file_name);\n        assert_eq!(binary_file.type_(), binary_file_type);\n\n        // check string part\n        let string = form_data\n            .get(string_name)\n            .as_string()\n            .expect(\"content is not a string\");\n        assert_eq!(string, string_content);\n\n        let binary_array_buffer_promise = binary_file.array_buffer();\n        let array_buffer = crate::wasm::promise::<JsValue>(binary_array_buffer_promise)\n            .await\n            .expect(\"could not get request body as array buffer\");\n\n        let binary = Uint8Array::new(&array_buffer).to_vec();\n\n        assert_eq!(binary, binary_content);\n    }\n}\n"
  },
  {
    "path": "src/wasm/request.rs",
    "content": "use std::convert::TryFrom;\nuse std::fmt;\nuse std::time::Duration;\n\nuse bytes::Bytes;\nuse http::{request::Parts, Method, Request as HttpRequest};\n#[cfg(any(feature = \"query\", feature = \"form\", feature = \"json\"))]\nuse serde::Serialize;\n#[cfg(feature = \"json\")]\nuse serde_json;\nuse url::Url;\nuse web_sys::{RequestCache, RequestCredentials};\n\nuse super::{Body, Client, Response};\n#[cfg(any(feature = \"form\", feature = \"json\"))]\nuse crate::header::CONTENT_TYPE;\nuse crate::header::{HeaderMap, HeaderName, HeaderValue};\n\n/// A request which can be executed with `Client::execute()`.\npub struct Request {\n    method: Method,\n    url: Url,\n    headers: HeaderMap,\n    body: Option<Body>,\n    timeout: Option<Duration>,\n    pub(super) cors: bool,\n    pub(super) credentials: Option<RequestCredentials>,\n    pub(super) cache: Option<RequestCache>,\n}\n\n/// A builder to construct the properties of a `Request`.\npub struct RequestBuilder {\n    client: Client,\n    request: crate::Result<Request>,\n}\n\nimpl Request {\n    /// Constructs a new request.\n    #[inline]\n    pub fn new(method: Method, url: Url) -> Self {\n        Request {\n            method,\n            url,\n            headers: HeaderMap::new(),\n            body: None,\n            timeout: None,\n            cors: true,\n            credentials: None,\n            cache: None,\n        }\n    }\n\n    /// Get the method.\n    #[inline]\n    pub fn method(&self) -> &Method {\n        &self.method\n    }\n\n    /// Get a mutable reference to the method.\n    #[inline]\n    pub fn method_mut(&mut self) -> &mut Method {\n        &mut self.method\n    }\n\n    /// Get the url.\n    #[inline]\n    pub fn url(&self) -> &Url {\n        &self.url\n    }\n\n    /// Get a mutable reference to the url.\n    #[inline]\n    pub fn url_mut(&mut self) -> &mut Url {\n        &mut self.url\n    }\n\n    /// Get the headers.\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        &self.headers\n    }\n\n    /// Get a mutable reference to the headers.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        &mut self.headers\n    }\n\n    /// Get the body.\n    #[inline]\n    pub fn body(&self) -> Option<&Body> {\n        self.body.as_ref()\n    }\n\n    /// Get a mutable reference to the body.\n    #[inline]\n    pub fn body_mut(&mut self) -> &mut Option<Body> {\n        &mut self.body\n    }\n\n    /// Get the timeout.\n    #[inline]\n    pub fn timeout(&self) -> Option<&Duration> {\n        self.timeout.as_ref()\n    }\n\n    /// Get a mutable reference to the timeout.\n    #[inline]\n    pub fn timeout_mut(&mut self) -> &mut Option<Duration> {\n        &mut self.timeout\n    }\n\n    /// Attempts to clone the `Request`.\n    ///\n    /// None is returned if a body is which can not be cloned.\n    pub fn try_clone(&self) -> Option<Request> {\n        let body = match self.body.as_ref() {\n            Some(body) => Some(body.try_clone()?),\n            None => None,\n        };\n\n        Some(Self {\n            method: self.method.clone(),\n            url: self.url.clone(),\n            headers: self.headers.clone(),\n            body,\n            timeout: self.timeout,\n            cors: self.cors,\n            credentials: self.credentials,\n            cache: self.cache,\n        })\n    }\n}\n\nimpl RequestBuilder {\n    pub(super) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder {\n        RequestBuilder { client, request }\n    }\n\n    /// Assemble a builder starting from an existing `Client` and a `Request`.\n    pub fn from_parts(client: crate::Client, request: crate::Request) -> crate::RequestBuilder {\n        crate::RequestBuilder {\n            client,\n            request: crate::Result::Ok(request),\n        }\n    }\n\n    /// Modify the query string of the URL.\n    ///\n    /// Modifies the URL of this request, adding the parameters provided.\n    /// This method appends and does not overwrite. This means that it can\n    /// be called multiple times and that existing query parameters are not\n    /// overwritten if the same key is used. The key will simply show up\n    /// twice in the query string.\n    /// Calling `.query([(\"foo\", \"a\"), (\"foo\", \"b\")])` gives `\"foo=a&foo=b\"`.\n    ///\n    /// # Note\n    /// This method does not support serializing a single key-value\n    /// pair. Instead of using `.query((\"key\", \"val\"))`, use a sequence, such\n    /// as `.query(&[(\"key\", \"val\")])`. It's also possible to serialize structs\n    /// and maps into a key-value pair.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `query` feature to be enabled.\n    ///\n    /// # Errors\n    /// This method will fail if the object you provide cannot be serialized\n    /// into a query string.\n    #[cfg(feature = \"query\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"query\")))]\n    pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            let url = req.url_mut();\n            let mut pairs = url.query_pairs_mut();\n            let serializer = serde_urlencoded::Serializer::new(&mut pairs);\n\n            if let Err(err) = query.serialize(serializer) {\n                error = Some(crate::error::builder(err));\n            }\n        }\n        if let Ok(ref mut req) = self.request {\n            if let Some(\"\") = req.url().query() {\n                req.url_mut().set_query(None);\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Send a form body.\n    ///\n    /// Sets the body to the url encoded serialization of the passed value,\n    /// and also sets the `Content-Type: application/x-www-form-urlencoded`\n    /// header.\n    ///\n    /// # Optional\n    ///\n    /// This requires the optional `form` feature to be enabled.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if the passed value cannot be serialized into\n    /// url encoded format\n    #[cfg(feature = \"form\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"form\")))]\n    pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_urlencoded::to_string(form) {\n                Ok(body) => {\n                    req.headers_mut().insert(\n                        CONTENT_TYPE,\n                        HeaderValue::from_static(\"application/x-www-form-urlencoded\"),\n                    );\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    /// Set the request json\n    pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match serde_json::to_vec(json) {\n                Ok(body) => {\n                    req.headers_mut()\n                        .entry(CONTENT_TYPE)\n                        .or_insert_with(|| HeaderValue::from_static(\"application/json\"));\n                    *req.body_mut() = Some(body.into());\n                }\n                Err(err) => error = Some(crate::error::builder(err)),\n            }\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Enable HTTP basic authentication.\n    pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> RequestBuilder\n    where\n        U: fmt::Display,\n        P: fmt::Display,\n    {\n        let header_value = crate::util::basic_auth(username, password);\n        self.header(crate::header::AUTHORIZATION, header_value)\n    }\n\n    /// Enable HTTP bearer authentication.\n    pub fn bearer_auth<T>(self, token: T) -> RequestBuilder\n    where\n        T: fmt::Display,\n    {\n        let header_value = format!(\"Bearer {token}\");\n        self.header(crate::header::AUTHORIZATION, header_value)\n    }\n\n    /// Set the request body.\n    pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.body = Some(body.into());\n        }\n        self\n    }\n\n    /// Enables a request timeout.\n    pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.timeout_mut() = Some(timeout);\n        }\n        self\n    }\n\n    /// TODO\n    #[cfg(feature = \"multipart\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"multipart\")))]\n    pub fn multipart(mut self, multipart: super::multipart::Form) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            *req.body_mut() = Some(Body::from_form(multipart))\n        }\n        self\n    }\n\n    /// Add a `Header` to this Request.\n    pub fn header<K, V>(mut self, key: K, value: V) -> RequestBuilder\n    where\n        HeaderName: TryFrom<K>,\n        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,\n        HeaderValue: TryFrom<V>,\n        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,\n    {\n        let mut error = None;\n        if let Ok(ref mut req) = self.request {\n            match <HeaderName as TryFrom<K>>::try_from(key) {\n                Ok(key) => match <HeaderValue as TryFrom<V>>::try_from(value) {\n                    Ok(value) => {\n                        req.headers_mut().append(key, value);\n                    }\n                    Err(e) => error = Some(crate::error::builder(e.into())),\n                },\n                Err(e) => error = Some(crate::error::builder(e.into())),\n            };\n        }\n        if let Some(err) = error {\n            self.request = Err(err);\n        }\n        self\n    }\n\n    /// Add a set of Headers to the existing ones on this Request.\n    ///\n    /// The headers will be merged in to any already set.\n    pub fn headers(mut self, headers: crate::header::HeaderMap) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            crate::util::replace_headers(req.headers_mut(), headers);\n        }\n        self\n    }\n\n    /// Disable CORS on fetching the request.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request mode][mdn] will be set to 'no-cors'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode\n    pub fn fetch_mode_no_cors(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cors = false;\n        }\n        self\n    }\n\n    /// Set fetch credentials to 'same-origin'\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request credentials][mdn] will be set to 'same-origin'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials\n    pub fn fetch_credentials_same_origin(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.credentials = Some(RequestCredentials::SameOrigin);\n        }\n        self\n    }\n\n    /// Set fetch credentials to 'include'\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request credentials][mdn] will be set to 'include'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials\n    pub fn fetch_credentials_include(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.credentials = Some(RequestCredentials::Include);\n        }\n        self\n    }\n\n    /// Set fetch credentials to 'omit'\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request credentials][mdn] will be set to 'omit'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials\n    pub fn fetch_credentials_omit(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.credentials = Some(RequestCredentials::Omit);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'default'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'default'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_default(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::Default);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'no-store'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'no-store'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_no_store(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::NoStore);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'reload'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'reload'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_reload(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::Reload);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'no-cache'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'no-cache'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_no_cache(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::NoCache);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'force-cache'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'force-cache'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_force_cache(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::ForceCache);\n        }\n        self\n    }\n\n    /// Set fetch cache mode to 'only-if-cached'.\n    ///\n    /// # WASM\n    ///\n    /// This option is only effective with WebAssembly target.\n    ///\n    /// The [request cache][mdn] will be set to 'only-if-cached'.\n    ///\n    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n    pub fn fetch_cache_only_if_cached(mut self) -> RequestBuilder {\n        if let Ok(ref mut req) = self.request {\n            req.cache = Some(RequestCache::OnlyIfCached);\n        }\n        self\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    pub fn build(self) -> crate::Result<Request> {\n        self.request\n    }\n\n    /// Build a `Request`, which can be inspected, modified and executed with\n    /// `Client::execute()`.\n    ///\n    /// This is similar to [`RequestBuilder::build()`], but also returns the\n    /// embedded `Client`.\n    pub fn build_split(self) -> (Client, crate::Result<Request>) {\n        (self.client, self.request)\n    }\n\n    /// Constructs the Request and sends it to the target URL, returning a\n    /// future Response.\n    ///\n    /// # Errors\n    ///\n    /// This method fails if there was an error while sending request.\n    ///\n    /// # Example\n    ///\n    /// ```no_run\n    /// # use reqwest::Error;\n    /// #\n    /// # async fn run() -> Result<(), Error> {\n    /// let response = reqwest::Client::new()\n    ///     .get(\"https://hyper.rs\")\n    ///     .send()\n    ///     .await?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub async fn send(self) -> crate::Result<Response> {\n        let req = self.request?;\n        self.client.execute_request(req).await\n    }\n\n    /// Attempt to clone the RequestBuilder.\n    ///\n    /// `None` is returned if the RequestBuilder can not be cloned.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// # use reqwest::Error;\n    /// #\n    /// # fn run() -> Result<(), Error> {\n    /// let client = reqwest::Client::new();\n    /// let builder = client.post(\"http://httpbin.org/post\")\n    ///     .body(\"from a &str!\");\n    /// let clone = builder.try_clone();\n    /// assert!(clone.is_some());\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn try_clone(&self) -> Option<RequestBuilder> {\n        self.request\n            .as_ref()\n            .ok()\n            .and_then(|req| req.try_clone())\n            .map(|req| RequestBuilder {\n                client: self.client.clone(),\n                request: Ok(req),\n            })\n    }\n}\n\nimpl fmt::Debug for Request {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt_request_fields(&mut f.debug_struct(\"Request\"), self).finish()\n    }\n}\n\nimpl fmt::Debug for RequestBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        let mut builder = f.debug_struct(\"RequestBuilder\");\n        match self.request {\n            Ok(ref req) => fmt_request_fields(&mut builder, req).finish(),\n            Err(ref err) => builder.field(\"error\", err).finish(),\n        }\n    }\n}\n\nfn fmt_request_fields<'a, 'b>(\n    f: &'a mut fmt::DebugStruct<'a, 'b>,\n    req: &Request,\n) -> &'a mut fmt::DebugStruct<'a, 'b> {\n    f.field(\"method\", &req.method)\n        .field(\"url\", &req.url)\n        .field(\"headers\", &req.headers)\n}\n\nimpl<T> TryFrom<HttpRequest<T>> for Request\nwhere\n    T: Into<Body>,\n{\n    type Error = crate::Error;\n\n    fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {\n        let (parts, body) = req.into_parts();\n        let Parts {\n            method,\n            uri,\n            headers,\n            ..\n        } = parts;\n        let url = Url::parse(&uri.to_string()).map_err(crate::error::builder)?;\n        Ok(Request {\n            method,\n            url,\n            headers,\n            body: Some(body.into()),\n            timeout: None,\n            cors: true,\n            credentials: None,\n            cache: None,\n        })\n    }\n}\n\nimpl TryFrom<Request> for HttpRequest<Body> {\n    type Error = crate::Error;\n\n    fn try_from(req: Request) -> crate::Result<Self> {\n        let Request {\n            method,\n            url,\n            headers,\n            body,\n            ..\n        } = req;\n\n        let mut req = HttpRequest::builder()\n            .method(method)\n            .uri(url.as_str())\n            .body(body.unwrap_or_else(|| Body::from(Bytes::default())))\n            .map_err(crate::error::builder)?;\n\n        *req.headers_mut() = headers;\n        Ok(req)\n    }\n}\n"
  },
  {
    "path": "src/wasm/response.rs",
    "content": "use std::fmt;\n\nuse bytes::Bytes;\nuse http::{HeaderMap, StatusCode};\nuse js_sys::Uint8Array;\nuse url::Url;\n\nuse crate::wasm::AbortGuard;\n\n#[cfg(feature = \"stream\")]\nuse wasm_bindgen::JsCast;\n\n#[cfg(feature = \"stream\")]\nuse futures_util::stream::{self, StreamExt};\n\n#[cfg(feature = \"json\")]\nuse serde::de::DeserializeOwned;\n\n/// A Response to a submitted `Request`.\npub struct Response {\n    http: http::Response<web_sys::Response>,\n    _abort: AbortGuard,\n    // Boxed to save space (11 words to 1 word), and it's not accessed\n    // frequently internally.\n    url: Box<Url>,\n}\n\nimpl Response {\n    pub(super) fn new(\n        res: http::Response<web_sys::Response>,\n        url: Url,\n        abort: AbortGuard,\n    ) -> Response {\n        Response {\n            http: res,\n            url: Box::new(url),\n            _abort: abort,\n        }\n    }\n\n    /// Get the `StatusCode` of this `Response`.\n    #[inline]\n    pub fn status(&self) -> StatusCode {\n        self.http.status()\n    }\n\n    /// Get the `Headers` of this `Response`.\n    #[inline]\n    pub fn headers(&self) -> &HeaderMap {\n        self.http.headers()\n    }\n\n    /// Get a mutable reference to the `Headers` of this `Response`.\n    #[inline]\n    pub fn headers_mut(&mut self) -> &mut HeaderMap {\n        self.http.headers_mut()\n    }\n\n    /// Get the content-length of this response, if known.\n    ///\n    /// Reasons it may not be known:\n    ///\n    /// - The server didn't send a `content-length` header.\n    /// - The response is compressed and automatically decoded (thus changing\n    ///   the actual decoded length).\n    pub fn content_length(&self) -> Option<u64> {\n        self.headers()\n            .get(http::header::CONTENT_LENGTH)?\n            .to_str()\n            .ok()?\n            .parse()\n            .ok()\n    }\n\n    /// Get the final `Url` of this `Response`.\n    #[inline]\n    pub fn url(&self) -> &Url {\n        &self.url\n    }\n\n    /* It might not be possible to detect this in JS?\n    /// Get the HTTP `Version` of this `Response`.\n    #[inline]\n    pub fn version(&self) -> Version {\n        self.http.version()\n    }\n    */\n\n    /// Try to deserialize the response body as JSON.\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"json\")))]\n    pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {\n        let full = self.bytes().await?;\n\n        serde_json::from_slice(&full).map_err(crate::error::decode)\n    }\n\n    /// Get the response text.\n    pub async fn text(self) -> crate::Result<String> {\n        let p = self\n            .http\n            .body()\n            .text()\n            .map_err(crate::error::wasm)\n            .map_err(crate::error::decode)?;\n        let js_val = super::promise::<wasm_bindgen::JsValue>(p)\n            .await\n            .map_err(crate::error::decode)?;\n        if let Some(s) = js_val.as_string() {\n            Ok(s)\n        } else {\n            Err(crate::error::decode(\"response.text isn't string\"))\n        }\n    }\n\n    /// Get the response as bytes\n    pub async fn bytes(self) -> crate::Result<Bytes> {\n        let p = self\n            .http\n            .body()\n            .array_buffer()\n            .map_err(crate::error::wasm)\n            .map_err(crate::error::decode)?;\n\n        let buf_js = super::promise::<wasm_bindgen::JsValue>(p)\n            .await\n            .map_err(crate::error::decode)?;\n\n        let buffer = Uint8Array::new(&buf_js);\n        let mut bytes = vec![0; buffer.length() as usize];\n        buffer.copy_to(&mut bytes);\n        Ok(bytes.into())\n    }\n\n    /// Convert the response into a `Stream` of `Bytes` from the body.\n    #[cfg(feature = \"stream\")]\n    pub fn bytes_stream(self) -> impl futures_core::Stream<Item = crate::Result<Bytes>> {\n        use futures_core::Stream;\n        use std::pin::Pin;\n\n        let web_response = self.http.into_body();\n        let abort = self._abort;\n\n        if let Some(body) = web_response.body() {\n            let body = wasm_streams::ReadableStream::from_raw(body.unchecked_into());\n            Box::pin(body.into_stream().map(move |buf_js| {\n                // Keep the abort guard alive as long as this stream is.\n                let _abort = &abort;\n                let buffer = Uint8Array::new(\n                    &buf_js\n                        .map_err(crate::error::wasm)\n                        .map_err(crate::error::decode)?,\n                );\n                let mut bytes = vec![0; buffer.length() as usize];\n                buffer.copy_to(&mut bytes);\n                Ok(bytes.into())\n            })) as Pin<Box<dyn Stream<Item = crate::Result<Bytes>>>>\n        } else {\n            // If there's no body, return an empty stream.\n            Box::pin(stream::empty()) as Pin<Box<dyn Stream<Item = crate::Result<Bytes>>>>\n        }\n    }\n\n    // util methods\n\n    /// Turn a response into an error if the server returned an error.\n    pub fn error_for_status(self) -> crate::Result<Self> {\n        let status = self.status();\n        if status.is_client_error() || status.is_server_error() {\n            Err(crate::error::status_code(*self.url, status))\n        } else {\n            Ok(self)\n        }\n    }\n\n    /// Turn a reference to a response into an error if the server returned an error.\n    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {\n        let status = self.status();\n        if status.is_client_error() || status.is_server_error() {\n            Err(crate::error::status_code(*self.url.clone(), status))\n        } else {\n            Ok(self)\n        }\n    }\n}\n\nimpl fmt::Debug for Response {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_struct(\"Response\")\n            //.field(\"url\", self.url())\n            .field(\"status\", &self.status())\n            .field(\"headers\", self.headers())\n            .finish()\n    }\n}\n"
  },
  {
    "path": "tests/badssl.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\n\n#[cfg(all(feature = \"__tls\"))]\n#[tokio::test]\nasync fn test_badssl_modern() {\n    let text = reqwest::Client::builder()\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(\"https://mozilla-modern.badssl.com/\")\n        .send()\n        .await\n        .unwrap()\n        .text()\n        .await\n        .unwrap();\n\n    assert!(text.contains(\"<title>mozilla-modern.badssl.com</title>\"));\n}\n\n#[cfg(feature = \"__tls\")]\n#[tokio::test]\nasync fn test_badssl_self_signed() {\n    let text = reqwest::Client::builder()\n        .tls_danger_accept_invalid_certs(true)\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(\"https://self-signed.badssl.com/\")\n        .send()\n        .await\n        .unwrap()\n        .text()\n        .await\n        .unwrap();\n\n    assert!(text.contains(\"<title>self-signed.badssl.com</title>\"));\n}\n\n#[cfg(feature = \"__tls\")]\n#[tokio::test]\nasync fn test_badssl_no_built_in_roots() {\n    let result = reqwest::Client::builder()\n        .tls_certs_only([])\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(\"https://mozilla-modern.badssl.com/\")\n        .send()\n        .await;\n\n    assert!(result.is_err());\n}\n\n#[cfg(any(feature = \"__native-tls\"))]\n#[tokio::test]\nasync fn test_badssl_wrong_host() {\n    let text = reqwest::Client::builder()\n        .tls_backend_native()\n        .tls_danger_accept_invalid_hostnames(true)\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(\"https://wrong.host.badssl.com/\")\n        .send()\n        .await\n        .unwrap()\n        .text()\n        .await\n        .unwrap();\n\n    assert!(text.contains(\"<title>wrong.host.badssl.com</title>\"));\n\n    let result = reqwest::Client::builder()\n        .tls_backend_native()\n        .tls_danger_accept_invalid_hostnames(true)\n        .build()\n        .unwrap()\n        .get(\"https://self-signed.badssl.com/\")\n        .send()\n        .await;\n\n    assert!(result.is_err());\n}\n"
  },
  {
    "path": "tests/blocking.rs",
    "content": "mod support;\n\nuse http::header::{CONTENT_LENGTH, CONTENT_TYPE, TRANSFER_ENCODING};\nuse http_body_util::BodyExt;\n#[cfg(feature = \"json\")]\nuse std::collections::HashMap;\nuse support::server;\n\n#[test]\nfn test_response_text() {\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let url = format!(\"http://{}/text\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.content_length(), Some(5));\n\n    let body = res.text().unwrap();\n    assert_eq!(b\"Hello\", body.as_bytes());\n}\n\n#[test]\nfn donot_set_content_length_0_if_have_no_body() {\n    let server = server::http(move |req| async move {\n        let headers = req.headers();\n        assert_eq!(headers.get(CONTENT_LENGTH), None);\n        assert!(headers.get(CONTENT_TYPE).is_none());\n        assert!(headers.get(TRANSFER_ENCODING).is_none());\n        http::Response::default()\n    });\n\n    let url = format!(\"http://{}/content-length\", server.addr());\n    let res = reqwest::blocking::Client::builder()\n        .no_proxy()\n        .build()\n        .expect(\"client builder\")\n        .get(&url)\n        .send()\n        .expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[test]\n#[cfg(feature = \"charset\")]\nfn test_response_non_utf_8_text() {\n    let server = server::http(move |_req| async {\n        http::Response::builder()\n            .header(\"content-type\", \"text/plain; charset=gbk\")\n            .body(b\"\\xc4\\xe3\\xba\\xc3\"[..].into())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/text\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.content_length(), Some(4));\n\n    let body = res.text().unwrap();\n    assert_eq!(\"你好\", &body);\n    assert_eq!(b\"\\xe4\\xbd\\xa0\\xe5\\xa5\\xbd\", body.as_bytes()); // Now it's utf-8\n}\n\n#[test]\n#[cfg(feature = \"json\")]\nfn test_response_json() {\n    let server = server::http(move |_req| async { http::Response::new(\"\\\"Hello\\\"\".into()) });\n\n    let url = format!(\"http://{}/json\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.content_length(), Some(7));\n\n    let body = res.json::<String>().unwrap();\n    assert_eq!(\"Hello\", body);\n}\n\n#[test]\nfn test_response_copy_to() {\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let mut res = reqwest::blocking::get(&url).unwrap();\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    let mut dst = Vec::new();\n    res.copy_to(&mut dst).unwrap();\n    assert_eq!(dst, b\"Hello\");\n}\n\n#[test]\nfn test_get() {\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.remote_addr(), Some(server.addr()));\n\n    assert_eq!(res.text().unwrap().len(), 0)\n}\n\n#[test]\nfn test_post() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"POST\");\n        assert_eq!(req.headers()[\"content-length\"], \"5\");\n\n        let data = req.into_body().collect().await.unwrap().to_bytes();\n        assert_eq!(&*data, b\"Hello\");\n\n        http::Response::default()\n    });\n\n    let url = format!(\"http://{}/2\", server.addr());\n    let res = reqwest::blocking::Client::new()\n        .post(&url)\n        .body(\"Hello\")\n        .send()\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[test]\n#[cfg(feature = \"form\")]\nfn test_post_form() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"POST\");\n        assert_eq!(req.headers()[\"content-length\"], \"24\");\n        assert_eq!(\n            req.headers()[\"content-type\"],\n            \"application/x-www-form-urlencoded\"\n        );\n\n        let data = req.into_body().collect().await.unwrap().to_bytes();\n        assert_eq!(&*data, b\"hello=world&sean=monstar\");\n\n        http::Response::default()\n    });\n\n    let form = &[(\"hello\", \"world\"), (\"sean\", \"monstar\")];\n\n    let url = format!(\"http://{}/form\", server.addr());\n    let res = reqwest::blocking::Client::new()\n        .post(&url)\n        .form(form)\n        .send()\n        .expect(\"request send\");\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n/// Calling `Response::error_for_status`` on a response with status in 4xx\n/// returns an error.\n#[test]\nfn test_error_for_status_4xx() {\n    let server = server::http(move |_req| async {\n        http::Response::builder()\n            .status(400)\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n\n    let err = res.error_for_status().unwrap_err();\n    assert!(err.is_status());\n    assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));\n}\n\n/// Calling `Response::error_for_status`` on a response with status in 5xx\n/// returns an error.\n#[test]\nfn test_error_for_status_5xx() {\n    let server = server::http(move |_req| async {\n        http::Response::builder()\n            .status(500)\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let res = reqwest::blocking::get(&url).unwrap();\n\n    let err = res.error_for_status().unwrap_err();\n    assert!(err.is_status());\n    assert_eq!(\n        err.status(),\n        Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR)\n    );\n}\n\n#[test]\nfn test_default_headers() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"reqwest-test\"], \"orly\");\n        http::Response::default()\n    });\n\n    let mut headers = http::HeaderMap::with_capacity(1);\n    headers.insert(\"reqwest-test\", \"orly\".parse().unwrap());\n    let client = reqwest::blocking::Client::builder()\n        .default_headers(headers)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let res = client.get(&url).send().unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[test]\nfn test_override_default_headers() {\n    let server = server::http(move |req| {\n        async move {\n            // not 'iamatoken'\n            assert_eq!(req.headers()[&http::header::AUTHORIZATION], \"secret\");\n            http::Response::default()\n        }\n    });\n\n    let mut headers = http::HeaderMap::with_capacity(1);\n    headers.insert(\n        http::header::AUTHORIZATION,\n        http::header::HeaderValue::from_static(\"iamatoken\"),\n    );\n    let client = reqwest::blocking::Client::builder()\n        .default_headers(headers)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/3\", server.addr());\n    let res = client\n        .get(&url)\n        .header(\n            http::header::AUTHORIZATION,\n            http::header::HeaderValue::from_static(\"secret\"),\n        )\n        .send()\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[test]\nfn test_appended_headers_not_overwritten() {\n    let server = server::http(move |req| async move {\n        let mut accepts = req.headers().get_all(\"accept\").into_iter();\n        assert_eq!(accepts.next().unwrap(), \"application/json\");\n        assert_eq!(accepts.next().unwrap(), \"application/json+hal\");\n        assert_eq!(accepts.next(), None);\n\n        http::Response::default()\n    });\n\n    let client = reqwest::blocking::Client::new();\n\n    let url = format!(\"http://{}/4\", server.addr());\n    let res = client\n        .get(&url)\n        .header(header::ACCEPT, \"application/json\")\n        .header(header::ACCEPT, \"application/json+hal\")\n        .send()\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    // make sure this also works with default headers\n    use reqwest::header;\n    let mut headers = header::HeaderMap::with_capacity(1);\n    headers.insert(\n        header::ACCEPT,\n        header::HeaderValue::from_static(\"text/html\"),\n    );\n    let client = reqwest::blocking::Client::builder()\n        .default_headers(headers)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/4\", server.addr());\n    let res = client\n        .get(&url)\n        .header(header::ACCEPT, \"application/json\")\n        .header(header::ACCEPT, \"application/json+hal\")\n        .send()\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg_attr(not(debug_assertions), ignore)]\n#[test]\n#[should_panic]\nfn test_blocking_inside_a_runtime() {\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let url = format!(\"http://{}/text\", server.addr());\n\n    let rt = tokio::runtime::Builder::new_current_thread()\n        .build()\n        .expect(\"new rt\");\n\n    rt.block_on(async move {\n        let _should_panic = reqwest::blocking::get(&url);\n    });\n}\n\n#[cfg(feature = \"default-tls\")]\n#[test]\nfn test_allowed_methods_blocking() {\n    let resp = reqwest::blocking::Client::builder()\n        .https_only(true)\n        .build()\n        .expect(\"client builder\")\n        .get(\"https://google.com\")\n        .send();\n\n    assert_eq!(resp.is_err(), false);\n\n    let resp = reqwest::blocking::Client::builder()\n        .https_only(true)\n        .build()\n        .expect(\"client builder\")\n        .get(\"http://google.com\")\n        .send();\n\n    assert_eq!(resp.is_err(), true);\n}\n\n/// Test that a [`reqwest::blocking::Body`] can be created from [`bytes::Bytes`].\n#[test]\nfn test_body_from_bytes() {\n    let body = \"abc\";\n    // No external calls are needed. Only the request building is tested.\n    let request = reqwest::blocking::Client::builder()\n        .build()\n        .expect(\"Could not build the client\")\n        .put(\"https://google.com\")\n        .body(bytes::Bytes::from(body))\n        .build()\n        .expect(\"Invalid body\");\n\n    assert_eq!(request.body().unwrap().as_bytes(), Some(body.as_bytes()));\n}\n\n#[test]\n#[cfg(feature = \"json\")]\nfn blocking_add_json_default_content_type_if_not_set_manually() {\n    use http::header::HeaderValue;\n\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let content_type = HeaderValue::from_static(\"application/vnd.api+json\");\n    let req = reqwest::blocking::Client::new()\n        .post(\"https://google.com/\")\n        .header(CONTENT_TYPE, &content_type)\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(content_type, req.headers().get(CONTENT_TYPE).unwrap());\n}\n\n#[test]\n#[cfg(feature = \"json\")]\nfn blocking_update_json_content_type_if_set_manually() {\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let req = reqwest::blocking::Client::new()\n        .post(\"https://google.com/\")\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(\"application/json\", req.headers().get(CONTENT_TYPE).unwrap());\n}\n\n#[test]\n#[cfg(feature = \"__tls\")]\nfn test_response_no_tls_info_for_http() {\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let url = format!(\"http://{}/text\", server.addr());\n\n    let client = reqwest::blocking::Client::builder()\n        .tls_info(true)\n        .build()\n        .unwrap();\n\n    let res = client.get(&url).send().unwrap();\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.content_length(), Some(5));\n    let tls_info = res.extensions().get::<reqwest::tls::TlsInfo>();\n    assert_eq!(tls_info.is_none(), true);\n\n    let body = res.text().unwrap();\n    assert_eq!(b\"Hello\", body.as_bytes());\n}\n"
  },
  {
    "path": "tests/brotli.rs",
    "content": "mod support;\nuse std::io::Read;\nuse support::server;\nuse tokio::io::AsyncWriteExt;\n\n#[tokio::test]\nasync fn brotli_response() {\n    brotli_case(10_000, 4096).await;\n}\n\n#[tokio::test]\nasync fn brotli_single_byte_chunks() {\n    brotli_case(10, 1).await;\n}\n\n#[tokio::test]\nasync fn test_brotli_empty_body() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"HEAD\");\n\n        http::Response::builder()\n            .header(\"content-encoding\", \"br\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::new();\n    let res = client\n        .head(&format!(\"http://{}/brotli\", server.addr()))\n        .send()\n        .await\n        .unwrap();\n\n    let body = res.text().await.unwrap();\n\n    assert_eq!(body, \"\");\n}\n\n#[tokio::test]\nasync fn test_accept_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"application/json\");\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"br\"));\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT,\n            reqwest::header::HeaderValue::from_static(\"application/json\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_accept_encoding_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"*/*\");\n        assert_eq!(req.headers()[\"accept-encoding\"], \"identity\");\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept-encoding\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT_ENCODING,\n            reqwest::header::HeaderValue::from_static(\"identity\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\nasync fn brotli_case(response_size: usize, chunk_size: usize) {\n    use futures_util::stream::StreamExt;\n\n    let content: String = (0..response_size)\n        .into_iter()\n        .map(|i| format!(\"test {i}\"))\n        .collect();\n\n    let mut encoder = brotli_crate::CompressorReader::new(content.as_bytes(), 4096, 5, 20);\n    let mut brotlied_content = Vec::new();\n    encoder.read_to_end(&mut brotlied_content).unwrap();\n\n    let mut response = format!(\n        \"\\\n         HTTP/1.1 200 OK\\r\\n\\\n         Server: test-accept\\r\\n\\\n         Content-Encoding: br\\r\\n\\\n         Content-Length: {}\\r\\n\\\n         \\r\\n\",\n        &brotlied_content.len()\n    )\n    .into_bytes();\n    response.extend(&brotlied_content);\n\n    let server = server::http(move |req| {\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"br\"));\n\n        let brotlied = brotlied_content.clone();\n        async move {\n            let len = brotlied.len();\n            let stream =\n                futures_util::stream::unfold((brotlied, 0), move |(brotlied, pos)| async move {\n                    let chunk = brotlied.chunks(chunk_size).nth(pos)?.to_vec();\n\n                    Some((chunk, (brotlied, pos + 1)))\n                });\n\n            let body = reqwest::Body::wrap_stream(stream.map(Ok::<_, std::convert::Infallible>));\n\n            http::Response::builder()\n                .header(\"content-encoding\", \"br\")\n                .header(\"content-length\", len)\n                .body(body)\n                .unwrap()\n        }\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/brotli\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let body = res.text().await.expect(\"text\");\n    assert_eq!(body, content);\n}\n\nconst COMPRESSED_RESPONSE_HEADERS: &[u8] = b\"HTTP/1.1 200 OK\\x0d\\x0a\\\n            Content-Type: text/plain\\x0d\\x0a\\\n            Connection: keep-alive\\x0d\\x0a\\\n            Content-Encoding: br\\x0d\\x0a\";\n\nconst RESPONSE_CONTENT: &str = \"some message here\";\n\nfn brotli_compress(input: &[u8]) -> Vec<u8> {\n    let mut encoder = brotli_crate::CompressorReader::new(input, 4096, 5, 20);\n    let mut brotlied_content = Vec::new();\n    encoder.read_to_end(&mut brotlied_content).unwrap();\n    brotlied_content\n}\n\n#[tokio::test]\nasync fn test_non_chunked_non_fragmented_response() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let brotlied_content = brotli_compress(RESPONSE_CONTENT.as_bytes());\n            let content_length_header =\n                format!(\"Content-Length: {}\\r\\n\\r\\n\", brotlied_content.len()).into_bytes();\n            let response = [\n                COMPRESSED_RESPONSE_HEADERS,\n                &content_length_header,\n                &brotlied_content,\n            ]\n            .concat();\n\n            client_socket\n                .write_all(response.as_slice())\n                .await\n                .expect(\"response write_all failed\");\n            client_socket.flush().await.expect(\"response flush failed\");\n        })\n    });\n\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_1() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let brotlied_content = brotli_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    brotlied_content.len()\n                )\n                .as_bytes(),\n                &brotlied_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_2() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let brotlied_content = brotli_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    brotlied_content.len()\n                )\n                .as_bytes(),\n                &brotlied_content,\n                b\"\\r\\n\",\n            ]\n            .concat();\n            let response_second_part = b\"0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_with_extra_bytes() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let brotlied_content = brotli_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    brotlied_content.len()\n                )\n                .as_bytes(),\n                &brotlied_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n2ab\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let err = res.text().await.expect_err(\"there must be an error\");\n    assert!(err.is_decode());\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n"
  },
  {
    "path": "tests/ci.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse support::server;\n\n#[tokio::test]\n#[should_panic(expected = \"test server should not panic\")]\nasync fn server_panics_should_propagate() {\n    let server = server::http(|_| async {\n        panic!(\"kaboom\");\n    });\n\n    let _ = reqwest::get(format!(\"http://{}/ci\", server.addr())).await;\n}\n"
  },
  {
    "path": "tests/client.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\n\nuse support::server;\n\nuse http::header::{CONTENT_LENGTH, CONTENT_TYPE, TRANSFER_ENCODING};\n#[cfg(feature = \"json\")]\nuse std::collections::HashMap;\n\nuse reqwest::Client;\nuse tokio::io::AsyncWriteExt;\n\n#[tokio::test]\nasync fn auto_headers() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"GET\");\n\n        assert_eq!(req.headers()[\"accept\"], \"*/*\");\n        assert_eq!(req.headers().get(\"user-agent\"), None);\n        if cfg!(feature = \"gzip\") {\n            assert!(req.headers()[\"accept-encoding\"]\n                .to_str()\n                .unwrap()\n                .contains(\"gzip\"));\n        }\n        if cfg!(feature = \"brotli\") {\n            assert!(req.headers()[\"accept-encoding\"]\n                .to_str()\n                .unwrap()\n                .contains(\"br\"));\n        }\n        if cfg!(feature = \"zstd\") {\n            assert!(req.headers()[\"accept-encoding\"]\n                .to_str()\n                .unwrap()\n                .contains(\"zstd\"));\n        }\n        if cfg!(feature = \"deflate\") {\n            assert!(req.headers()[\"accept-encoding\"]\n                .to_str()\n                .unwrap()\n                .contains(\"deflate\"));\n        }\n\n        http::Response::default()\n    });\n\n    let url = format!(\"http://{}/1\", server.addr());\n    let res = reqwest::Client::builder()\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.remote_addr(), Some(server.addr()));\n}\n\n#[tokio::test]\nasync fn donot_set_content_length_0_if_have_no_body() {\n    let server = server::http(move |req| async move {\n        let headers = req.headers();\n        assert_eq!(headers.get(CONTENT_LENGTH), None);\n        assert!(headers.get(CONTENT_TYPE).is_none());\n        assert!(headers.get(TRANSFER_ENCODING).is_none());\n        dbg!(&headers);\n        http::Response::default()\n    });\n\n    let url = format!(\"http://{}/content-length\", server.addr());\n    let res = reqwest::Client::builder()\n        .no_proxy()\n        .build()\n        .expect(\"client builder\")\n        .get(&url)\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn user_agent() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"user-agent\"], \"reqwest-test-agent\");\n        http::Response::default()\n    });\n\n    let url = format!(\"http://{}/ua\", server.addr());\n    let res = reqwest::Client::builder()\n        .user_agent(\"reqwest-test-agent\")\n        .build()\n        .expect(\"client builder\")\n        .get(&url)\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn response_text() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let client = Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/text\", server.addr()))\n        .send()\n        .await\n        .expect(\"Failed to get\");\n    assert_eq!(res.content_length(), Some(5));\n    let text = res.text().await.expect(\"Failed to get text\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[tokio::test]\nasync fn response_bytes() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let client = Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/bytes\", server.addr()))\n        .send()\n        .await\n        .expect(\"Failed to get\");\n    assert_eq!(res.content_length(), Some(5));\n    let bytes = res.bytes().await.expect(\"res.bytes()\");\n    assert_eq!(\"Hello\", bytes);\n}\n\n#[tokio::test]\n#[cfg(feature = \"json\")]\nasync fn response_json() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::new(\"\\\"Hello\\\"\".into()) });\n\n    let client = Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/json\", server.addr()))\n        .send()\n        .await\n        .expect(\"Failed to get\");\n    let text = res.json::<String>().await.expect(\"Failed to get json\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[tokio::test]\nasync fn body_pipe_response() {\n    use http_body_util::BodyExt;\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/get\" {\n            http::Response::new(\"pipe me\".into())\n        } else {\n            assert_eq!(req.uri(), \"/pipe\");\n            assert_eq!(req.headers()[\"content-length\"], \"7\");\n\n            let full: Vec<u8> = req\n                .into_body()\n                .collect()\n                .await\n                .expect(\"must succeed\")\n                .to_bytes()\n                .to_vec();\n\n            assert_eq!(full, b\"pipe me\");\n\n            http::Response::default()\n        }\n    });\n\n    let client = Client::new();\n\n    let res1 = client\n        .get(&format!(\"http://{}/get\", server.addr()))\n        .send()\n        .await\n        .expect(\"get1\");\n\n    assert_eq!(res1.status(), reqwest::StatusCode::OK);\n    assert_eq!(res1.content_length(), Some(7));\n\n    // and now ensure we can \"pipe\" the response to another request\n    let res2 = client\n        .post(&format!(\"http://{}/pipe\", server.addr()))\n        .body(res1)\n        .send()\n        .await\n        .expect(\"res2\");\n\n    assert_eq!(res2.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn overridden_dns_resolution_with_gai() {\n    let _ = env_logger::builder().is_test(true).try_init();\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let overridden_domain = \"rust-lang.org\";\n    let url = format!(\n        \"http://{overridden_domain}:{}/domain_override\",\n        server.addr().port()\n    );\n    let client = reqwest::Client::builder()\n        .no_proxy()\n        .resolve(overridden_domain, server.addr())\n        .build()\n        .expect(\"client builder\");\n    let req = client.get(&url);\n    let res = req.send().await.expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    let text = res.text().await.expect(\"Failed to get text\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[tokio::test]\nasync fn overridden_dns_resolution_with_gai_multiple() {\n    let _ = env_logger::builder().is_test(true).try_init();\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let overridden_domain = \"rust-lang.org\";\n    let url = format!(\n        \"http://{overridden_domain}:{}/domain_override\",\n        server.addr().port()\n    );\n    // the server runs on IPv4 localhost, so provide both IPv4 and IPv6 and let the happy eyeballs\n    // algorithm decide which address to use.\n    let client = reqwest::Client::builder()\n        .no_proxy()\n        .resolve_to_addrs(\n            overridden_domain,\n            &[\n                std::net::SocketAddr::new(\n                    std::net::IpAddr::V6(std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),\n                    server.addr().port(),\n                ),\n                server.addr(),\n            ],\n        )\n        .build()\n        .expect(\"client builder\");\n    let req = client.get(&url);\n    let res = req.send().await.expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    let text = res.text().await.expect(\"Failed to get text\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[cfg(feature = \"hickory-dns\")]\n#[tokio::test]\nasync fn overridden_dns_resolution_with_hickory_dns() {\n    let _ = env_logger::builder().is_test(true).try_init();\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let overridden_domain = \"rust-lang.org\";\n    let url = format!(\n        \"http://{overridden_domain}:{}/domain_override\",\n        server.addr().port()\n    );\n    let client = reqwest::Client::builder()\n        .no_proxy()\n        .resolve(overridden_domain, server.addr())\n        .hickory_dns(true)\n        .build()\n        .expect(\"client builder\");\n    let req = client.get(&url);\n    let res = req.send().await.expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    let text = res.text().await.expect(\"Failed to get text\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[cfg(feature = \"hickory-dns\")]\n#[tokio::test]\nasync fn overridden_dns_resolution_with_hickory_dns_multiple() {\n    let _ = env_logger::builder().is_test(true).try_init();\n    let server = server::http(move |_req| async { http::Response::new(\"Hello\".into()) });\n\n    let overridden_domain = \"rust-lang.org\";\n    let url = format!(\n        \"http://{overridden_domain}:{}/domain_override\",\n        server.addr().port()\n    );\n    // the server runs on IPv4 localhost, so provide both IPv4 and IPv6 and let the happy eyeballs\n    // algorithm decide which address to use.\n    let client = reqwest::Client::builder()\n        .no_proxy()\n        .resolve_to_addrs(\n            overridden_domain,\n            &[\n                std::net::SocketAddr::new(\n                    std::net::IpAddr::V6(std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),\n                    server.addr().port(),\n                ),\n                server.addr(),\n            ],\n        )\n        .hickory_dns(true)\n        .build()\n        .expect(\"client builder\");\n    let req = client.get(&url);\n    let res = req.send().await.expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    let text = res.text().await.expect(\"Failed to get text\");\n    assert_eq!(\"Hello\", text);\n}\n\n#[cfg(any(feature = \"__native-tls\", feature = \"__rustls\",))]\n#[test]\nfn use_preconfigured_tls_with_bogus_backend() {\n    struct DefinitelyNotTls;\n\n    reqwest::Client::builder()\n        .use_preconfigured_tls(DefinitelyNotTls)\n        .build()\n        .expect_err(\"definitely is not TLS\");\n}\n\n#[cfg(feature = \"__native-tls\")]\n#[test]\nfn use_preconfigured_native_tls_default() {\n    extern crate native_tls_crate;\n\n    let tls = native_tls_crate::TlsConnector::builder()\n        .build()\n        .expect(\"tls builder\");\n\n    reqwest::Client::builder()\n        .use_preconfigured_tls(tls)\n        .build()\n        .expect(\"preconfigured default tls\");\n}\n\n#[cfg(feature = \"rustls\")] // needs a TLS provider\n#[test]\nfn use_preconfigured_rustls_default() {\n    extern crate rustls;\n\n    let root_cert_store = rustls::RootCertStore::empty();\n    let tls = rustls::ClientConfig::builder_with_provider(std::sync::Arc::new(\n        rustls::crypto::aws_lc_rs::default_provider(),\n    ))\n    .with_safe_default_protocol_versions()\n    .unwrap()\n    .with_root_certificates(root_cert_store)\n    .with_no_client_auth();\n\n    reqwest::Client::builder()\n        .use_preconfigured_tls(tls)\n        .build()\n        .expect(\"preconfigured rustls tls\");\n}\n\n#[cfg(all(feature = \"__tls\", not(any(feature = \"http2\", feature = \"http3\")),))]\n#[tokio::test]\nasync fn http1_only() {\n    let res = reqwest::Client::builder()\n        .build()\n        .expect(\"client builder\")\n        .get(\"https://google.com\")\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.version(), reqwest::Version::HTTP_11);\n}\n\n#[cfg(feature = \"__rustls\")]\n#[tokio::test]\n#[ignore = \"Needs TLS support in the test server\"]\nasync fn http2_upgrade() {\n    let server = server::http(move |_| async move { http::Response::default() });\n\n    let url = format!(\"https://localhost:{}\", server.addr().port());\n    let res = reqwest::Client::builder()\n        .tls_danger_accept_invalid_certs(true)\n        .tls_backend_rustls()\n        .build()\n        .expect(\"client builder\")\n        .get(&url)\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    assert_eq!(res.version(), reqwest::Version::HTTP_2);\n}\n\n#[cfg(feature = \"default-tls\")]\n#[cfg_attr(feature = \"http3\", ignore = \"enabling http3 seems to break this, why?\")]\n#[tokio::test]\nasync fn test_allowed_methods() {\n    let resp = reqwest::Client::builder()\n        .https_only(true)\n        .build()\n        .expect(\"client builder\")\n        .get(\"https://google.com\")\n        .send()\n        .await;\n\n    assert!(resp.is_ok());\n\n    let resp = reqwest::Client::builder()\n        .https_only(true)\n        .build()\n        .expect(\"client builder\")\n        .get(\"http://google.com\")\n        .send()\n        .await;\n\n    assert!(resp.is_err());\n}\n\n#[test]\n#[cfg(feature = \"json\")]\nfn add_json_default_content_type_if_not_set_manually() {\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let content_type = http::HeaderValue::from_static(\"application/vnd.api+json\");\n    let req = Client::new()\n        .post(\"https://google.com/\")\n        .header(CONTENT_TYPE, &content_type)\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(content_type, req.headers().get(CONTENT_TYPE).unwrap());\n}\n\n#[test]\n#[cfg(feature = \"json\")]\nfn update_json_content_type_if_set_manually() {\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let req = Client::new()\n        .post(\"https://google.com/\")\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(\"application/json\", req.headers().get(CONTENT_TYPE).unwrap());\n}\n\n#[cfg(all(feature = \"__tls\", not(feature = \"rustls-no-provider\")))]\n#[tokio::test]\nasync fn test_tls_info() {\n    let resp = reqwest::Client::builder()\n        .tls_info(true)\n        .build()\n        .expect(\"client builder\")\n        .get(\"https://google.com\")\n        .send()\n        .await\n        .expect(\"response\");\n    let tls_info = resp.extensions().get::<reqwest::tls::TlsInfo>();\n    assert!(tls_info.is_some());\n    let tls_info = tls_info.unwrap();\n    let peer_certificate = tls_info.peer_certificate();\n    assert!(peer_certificate.is_some());\n    let der = peer_certificate.unwrap();\n    assert_eq!(der[0], 0x30); // ASN.1 SEQUENCE\n\n    let resp = reqwest::Client::builder()\n        .build()\n        .expect(\"client builder\")\n        .get(\"https://google.com\")\n        .send()\n        .await\n        .expect(\"response\");\n    let tls_info = resp.extensions().get::<reqwest::tls::TlsInfo>();\n    assert!(tls_info.is_none());\n}\n\n#[tokio::test]\nasync fn close_connection_after_idle_timeout() {\n    let mut server = server::http(move |_| async move { http::Response::default() });\n\n    let client = reqwest::Client::builder()\n        .pool_idle_timeout(std::time::Duration::from_secs(1))\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}\", server.addr());\n\n    client.get(&url).send().await.unwrap();\n\n    tokio::time::sleep(std::time::Duration::from_secs(2)).await;\n\n    assert!(server\n        .events()\n        .iter()\n        .any(|e| matches!(e, server::Event::ConnectionClosed)));\n}\n\n#[tokio::test]\nasync fn http1_reason_phrase() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            client_socket\n                .write_all(b\"HTTP/1.1 418 I'm not a teapot\\r\\nContent-Length: 0\\r\\n\\r\\n\")\n                .await\n                .expect(\"response write_all failed\");\n        })\n    });\n\n    let client = Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}\", server.addr()))\n        .send()\n        .await\n        .expect(\"Failed to get\");\n\n    assert_eq!(\n        res.error_for_status().unwrap_err().to_string(),\n        format!(\n            \"HTTP status client error (418 I'm not a teapot) for url (http://{}/)\",\n            server.addr()\n        )\n    );\n}\n\n#[tokio::test]\nasync fn error_has_url() {\n    let u = \"http://does.not.exist.local/ever\";\n    let err = reqwest::get(u).await.unwrap_err();\n    assert_eq!(err.url().map(AsRef::as_ref), Some(u), \"{err:?}\");\n}\n"
  },
  {
    "path": "tests/connector_layers.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\n\nuse std::time::Duration;\n\nuse futures_util::future::join_all;\nuse tower::layer::util::Identity;\nuse tower::limit::ConcurrencyLimitLayer;\nuse tower::timeout::TimeoutLayer;\n\nuse support::{delay_layer::DelayLayer, server};\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn non_op_layer() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(Identity::new())\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await;\n\n    assert!(res.is_ok());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn non_op_layer_with_timeout() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::Client::builder()\n        .connector_layer(Identity::new())\n        .connect_timeout(Duration::from_millis(200))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    // never returns\n    let url = \"http://192.0.2.1:81/slow\";\n\n    let res = client.get(url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn with_connect_timeout_layer_never_returning() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::Client::builder()\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(100)))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    // never returns\n    let url = \"http://192.0.2.1:81/slow\";\n\n    let res = client.get(url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn with_connect_timeout_layer_slow() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(200)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(100)))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn multiple_timeout_layers_under_threshold() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(200)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(300)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(500)))\n        .connect_timeout(Duration::from_millis(200))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await;\n\n    assert!(res.is_ok());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn multiple_timeout_layers_over_threshold() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(50)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(50)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(50)))\n        .connect_timeout(Duration::from_millis(50))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn with_concurrency_limit_layer_timeout() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(ConcurrencyLimitLayer::new(1))\n        .timeout(Duration::from_millis(200))\n        .pool_max_idle_per_host(0) // disable connection reuse to force resource contention on the concurrency limit semaphore\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    // first call succeeds since no resource contention\n    let res = client.get(url.clone()).send().await;\n    assert!(res.is_ok());\n\n    // 3 calls where the second two wait on the first and time out\n    let mut futures = Vec::new();\n    for _ in 0..3 {\n        futures.push(client.clone().get(url.clone()).send());\n    }\n\n    let all_res = join_all(futures).await;\n\n    let timed_out = all_res\n        .into_iter()\n        .any(|res| res.is_err_and(|err| err.is_timeout()));\n\n    assert!(timed_out, \"at least one request should have timed out\");\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn with_concurrency_limit_layer_success() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(200)))\n        .connector_layer(ConcurrencyLimitLayer::new(1))\n        .timeout(Duration::from_millis(1000))\n        .pool_max_idle_per_host(0) // disable connection reuse to force resource contention on the concurrency limit semaphore\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    // first call succeeds since no resource contention\n    let res = client.get(url.clone()).send().await;\n    assert!(res.is_ok());\n\n    // 3 calls of which all are individually below the inner timeout\n    // and the sum is below outer timeout which affects the final call which waited the whole time\n    let mut futures = Vec::new();\n    for _ in 0..3 {\n        futures.push(client.clone().get(url.clone()).send());\n    }\n\n    let all_res = join_all(futures).await;\n\n    for res in all_res.into_iter() {\n        assert!(\n            res.is_ok(),\n            \"neither outer long timeout or inner short timeout should be exceeded\"\n        );\n    }\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn non_op_layer_blocking_client() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::blocking::Client::builder()\n        .connector_layer(Identity::new())\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send();\n\n    assert!(res.is_ok());\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn timeout_layer_blocking_client() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::blocking::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(50)))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send();\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn concurrency_layer_blocking_client_timeout() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::blocking::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(ConcurrencyLimitLayer::new(1))\n        .timeout(Duration::from_millis(200))\n        .pool_max_idle_per_host(0) // disable connection reuse to force resource contention on the concurrency limit semaphore\n        .build()\n        .unwrap();\n\n    let res = client.get(url.clone()).send();\n\n    assert!(res.is_ok());\n\n    // 3 calls where the second two wait on the first and time out\n    let mut join_handles = Vec::new();\n    for _ in 0..3 {\n        let client = client.clone();\n        let url = url.clone();\n        let join_handle = std::thread::spawn(move || client.get(url.clone()).send());\n        join_handles.push(join_handle);\n    }\n\n    let timed_out = join_handles\n        .into_iter()\n        .any(|handle| handle.join().unwrap().is_err_and(|err| err.is_timeout()));\n\n    assert!(timed_out, \"at least one request should have timed out\");\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn concurrency_layer_blocking_client_success() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::blocking::Client::builder()\n        .connector_layer(DelayLayer::new(Duration::from_millis(100)))\n        .connector_layer(TimeoutLayer::new(Duration::from_millis(200)))\n        .connector_layer(ConcurrencyLimitLayer::new(1))\n        .timeout(Duration::from_millis(1000))\n        .pool_max_idle_per_host(0) // disable connection reuse to force resource contention on the concurrency limit semaphore\n        .build()\n        .unwrap();\n\n    let res = client.get(url.clone()).send();\n\n    assert!(res.is_ok());\n\n    // 3 calls of which all are individually below the inner timeout\n    // and the sum is below outer timeout which affects the final call which waited the whole time\n    let mut join_handles = Vec::new();\n    for _ in 0..3 {\n        let client = client.clone();\n        let url = url.clone();\n        let join_handle = std::thread::spawn(move || client.get(url.clone()).send());\n        join_handles.push(join_handle);\n    }\n\n    for handle in join_handles {\n        let res = handle.join().unwrap();\n        assert!(\n            res.is_ok(),\n            \"neither outer long timeout or inner short timeout should be exceeded\"\n        );\n    }\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn no_generic_bounds_required_for_client_new() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::Client::new();\n    let res = client.get(url).send().await;\n\n    assert!(res.is_ok());\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn no_generic_bounds_required_for_client_new_blocking() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let client = reqwest::blocking::Client::new();\n    let res = client.get(url).send();\n\n    assert!(res.is_ok());\n}\n"
  },
  {
    "path": "tests/cookie.rs",
    "content": "mod support;\nuse support::server;\n\n#[tokio::test]\nasync fn cookie_response_accessor() {\n    let server = server::http(move |_req| async move {\n        http::Response::builder()\n            .header(\"Set-Cookie\", \"key=val\")\n            .header(\n                \"Set-Cookie\",\n                \"expires=1; Expires=Wed, 21 Oct 2015 07:28:00 GMT\",\n            )\n            .header(\"Set-Cookie\", \"path=1; Path=/the-path\")\n            .header(\"Set-Cookie\", \"maxage=1; Max-Age=100\")\n            .header(\"Set-Cookie\", \"domain=1; Domain=mydomain\")\n            .header(\"Set-Cookie\", \"secure=1; Secure\")\n            .header(\"Set-Cookie\", \"httponly=1; HttpOnly\")\n            .header(\"Set-Cookie\", \"samesitelax=1; SameSite=Lax\")\n            .header(\"Set-Cookie\", \"samesitestrict=1; SameSite=Strict\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::new();\n\n    let url = format!(\"http://{}/\", server.addr());\n    let res = client.get(&url).send().await.unwrap();\n\n    let cookies = res.cookies().collect::<Vec<_>>();\n\n    // key=val\n    assert_eq!(cookies[0].name(), \"key\");\n    assert_eq!(cookies[0].value(), \"val\");\n\n    // expires\n    assert_eq!(cookies[1].name(), \"expires\");\n    assert_eq!(\n        cookies[1].expires().unwrap(),\n        std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1_445_412_480)\n    );\n\n    // path\n    assert_eq!(cookies[2].name(), \"path\");\n    assert_eq!(cookies[2].path().unwrap(), \"/the-path\");\n\n    // max-age\n    assert_eq!(cookies[3].name(), \"maxage\");\n    assert_eq!(\n        cookies[3].max_age().unwrap(),\n        std::time::Duration::from_secs(100)\n    );\n\n    // domain\n    assert_eq!(cookies[4].name(), \"domain\");\n    assert_eq!(cookies[4].domain().unwrap(), \"mydomain\");\n\n    // secure\n    assert_eq!(cookies[5].name(), \"secure\");\n    assert_eq!(cookies[5].secure(), true);\n\n    // httponly\n    assert_eq!(cookies[6].name(), \"httponly\");\n    assert_eq!(cookies[6].http_only(), true);\n\n    // samesitelax\n    assert_eq!(cookies[7].name(), \"samesitelax\");\n    assert!(cookies[7].same_site_lax());\n\n    // samesitestrict\n    assert_eq!(cookies[8].name(), \"samesitestrict\");\n    assert!(cookies[8].same_site_strict());\n}\n\n#[tokio::test]\nasync fn cookie_store_simple() {\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/2\" {\n            assert_eq!(req.headers()[\"cookie\"], \"key=val\");\n        }\n        http::Response::builder()\n            .header(\"Set-Cookie\", \"key=val; HttpOnly\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::builder()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/\", server.addr());\n    client.get(&url).send().await.unwrap();\n\n    let url = format!(\"http://{}/2\", server.addr());\n    client.get(&url).send().await.unwrap();\n}\n\n#[tokio::test]\nasync fn cookie_store_overwrite_existing() {\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/\" {\n            http::Response::builder()\n                .header(\"Set-Cookie\", \"key=val\")\n                .body(Default::default())\n                .unwrap()\n        } else if req.uri() == \"/2\" {\n            assert_eq!(req.headers()[\"cookie\"], \"key=val\");\n            http::Response::builder()\n                .header(\"Set-Cookie\", \"key=val2\")\n                .body(Default::default())\n                .unwrap()\n        } else {\n            assert_eq!(req.uri(), \"/3\");\n            assert_eq!(req.headers()[\"cookie\"], \"key=val2\");\n            http::Response::default()\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/\", server.addr());\n    client.get(&url).send().await.unwrap();\n\n    let url = format!(\"http://{}/2\", server.addr());\n    client.get(&url).send().await.unwrap();\n\n    let url = format!(\"http://{}/3\", server.addr());\n    client.get(&url).send().await.unwrap();\n}\n\n#[tokio::test]\nasync fn cookie_store_max_age() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers().get(\"cookie\"), None);\n        http::Response::builder()\n            .header(\"Set-Cookie\", \"key=val; Max-Age=0\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::builder()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n    let url = format!(\"http://{}/\", server.addr());\n    client.get(&url).send().await.unwrap();\n    client.get(&url).send().await.unwrap();\n}\n\n#[tokio::test]\nasync fn cookie_store_expires() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers().get(\"cookie\"), None);\n        http::Response::builder()\n            .header(\n                \"Set-Cookie\",\n                \"key=val; Expires=Wed, 21 Oct 2015 07:28:00 GMT\",\n            )\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::builder()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/\", server.addr());\n    client.get(&url).send().await.unwrap();\n    client.get(&url).send().await.unwrap();\n}\n\n#[tokio::test]\nasync fn cookie_store_path() {\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/\" {\n            assert_eq!(req.headers().get(\"cookie\"), None);\n            http::Response::builder()\n                .header(\"Set-Cookie\", \"key=val; Path=/subpath\")\n                .body(Default::default())\n                .unwrap()\n        } else {\n            assert_eq!(req.uri(), \"/subpath\");\n            assert_eq!(req.headers()[\"cookie\"], \"key=val\");\n            http::Response::default()\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/\", server.addr());\n    client.get(&url).send().await.unwrap();\n    client.get(&url).send().await.unwrap();\n\n    let url = format!(\"http://{}/subpath\", server.addr());\n    client.get(&url).send().await.unwrap();\n}\n"
  },
  {
    "path": "tests/deflate.rs",
    "content": "mod support;\nuse flate2::write::ZlibEncoder;\nuse flate2::Compression;\nuse std::io::Write;\nuse support::server;\nuse tokio::io::AsyncWriteExt;\n\n#[tokio::test]\nasync fn deflate_response() {\n    deflate_case(10_000, 4096).await;\n}\n\n#[tokio::test]\nasync fn deflate_single_byte_chunks() {\n    deflate_case(10, 1).await;\n}\n\n#[tokio::test]\nasync fn test_deflate_empty_body() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"HEAD\");\n\n        http::Response::builder()\n            .header(\"content-encoding\", \"deflate\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::new();\n    let res = client\n        .head(&format!(\"http://{}/deflate\", server.addr()))\n        .send()\n        .await\n        .unwrap();\n\n    let body = res.text().await.unwrap();\n\n    assert_eq!(body, \"\");\n}\n\n#[tokio::test]\nasync fn test_accept_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"application/json\");\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"deflate\"));\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT,\n            reqwest::header::HeaderValue::from_static(\"application/json\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_accept_encoding_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"*/*\");\n        assert_eq!(req.headers()[\"accept-encoding\"], \"identity\");\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept-encoding\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT_ENCODING,\n            reqwest::header::HeaderValue::from_static(\"identity\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\nasync fn deflate_case(response_size: usize, chunk_size: usize) {\n    use futures_util::stream::StreamExt;\n\n    let content: String = (0..response_size)\n        .into_iter()\n        .map(|i| format!(\"test {i}\"))\n        .collect();\n\n    let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());\n    encoder.write_all(content.as_bytes()).unwrap();\n    let deflated_content = encoder.finish().unwrap();\n\n    let mut response = format!(\n        \"\\\n         HTTP/1.1 200 OK\\r\\n\\\n         Server: test-accept\\r\\n\\\n         Content-Encoding: deflate\\r\\n\\\n         Content-Length: {}\\r\\n\\\n         \\r\\n\",\n        &deflated_content.len()\n    )\n    .into_bytes();\n    response.extend(&deflated_content);\n\n    let server = server::http(move |req| {\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"deflate\"));\n\n        let deflated = deflated_content.clone();\n        async move {\n            let len = deflated.len();\n            let stream =\n                futures_util::stream::unfold((deflated, 0), move |(deflated, pos)| async move {\n                    let chunk = deflated.chunks(chunk_size).nth(pos)?.to_vec();\n\n                    Some((chunk, (deflated, pos + 1)))\n                });\n\n            let body = reqwest::Body::wrap_stream(stream.map(Ok::<_, std::convert::Infallible>));\n\n            http::Response::builder()\n                .header(\"content-encoding\", \"deflate\")\n                .header(\"content-length\", len)\n                .body(body)\n                .unwrap()\n        }\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/deflate\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let body = res.text().await.expect(\"text\");\n    assert_eq!(body, content);\n}\n\nconst COMPRESSED_RESPONSE_HEADERS: &[u8] = b\"HTTP/1.1 200 OK\\x0d\\x0a\\\n            Content-Type: text/plain\\x0d\\x0a\\\n            Connection: keep-alive\\x0d\\x0a\\\n            Content-Encoding: deflate\\x0d\\x0a\";\n\nconst RESPONSE_CONTENT: &str = \"some message here\";\n\nfn deflate_compress(input: &[u8]) -> Vec<u8> {\n    let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());\n    encoder.write_all(input).unwrap();\n    encoder.finish().unwrap()\n}\n\n#[tokio::test]\nasync fn test_non_chunked_non_fragmented_response() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let deflated_content = deflate_compress(RESPONSE_CONTENT.as_bytes());\n            let content_length_header =\n                format!(\"Content-Length: {}\\r\\n\\r\\n\", deflated_content.len()).into_bytes();\n            let response = [\n                COMPRESSED_RESPONSE_HEADERS,\n                &content_length_header,\n                &deflated_content,\n            ]\n            .concat();\n\n            client_socket\n                .write_all(response.as_slice())\n                .await\n                .expect(\"response write_all failed\");\n            client_socket.flush().await.expect(\"response flush failed\");\n        })\n    });\n\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_1() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let deflated_content = deflate_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    deflated_content.len()\n                )\n                .as_bytes(),\n                &deflated_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_2() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let deflated_content = deflate_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    deflated_content.len()\n                )\n                .as_bytes(),\n                &deflated_content,\n                b\"\\r\\n\",\n            ]\n            .concat();\n            let response_second_part = b\"0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_with_extra_bytes() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let deflated_content = deflate_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    deflated_content.len()\n                )\n                .as_bytes(),\n                &deflated_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n2ab\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let err = res.text().await.expect_err(\"there must be an error\");\n    assert!(err.is_decode());\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n"
  },
  {
    "path": "tests/gzip.rs",
    "content": "mod support;\nuse flate2::write::GzEncoder;\nuse flate2::Compression;\nuse support::server;\n\nuse std::io::Write;\nuse std::time::Duration;\nuse tokio::io::AsyncWriteExt;\n\n#[tokio::test]\nasync fn gzip_response() {\n    gzip_case(10_000, 4096).await;\n}\n\n#[tokio::test]\nasync fn gzip_single_byte_chunks() {\n    gzip_case(10, 1).await;\n}\n\n#[tokio::test]\nasync fn test_gzip_empty_body() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"HEAD\");\n\n        http::Response::builder()\n            .header(\"content-encoding\", \"gzip\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::new();\n    let res = client\n        .head(&format!(\"http://{}/gzip\", server.addr()))\n        .send()\n        .await\n        .unwrap();\n\n    let body = res.text().await.unwrap();\n\n    assert_eq!(body, \"\");\n}\n\n#[tokio::test]\nasync fn test_accept_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"application/json\");\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"gzip\"));\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT,\n            reqwest::header::HeaderValue::from_static(\"application/json\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_accept_encoding_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"*/*\");\n        assert_eq!(req.headers()[\"accept-encoding\"], \"identity\");\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept-encoding\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT_ENCODING,\n            reqwest::header::HeaderValue::from_static(\"identity\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\nasync fn gzip_case(response_size: usize, chunk_size: usize) {\n    use futures_util::stream::StreamExt;\n\n    let content: String = (0..response_size)\n        .into_iter()\n        .map(|i| format!(\"test {i}\"))\n        .collect();\n\n    let mut encoder = GzEncoder::new(Vec::new(), Compression::default());\n    encoder.write_all(content.as_bytes()).unwrap();\n    let gzipped_content = encoder.finish().unwrap();\n\n    let mut response = format!(\n        \"\\\n         HTTP/1.1 200 OK\\r\\n\\\n         Server: test-accept\\r\\n\\\n         Content-Encoding: gzip\\r\\n\\\n         Content-Length: {}\\r\\n\\\n         \\r\\n\",\n        &gzipped_content.len()\n    )\n    .into_bytes();\n    response.extend(&gzipped_content);\n\n    let server = server::http(move |req| {\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"gzip\"));\n\n        let gzipped = gzipped_content.clone();\n        async move {\n            let len = gzipped.len();\n            let stream =\n                futures_util::stream::unfold((gzipped, 0), move |(gzipped, pos)| async move {\n                    let chunk = gzipped.chunks(chunk_size).nth(pos)?.to_vec();\n\n                    Some((chunk, (gzipped, pos + 1)))\n                });\n\n            let body = reqwest::Body::wrap_stream(stream.map(Ok::<_, std::convert::Infallible>));\n\n            http::Response::builder()\n                .header(\"content-encoding\", \"gzip\")\n                .header(\"content-length\", len)\n                .body(body)\n                .unwrap()\n        }\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/gzip\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let body = res.text().await.expect(\"text\");\n    assert_eq!(body, content);\n}\n\nconst COMPRESSED_RESPONSE_HEADERS: &[u8] = b\"HTTP/1.1 200 OK\\x0d\\x0a\\\n            Content-Type: text/plain\\x0d\\x0a\\\n            Connection: keep-alive\\x0d\\x0a\\\n            Content-Encoding: gzip\\x0d\\x0a\";\n\nconst RESPONSE_CONTENT: &str = \"some message here\";\n\nfn gzip_compress(input: &[u8]) -> Vec<u8> {\n    let mut encoder = GzEncoder::new(Vec::new(), Compression::default());\n    encoder.write_all(input).unwrap();\n    encoder.finish().unwrap()\n}\n\n#[tokio::test]\nasync fn test_non_chunked_non_fragmented_response() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let gzipped_content = gzip_compress(RESPONSE_CONTENT.as_bytes());\n            let content_length_header =\n                format!(\"Content-Length: {}\\r\\n\\r\\n\", gzipped_content.len()).into_bytes();\n            let response = [\n                COMPRESSED_RESPONSE_HEADERS,\n                &content_length_header,\n                &gzipped_content,\n            ]\n            .concat();\n\n            client_socket\n                .write_all(response.as_slice())\n                .await\n                .expect(\"response write_all failed\");\n            client_socket.flush().await.expect(\"response flush failed\");\n        })\n    });\n\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_1() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: Duration = Duration::from_millis(1000);\n    const DELAY_MARGIN: Duration = Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let gzipped_content = gzip_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    gzipped_content.len()\n                )\n                .as_bytes(),\n                &gzipped_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_2() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: Duration = Duration::from_millis(1000);\n    const DELAY_MARGIN: Duration = Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let gzipped_content = gzip_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    gzipped_content.len()\n                )\n                .as_bytes(),\n                &gzipped_content,\n                b\"\\r\\n\",\n            ]\n            .concat();\n            let response_second_part = b\"0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_with_extra_bytes() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: Duration = Duration::from_millis(1000);\n    const DELAY_MARGIN: Duration = Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let gzipped_content = gzip_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    gzipped_content.len()\n                )\n                .as_bytes(),\n                &gzipped_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n2ab\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let err = res.text().await.expect_err(\"there must be an error\");\n    assert!(err.is_decode());\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n"
  },
  {
    "path": "tests/http3.rs",
    "content": "#![cfg(feature = \"http3\")]\n#![cfg(not(target_arch = \"wasm32\"))]\n\nmod support;\n\nuse http::header::CONTENT_LENGTH;\nuse std::error::Error;\nuse support::server;\n\nfn assert_send_sync<T: Send + Sync>(_: &T) {}\n\n#[tokio::test]\nasync fn http3_request_full() {\n    use http_body_util::BodyExt;\n\n    let server = server::Http3::new().build(move |req| async move {\n        assert_eq!(req.headers()[CONTENT_LENGTH], \"5\");\n        let reqb = req.collect().await.unwrap().to_bytes();\n        assert_eq!(reqb, \"hello\");\n        http::Response::default()\n    });\n\n    let url = format!(\"https://{}/content-length\", server.addr());\n    let res_fut = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\")\n        .post(url)\n        .version(http::Version::HTTP_3)\n        .body(\"hello\")\n        .send();\n\n    assert_send_sync(&res_fut);\n    let res = res_fut.await.expect(\"request\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\nasync fn find_free_tcp_addr() -> std::net::SocketAddr {\n    let listener = tokio::net::TcpListener::bind(\"[::1]:0\").await.unwrap();\n    listener.local_addr().unwrap()\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_failed_connection() {\n    let addr = find_free_tcp_addr().await;\n    let port = addr.port();\n\n    let url = format!(\"https://[::1]:{port}/\");\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .http3_max_idle_timeout(std::time::Duration::from_millis(20))\n        .build()\n        .expect(\"client builder\");\n\n    let err = client\n        .get(&url)\n        .version(http::Version::HTTP_3)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = err\n        .source()\n        .unwrap()\n        .source()\n        .unwrap()\n        .downcast_ref::<quinn::ConnectionError>()\n        .unwrap();\n    assert_eq!(*err, quinn::ConnectionError::TimedOut);\n\n    let err = client\n        .get(&url)\n        .version(http::Version::HTTP_3)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = err\n        .source()\n        .unwrap()\n        .source()\n        .unwrap()\n        .downcast_ref::<quinn::ConnectionError>()\n        .unwrap();\n    assert_eq!(*err, quinn::ConnectionError::TimedOut);\n\n    let server = server::Http3::new()\n        .with_addr(addr)\n        .build(|_| async { http::Response::default() });\n\n    let res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .body(\"hello\")\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    drop(server);\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_concurrent_request() {\n    let server = server::Http3::new().build(|req| async move {\n        let mut res = http::Response::default();\n        *res.body_mut() = reqwest::Body::from(format!(\"hello {}\", req.uri().path()));\n        res\n    });\n    let addr = server.addr();\n\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .http3_max_idle_timeout(std::time::Duration::from_millis(20))\n        .build()\n        .expect(\"client builder\");\n\n    let mut tasks = vec![];\n    for i in 0..10 {\n        let client = client.clone();\n        tasks.push(async move {\n            let url = format!(\"https://{}/{}\", addr, i);\n\n            client\n                .post(&url)\n                .version(http::Version::HTTP_3)\n                .send()\n                .await\n                .expect(\"request\")\n        });\n    }\n\n    let handlers = tasks.into_iter().map(tokio::spawn).collect::<Vec<_>>();\n\n    for (i, handler) in handlers.into_iter().enumerate() {\n        let result = handler.await.unwrap();\n\n        assert_eq!(result.version(), http::Version::HTTP_3);\n        assert_eq!(result.status(), reqwest::StatusCode::OK);\n\n        let body = result.text().await.unwrap();\n        assert_eq!(body, format!(\"hello /{}\", i));\n    }\n\n    drop(server);\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_h3_stop_sending_before_response_no_error() {\n    // Order of payloads:\n    // 1. Server: Response headers\n    // 2. Server: STOP_SENDING\n    // 3. Server: Response body chunk, ensures following happens after STOP_SENDING\n    // 4. Client: Request close\n    // 5. Server: Response body chunk and close\n\n    let (response_tx, response_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let response_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(response_rx)));\n    let server_response_rx = response_rx.clone();\n\n    let server = server::Http3::new().build_with_stop_sending_before_response(\n        move |_| {\n            let server_response_rx = server_response_rx.clone();\n            async move {\n                let response_rx = server_response_rx.lock().unwrap().take().unwrap();\n                let response_stream =\n                    futures_util::stream::unfold(response_rx, |mut rx| async move {\n                        rx.recv().await.map(|chunk| {\n                            (\n                                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                                rx,\n                            )\n                        })\n                    });\n                let response_body =\n                    reqwest::Body::wrap(http_body_util::StreamBody::new(response_stream));\n                http::Response::new(response_body)\n            }\n        },\n        h3::error::Code::H3_NO_ERROR,\n    );\n\n    let (request_tx, request_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let request_stream = futures_util::stream::unfold(request_rx, |mut rx| async move {\n        rx.recv().await.map(|chunk| {\n            (\n                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                rx,\n            )\n        })\n    });\n    let request_body = reqwest::Body::wrap(http_body_util::StreamBody::new(request_stream));\n\n    let url = format!(\"https://{}/\", server.addr());\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\");\n\n    let mut res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .body(request_body)\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"first\"))\n        .unwrap();\n    let first = res\n        .chunk()\n        .await\n        .ok()\n        .flatten()\n        .expect(\"missing first response chunk\");\n    assert_eq!(first, bytes::Bytes::from_static(b\"first\"));\n\n    drop(request_tx);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"second\"))\n        .unwrap();\n    drop(response_tx);\n\n    let second = res\n        .chunk()\n        .await\n        .ok()\n        .flatten()\n        .expect(\"missing second response chunk\");\n    assert_eq!(second, bytes::Bytes::from_static(b\"second\"));\n    assert!(res.chunk().await.expect(\"read response eof\").is_none());\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_h3_stop_sending_before_response_no_error_request_body() {\n    // Order of payloads:\n    // 1. Server: Response headers\n    // 2. Server: STOP_SENDING\n    // 3. Server: Response body chunk, ensures following happens after STOP_SENDING\n    // 4. Client: Request body chunk and close\n    // 5. Server: Response body chunk and close\n\n    let (response_tx, response_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let response_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(response_rx)));\n    let server_response_rx = response_rx.clone();\n\n    let server = server::Http3::new().build_with_stop_sending_before_response(\n        move |_| {\n            let server_response_rx = server_response_rx.clone();\n            async move {\n                let response_rx = server_response_rx.lock().unwrap().take().unwrap();\n                let response_stream =\n                    futures_util::stream::unfold(response_rx, |mut rx| async move {\n                        rx.recv().await.map(|chunk| {\n                            (\n                                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                                rx,\n                            )\n                        })\n                    });\n                let response_body =\n                    reqwest::Body::wrap(http_body_util::StreamBody::new(response_stream));\n                http::Response::new(response_body)\n            }\n        },\n        h3::error::Code::H3_NO_ERROR,\n    );\n\n    let (request_tx, request_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let request_stream = futures_util::stream::unfold(request_rx, |mut rx| async move {\n        rx.recv().await.map(|chunk| {\n            (\n                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                rx,\n            )\n        })\n    });\n    let request_body = reqwest::Body::wrap(http_body_util::StreamBody::new(request_stream));\n\n    let url = format!(\"https://{}/\", server.addr());\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\");\n\n    let mut res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .body(request_body)\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"first\"))\n        .unwrap();\n    let first = res\n        .chunk()\n        .await\n        .ok()\n        .flatten()\n        .expect(\"missing first response chunk\");\n    assert_eq!(first, bytes::Bytes::from_static(b\"first\"));\n\n    request_tx\n        .send(bytes::Bytes::from_static(b\"late request chunk\"))\n        .unwrap();\n    drop(request_tx);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"second\"))\n        .unwrap();\n    drop(response_tx);\n\n    let second = res\n        .chunk()\n        .await\n        .ok()\n        .flatten()\n        .expect(\"missing second response chunk\");\n    assert_eq!(second, bytes::Bytes::from_static(b\"second\"));\n    assert!(res.chunk().await.expect(\"read response eof\").is_none());\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_h3_stop_sending_before_response_internal_error() {\n    // Order of payloads:\n    // 1. Server: Response headers\n    // 2. Server: STOP_SENDING with error\n    // 3. Server: Response body chunk, ensures following happens after STOP_SENDING\n    // 4. Client: Request close - returns error\n\n    let (response_tx, response_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let response_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(response_rx)));\n    let server_response_rx = response_rx.clone();\n\n    let server = server::Http3::new().build_with_stop_sending_before_response(\n        move |_| {\n            let server_response_rx = server_response_rx.clone();\n            async move {\n                let response_rx = server_response_rx.lock().unwrap().take().unwrap();\n                let response_stream =\n                    futures_util::stream::unfold(response_rx, |mut rx| async move {\n                        rx.recv().await.map(|chunk| {\n                            (\n                                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                                rx,\n                            )\n                        })\n                    });\n                let response_body =\n                    reqwest::Body::wrap(http_body_util::StreamBody::new(response_stream));\n                http::Response::new(response_body)\n            }\n        },\n        h3::error::Code::H3_INTERNAL_ERROR,\n    );\n\n    let (request_tx, request_rx) = tokio::sync::mpsc::unbounded_channel::<bytes::Bytes>();\n    let request_stream = futures_util::stream::unfold(request_rx, |mut rx| async move {\n        rx.recv().await.map(|chunk| {\n            (\n                Ok::<_, std::convert::Infallible>(hyper::body::Frame::data(chunk)),\n                rx,\n            )\n        })\n    });\n    let request_body = reqwest::Body::wrap(http_body_util::StreamBody::new(request_stream));\n\n    let url = format!(\"https://{}/\", server.addr());\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\");\n\n    let mut res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .body(request_body)\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"first\"))\n        .expect(\"send first response chunk\");\n    let first = res\n        .chunk()\n        .await\n        .ok()\n        .flatten()\n        .expect(\"missing first response chunk\");\n    assert_eq!(first, bytes::Bytes::from_static(b\"first\"));\n\n    drop(request_tx);\n\n    response_tx\n        .send(bytes::Bytes::from_static(b\"second\"))\n        .unwrap();\n    drop(response_tx);\n\n    let err = res.chunk().await.unwrap_err();\n    assert!(err.is_decode());\n    let err = err\n        .source()\n        .unwrap()\n        .source()\n        .unwrap()\n        .downcast_ref::<h3::error::StreamError>()\n        .expect(\"h3 stream error\");\n    assert!(matches!(\n        err,\n        h3::error::StreamError::RemoteTerminate {\n            code: h3::error::Code::H3_INTERNAL_ERROR,\n            ..\n        }\n    ));\n}\n\n#[cfg(feature = \"http3\")]\n#[tokio::test]\nasync fn http3_test_reconnection() {\n    use std::error::Error;\n\n    use h3::error::{ConnectionError, StreamError};\n\n    let server = server::Http3::new().build(|_| async { http::Response::default() });\n    let addr = server.addr();\n\n    let url = format!(\"https://{}/\", addr);\n    let client = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .http3_max_idle_timeout(std::time::Duration::from_millis(20))\n        .build()\n        .expect(\"client builder\");\n\n    let res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    drop(server);\n\n    let err = client\n        .get(&url)\n        .version(http::Version::HTTP_3)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = err\n        .source()\n        .unwrap()\n        .source()\n        .unwrap()\n        .downcast_ref::<StreamError>()\n        .unwrap();\n\n    assert!(matches!(\n        err,\n        StreamError::ConnectionError {\n            0: ConnectionError::Timeout { .. },\n            ..\n        }\n    ));\n\n    let server = server::Http3::new()\n        .with_addr(addr)\n        .build(|_| async { http::Response::default() });\n\n    let res = client\n        .post(&url)\n        .version(http::Version::HTTP_3)\n        .body(\"hello\")\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n    drop(server);\n}\n\n#[cfg(all(feature = \"http3\", feature = \"stream\"))]\n#[tokio::test]\nasync fn http3_request_stream() {\n    use http_body_util::BodyExt;\n\n    let server = server::Http3::new().build(move |req| async move {\n        let reqb = req.collect().await.unwrap().to_bytes();\n        assert_eq!(reqb, \"hello world\");\n        http::Response::default()\n    });\n\n    let url = format!(\"https://{}\", server.addr());\n    let body = reqwest::Body::wrap_stream(futures_util::stream::iter(vec![\n        Ok::<_, std::convert::Infallible>(\"hello\"),\n        Ok::<_, std::convert::Infallible>(\" \"),\n        Ok::<_, std::convert::Infallible>(\"world\"),\n    ]));\n\n    let res = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\")\n        .post(url)\n        .version(http::Version::HTTP_3)\n        .body(body)\n        .send()\n        .await\n        .expect(\"request\");\n\n    assert_eq!(res.version(), http::Version::HTTP_3);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(all(feature = \"http3\", feature = \"stream\"))]\n#[tokio::test]\nasync fn http3_request_stream_error() {\n    use http_body_util::BodyExt;\n\n    let server = server::Http3::new().build(move |req| async move {\n        // HTTP/3 response can start and finish before the entire request body has been received.\n        // To avoid prematurely terminating the session, collect full request body before responding.\n        let _ = req.collect().await;\n\n        http::Response::default()\n    });\n\n    let url = format!(\"https://{}\", server.addr());\n    let body = reqwest::Body::wrap_stream(futures_util::stream::iter(vec![\n        Ok::<_, std::io::Error>(\"first chunk\"),\n        Err::<_, std::io::Error>(std::io::Error::other(\"oh no!\")),\n    ]));\n\n    let res = reqwest::Client::builder()\n        .http3_prior_knowledge()\n        .danger_accept_invalid_certs(true)\n        .build()\n        .expect(\"client builder\")\n        .post(url)\n        .version(http::Version::HTTP_3)\n        .body(body)\n        .send()\n        .await;\n\n    let err = res.unwrap_err();\n    assert!(err.is_request());\n    let err = err\n        .source()\n        .unwrap()\n        .source()\n        .unwrap()\n        .downcast_ref::<reqwest::Error>()\n        .unwrap();\n    assert!(err.is_body());\n}\n"
  },
  {
    "path": "tests/multipart.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\nmod support;\nuse http_body_util::BodyExt;\nuse support::server;\n\n#[tokio::test]\nasync fn text_part() {\n    let _ = env_logger::try_init();\n\n    let form = reqwest::multipart::Form::new().text(\"foo\", \"bar\");\n\n    let expected_body = format!(\n        \"\\\n         --{0}\\r\\n\\\n         Content-Disposition: form-data; name=\\\"foo\\\"\\r\\n\\r\\n\\\n         bar\\r\\n\\\n         --{0}--\\r\\n\\\n         \",\n        form.boundary()\n    );\n\n    let ct = format!(\"multipart/form-data; boundary={}\", form.boundary());\n\n    let server = server::http(move |mut req| {\n        let ct = ct.clone();\n        let expected_body = expected_body.clone();\n        async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.headers()[\"content-type\"], ct);\n            assert_eq!(\n                req.headers()[\"content-length\"],\n                expected_body.len().to_string()\n            );\n\n            let mut full: Vec<u8> = Vec::new();\n            while let Some(item) = req.body_mut().frame().await {\n                full.extend(&*item.unwrap().into_data().unwrap());\n            }\n\n            assert_eq!(full, expected_body.as_bytes());\n\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/multipart/1\", server.addr());\n\n    let res = reqwest::Client::new()\n        .post(&url)\n        .multipart(form)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(feature = \"stream\")]\n#[tokio::test]\nasync fn stream_part() {\n    use futures_util::stream;\n    use std::future;\n\n    let _ = env_logger::try_init();\n\n    let stream = reqwest::Body::wrap_stream(stream::once(future::ready(Ok::<_, reqwest::Error>(\n        \"part1 part2\".to_owned(),\n    ))));\n    let part = reqwest::multipart::Part::stream(stream);\n\n    let form = reqwest::multipart::Form::new()\n        .text(\"foo\", \"bar\")\n        .part(\"part_stream\", part);\n\n    let expected_body = format!(\n        \"\\\n         --{0}\\r\\n\\\n         Content-Disposition: form-data; name=\\\"foo\\\"\\r\\n\\\n         \\r\\n\\\n         bar\\r\\n\\\n         --{0}\\r\\n\\\n         Content-Disposition: form-data; name=\\\"part_stream\\\"\\r\\n\\\n         \\r\\n\\\n         part1 part2\\r\\n\\\n         --{0}--\\r\\n\\\n         \",\n        form.boundary()\n    );\n\n    let ct = format!(\"multipart/form-data; boundary={}\", form.boundary());\n\n    let server = server::http(move |req| {\n        let ct = ct.clone();\n        let expected_body = expected_body.clone();\n        async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.headers()[\"content-type\"], ct);\n            assert_eq!(req.headers()[\"transfer-encoding\"], \"chunked\");\n\n            let full = req.collect().await.unwrap().to_bytes();\n\n            assert_eq!(full, expected_body.as_bytes());\n\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/multipart/1\", server.addr());\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .post(&url)\n        .multipart(form)\n        .send()\n        .await\n        .expect(\"Failed to post multipart\");\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn blocking_file_part() {\n    let _ = env_logger::try_init();\n\n    let form = reqwest::blocking::multipart::Form::new()\n        .file(\"foo\", \"Cargo.lock\")\n        .unwrap();\n\n    let fcontents = std::fs::read_to_string(\"Cargo.lock\").unwrap();\n\n    let expected_body = format!(\n        \"\\\n         --{0}\\r\\n\\\n         Content-Disposition: form-data; name=\\\"foo\\\"; filename=\\\"Cargo.lock\\\"\\r\\n\\\n         Content-Type: application/octet-stream\\r\\n\\r\\n\\\n         {1}\\r\\n\\\n         --{0}--\\r\\n\\\n         \",\n        form.boundary(),\n        fcontents\n    );\n\n    let ct = format!(\"multipart/form-data; boundary={}\", form.boundary());\n\n    let server = server::http(move |req| {\n        let ct = ct.clone();\n        let expected_body = expected_body.clone();\n        async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.headers()[\"content-type\"], ct);\n            // files know their exact size\n            assert_eq!(\n                req.headers()[\"content-length\"],\n                expected_body.len().to_string()\n            );\n\n            let full = req.collect().await.unwrap().to_bytes();\n\n            assert_eq!(full, expected_body.as_bytes());\n\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/multipart/2\", server.addr());\n\n    let res = reqwest::blocking::Client::new()\n        .post(&url)\n        .multipart(form)\n        .send()\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(feature = \"stream\")]\n#[tokio::test]\nasync fn async_impl_file_part() {\n    let _ = env_logger::try_init();\n\n    let form = reqwest::multipart::Form::new()\n        .file(\"foo\", \"Cargo.lock\")\n        .await\n        .unwrap();\n\n    let fcontents = std::fs::read_to_string(\"Cargo.lock\").unwrap();\n\n    let expected_body = format!(\n        \"\\\n         --{0}\\r\\n\\\n         Content-Disposition: form-data; name=\\\"foo\\\"; filename=\\\"Cargo.lock\\\"\\r\\n\\\n         Content-Type: application/octet-stream\\r\\n\\r\\n\\\n         {1}\\r\\n\\\n         --{0}--\\r\\n\\\n         \",\n        form.boundary(),\n        fcontents\n    );\n\n    let ct = format!(\"multipart/form-data; boundary={}\", form.boundary());\n\n    let server = server::http(move |req| {\n        let ct = ct.clone();\n        let expected_body = expected_body.clone();\n        async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.headers()[\"content-type\"], ct);\n            // files know their exact size\n            assert_eq!(\n                req.headers()[\"content-length\"],\n                expected_body.len().to_string()\n            );\n            let full = req.collect().await.unwrap().to_bytes();\n\n            assert_eq!(full, expected_body.as_bytes());\n\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/multipart/3\", server.addr());\n\n    let res = reqwest::Client::new()\n        .post(&url)\n        .multipart(form)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n"
  },
  {
    "path": "tests/not_tcp.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\n#![cfg(unix)]\n\nmod support;\n\n#[tokio::test]\nasync fn unix_socket_works() {\n    let server = support::not_tcp::uds(move |_| async move { http::Response::default() });\n\n    let res = reqwest::Client::builder()\n        .unix_socket(server.path())\n        .build()\n        .unwrap()\n        .get(\"http://yolo.local/foo\")\n        .send()\n        .await\n        .expect(\"send request\");\n\n    assert_eq!(res.status(), 200);\n}\n\n#[tokio::test]\nasync fn unix_socket_ignores_proxies() {\n    let server = support::not_tcp::uds(move |_| async move { http::Response::default() });\n\n    let res = reqwest::Client::builder()\n        .unix_socket(server.path())\n        .proxy(reqwest::Proxy::http(\"http://dont.use.me.local\").unwrap())\n        .build()\n        .unwrap()\n        .get(\"http://yolo.local/foo\")\n        .send()\n        .await\n        .expect(\"send request\");\n\n    assert_eq!(res.status(), 200);\n}\n\n// TODO: enable when test server supports TLS\n#[ignore]\n#[tokio::test]\nasync fn unix_socket_uses_tls() {\n    let server = support::not_tcp::uds(move |_| async move { http::Response::default() });\n\n    let res = reqwest::Client::builder()\n        .unix_socket(server.path())\n        .build()\n        .unwrap()\n        .get(\"https://yolo.local/foo\")\n        .send()\n        .await\n        .expect(\"send request\");\n\n    assert_eq!(res.status(), 200);\n}\n"
  },
  {
    "path": "tests/proxy.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse support::server;\n\nuse std::env;\n\nuse std::sync::LazyLock;\nuse tokio::sync::Mutex;\n\n// serialize tests that read from / write to environment variables\nstatic HTTP_PROXY_ENV_MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));\n\n#[tokio::test]\nasync fn http_proxy() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n\n        async { http::Response::default() }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::http(&proxy).unwrap())\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn http_proxy_basic_auth() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n\n        async { http::Response::default() }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .proxy(\n            reqwest::Proxy::http(&proxy)\n                .unwrap()\n                .basic_auth(\"Aladdin\", \"open sesame\"),\n        )\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn http_proxy_basic_auth_parsed() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n\n        async { http::Response::default() }\n    });\n\n    let proxy = format!(\"http://Aladdin:open sesame@{}\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::http(&proxy).unwrap())\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn system_http_proxy_basic_auth_parsed() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuc2VzYW1l\"\n        );\n\n        async { http::Response::default() }\n    });\n\n    // avoid races with other tests that change \"http_proxy\"\n    let _env_lock = HTTP_PROXY_ENV_MUTEX.lock().await;\n\n    // save system setting first.\n    let system_proxy = env::var(\"http_proxy\");\n\n    // set-up http proxy.\n    env::set_var(\n        \"http_proxy\",\n        format!(\"http://Aladdin:opensesame@{}\", server.addr()),\n    );\n\n    let res = reqwest::Client::builder()\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    // reset user setting.\n    match system_proxy {\n        Err(_) => env::remove_var(\"http_proxy\"),\n        Ok(proxy) => env::set_var(\"http_proxy\", proxy),\n    }\n}\n\n#[tokio::test]\nasync fn test_no_proxy() {\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), \"/4\");\n\n        async { http::Response::default() }\n    });\n    let proxy = format!(\"http://{}\", server.addr());\n    let url = format!(\"http://{}/4\", server.addr());\n\n    // set up proxy and use no_proxy to clear up client builder proxies.\n    let res = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::http(&proxy).unwrap())\n        .no_proxy()\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), &url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_custom_headers() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n        async { http::Response::default() }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n    let mut headers = reqwest::header::HeaderMap::new();\n    headers.insert(\n        // reqwest::header::HeaderName::from_static(\"Proxy-Authorization\"),\n        reqwest::header::PROXY_AUTHORIZATION,\n        \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\".parse().unwrap(),\n    );\n\n    let res = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::http(&proxy).unwrap().headers(headers))\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_using_system_proxy() {\n    let url = \"http://not.a.real.sub.hyper.rs.local/prox\";\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"not.a.real.sub.hyper.rs.local\");\n\n        async { http::Response::default() }\n    });\n\n    // avoid races with other tests that change \"http_proxy\"\n    let _env_lock = HTTP_PROXY_ENV_MUTEX.lock().await;\n\n    // save system setting first.\n    let system_proxy = env::var(\"http_proxy\");\n    // set-up http proxy.\n    env::set_var(\"http_proxy\", format!(\"http://{}\", server.addr()));\n\n    // system proxy is used by default\n    let res = reqwest::get(url).await.unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    // reset user setting.\n    match system_proxy {\n        Err(_) => env::remove_var(\"http_proxy\"),\n        Ok(proxy) => env::set_var(\"http_proxy\", proxy),\n    }\n}\n\n#[tokio::test]\nasync fn http_over_http() {\n    let url = \"http://hyper.rs.local/prox\";\n\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n\n        async { http::Response::default() }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::http(&proxy).unwrap())\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(feature = \"__tls\")]\n#[tokio::test]\nasync fn tunnel_detects_auth_required() {\n    let url = \"https://hyper.rs.local/prox\";\n\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"CONNECT\");\n        assert_eq!(req.uri(), \"hyper.rs.local:443\");\n        assert!(!req\n            .headers()\n            .contains_key(http::header::PROXY_AUTHORIZATION));\n\n        async {\n            let mut res = http::Response::default();\n            *res.status_mut() = http::StatusCode::PROXY_AUTHENTICATION_REQUIRED;\n            res\n        }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n\n    let err = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::https(&proxy).unwrap())\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = support::error::inspect(err).pop().unwrap();\n    assert!(\n        err.contains(\"auth\"),\n        \"proxy auth err expected, got: {:?}\",\n        err\n    );\n}\n\n#[cfg(feature = \"__tls\")]\n#[tokio::test]\nasync fn tunnel_includes_proxy_auth() {\n    let url = \"https://hyper.rs.local/prox\";\n\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"CONNECT\");\n        assert_eq!(req.uri(), \"hyper.rs.local:443\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n\n        async {\n            // return 400 to not actually deal with TLS tunneling\n            let mut res = http::Response::default();\n            *res.status_mut() = http::StatusCode::BAD_REQUEST;\n            res\n        }\n    });\n\n    let proxy = format!(\"http://Aladdin:open%20sesame@{}\", server.addr());\n\n    let err = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::https(&proxy).unwrap())\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = support::error::inspect(err).pop().unwrap();\n    assert!(\n        err.contains(\"unsuccessful\"),\n        \"tunnel unsuccessful expected, got: {:?}\",\n        err\n    );\n}\n\n#[cfg(feature = \"__tls\")]\n#[tokio::test]\nasync fn tunnel_includes_user_agent() {\n    let url = \"https://hyper.rs.local/prox\";\n\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"CONNECT\");\n        assert_eq!(req.uri(), \"hyper.rs.local:443\");\n        assert_eq!(req.headers()[\"user-agent\"], \"reqwest-test\");\n\n        async {\n            // return 400 to not actually deal with TLS tunneling\n            let mut res = http::Response::default();\n            *res.status_mut() = http::StatusCode::BAD_REQUEST;\n            res\n        }\n    });\n\n    let proxy = format!(\"http://{}\", server.addr());\n\n    let err = reqwest::Client::builder()\n        .proxy(reqwest::Proxy::https(&proxy).unwrap())\n        .user_agent(\"reqwest-test\")\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap_err();\n\n    let err = support::error::inspect(err).pop().unwrap();\n    assert!(\n        err.contains(\"unsuccessful\"),\n        \"tunnel unsuccessful expected, got: {:?}\",\n        err\n    );\n}\n\n#[tokio::test]\nasync fn tunnel_includes_proxy_auth_with_multiple_proxies() {\n    let url = \"http://hyper.rs.local/prox\";\n    let server1 = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.uri(), url);\n        assert_eq!(req.headers()[\"host\"], \"hyper.rs.local\");\n        assert_eq!(\n            req.headers()[\"proxy-authorization\"],\n            \"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\"\n        );\n        assert_eq!(req.headers()[\"proxy-header\"], \"proxy2\");\n        async { http::Response::default() }\n    });\n\n    let proxy_url = format!(\"http://Aladdin:open%20sesame@{}\", server1.addr());\n\n    let mut headers1 = reqwest::header::HeaderMap::new();\n    headers1.insert(\"proxy-header\", \"proxy1\".parse().unwrap());\n\n    let mut headers2 = reqwest::header::HeaderMap::new();\n    headers2.insert(\"proxy-header\", \"proxy2\".parse().unwrap());\n\n    let client = reqwest::Client::builder()\n        // When processing proxy headers, the first one is iterated,\n        // and if the current URL does not match, the proxy is skipped\n        .proxy(\n            reqwest::Proxy::https(&proxy_url)\n                .unwrap()\n                .headers(headers1.clone()),\n        )\n        // When processing proxy headers, the second one is iterated,\n        // and for the current URL matching, the proxy will be used\n        .proxy(\n            reqwest::Proxy::http(&proxy_url)\n                .unwrap()\n                .headers(headers2.clone()),\n        )\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await.unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n\n    let client = reqwest::Client::builder()\n        // When processing proxy headers, the first one is iterated,\n        // and for the current URL matching, the proxy will be used\n        .proxy(reqwest::Proxy::http(&proxy_url).unwrap().headers(headers2))\n        // When processing proxy headers, the second one is iterated,\n        // and if the current URL does not match, the proxy is skipped\n        .proxy(reqwest::Proxy::https(&proxy_url).unwrap().headers(headers1))\n        .build()\n        .unwrap();\n\n    let res = client.get(url).send().await.unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n"
  },
  {
    "path": "tests/redirect.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse http_body_util::BodyExt;\nuse reqwest::Body;\nuse support::server;\n\n#[tokio::test]\nasync fn test_redirect_301_and_302_and_303_changes_post_to_get() {\n    let client = reqwest::Client::new();\n    let codes = [301u16, 302, 303];\n\n    for &code in &codes {\n        let redirect = server::http(move |req| async move {\n            if req.method() == \"POST\" {\n                assert_eq!(req.uri(), &*format!(\"/{code}\"));\n                http::Response::builder()\n                    .status(code)\n                    .header(\"location\", \"/dst\")\n                    .header(\"server\", \"test-redirect\")\n                    .body(Body::default())\n                    .unwrap()\n            } else {\n                assert_eq!(req.method(), \"GET\");\n\n                http::Response::builder()\n                    .header(\"server\", \"test-dst\")\n                    .body(Body::default())\n                    .unwrap()\n            }\n        });\n\n        let url = format!(\"http://{}/{}\", redirect.addr(), code);\n        let dst = format!(\"http://{}/{}\", redirect.addr(), \"dst\");\n        let res = client.post(&url).send().await.unwrap();\n        assert_eq!(res.url().as_str(), dst);\n        assert_eq!(res.status(), reqwest::StatusCode::OK);\n        assert_eq!(\n            res.headers().get(reqwest::header::SERVER).unwrap(),\n            &\"test-dst\"\n        );\n    }\n}\n\n#[tokio::test]\nasync fn test_redirect_307_and_308_tries_to_get_again() {\n    let client = reqwest::Client::new();\n    let codes = [307u16, 308];\n    for &code in &codes {\n        let redirect = server::http(move |req| async move {\n            assert_eq!(req.method(), \"GET\");\n            if req.uri() == &*format!(\"/{code}\") {\n                http::Response::builder()\n                    .status(code)\n                    .header(\"location\", \"/dst\")\n                    .header(\"server\", \"test-redirect\")\n                    .body(Body::default())\n                    .unwrap()\n            } else {\n                assert_eq!(req.uri(), \"/dst\");\n\n                http::Response::builder()\n                    .header(\"server\", \"test-dst\")\n                    .body(Body::default())\n                    .unwrap()\n            }\n        });\n\n        let url = format!(\"http://{}/{}\", redirect.addr(), code);\n        let dst = format!(\"http://{}/{}\", redirect.addr(), \"dst\");\n        let res = client.get(&url).send().await.unwrap();\n        assert_eq!(res.url().as_str(), dst);\n        assert_eq!(res.status(), reqwest::StatusCode::OK);\n        assert_eq!(\n            res.headers().get(reqwest::header::SERVER).unwrap(),\n            &\"test-dst\"\n        );\n    }\n}\n\n#[tokio::test]\nasync fn test_redirect_307_and_308_tries_to_post_again() {\n    let _ = env_logger::try_init();\n    let client = reqwest::Client::new();\n    let codes = [307u16, 308];\n    for &code in &codes {\n        let redirect = server::http(move |mut req| async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.headers()[\"content-length\"], \"5\");\n\n            let data = req\n                .body_mut()\n                .frame()\n                .await\n                .unwrap()\n                .unwrap()\n                .into_data()\n                .unwrap();\n            assert_eq!(&*data, b\"Hello\");\n\n            if req.uri() == &*format!(\"/{code}\") {\n                http::Response::builder()\n                    .status(code)\n                    .header(\"location\", \"/dst\")\n                    .header(\"server\", \"test-redirect\")\n                    .body(Body::default())\n                    .unwrap()\n            } else {\n                assert_eq!(req.uri(), \"/dst\");\n\n                http::Response::builder()\n                    .header(\"server\", \"test-dst\")\n                    .body(Body::default())\n                    .unwrap()\n            }\n        });\n\n        let url = format!(\"http://{}/{}\", redirect.addr(), code);\n        let dst = format!(\"http://{}/{}\", redirect.addr(), \"dst\");\n        let res = client.post(&url).body(\"Hello\").send().await.unwrap();\n        assert_eq!(res.url().as_str(), dst);\n        assert_eq!(res.status(), reqwest::StatusCode::OK);\n        assert_eq!(\n            res.headers().get(reqwest::header::SERVER).unwrap(),\n            &\"test-dst\"\n        );\n    }\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn test_redirect_307_does_not_try_if_reader_cannot_reset() {\n    let client = reqwest::blocking::Client::new();\n    let codes = [307u16, 308];\n    for &code in &codes {\n        let redirect = server::http(move |mut req| async move {\n            assert_eq!(req.method(), \"POST\");\n            assert_eq!(req.uri(), &*format!(\"/{code}\"));\n            assert_eq!(req.headers()[\"transfer-encoding\"], \"chunked\");\n\n            let data = req\n                .body_mut()\n                .frame()\n                .await\n                .unwrap()\n                .unwrap()\n                .into_data()\n                .unwrap();\n            assert_eq!(&*data, b\"Hello\");\n\n            http::Response::builder()\n                .status(code)\n                .header(\"location\", \"/dst\")\n                .header(\"server\", \"test-redirect\")\n                .body(Body::default())\n                .unwrap()\n        });\n\n        let url = format!(\"http://{}/{}\", redirect.addr(), code);\n        let res = client\n            .post(&url)\n            .body(reqwest::blocking::Body::new(&b\"Hello\"[..]))\n            .send()\n            .unwrap();\n        assert_eq!(res.url().as_str(), url);\n        assert_eq!(res.status(), code);\n    }\n}\n\n#[tokio::test]\nasync fn test_redirect_removes_sensitive_headers() {\n    use tokio::sync::watch;\n\n    let (tx, rx) = watch::channel::<Option<std::net::SocketAddr>>(None);\n\n    let end_server = server::http(move |req| {\n        let mut rx = rx.clone();\n        async move {\n            assert_eq!(req.headers().get(\"cookie\"), None);\n\n            rx.changed().await.unwrap();\n            let mid_addr = rx.borrow().unwrap();\n            assert_eq!(\n                req.headers()[\"referer\"],\n                format!(\"http://{mid_addr}/sensitive\")\n            );\n            http::Response::default()\n        }\n    });\n\n    let end_addr = end_server.addr();\n\n    let mid_server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"cookie\"], \"foo=bar\");\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", format!(\"http://{end_addr}/end\"))\n            .body(Body::default())\n            .unwrap()\n    });\n\n    tx.send(Some(mid_server.addr())).unwrap();\n\n    reqwest::Client::builder()\n        .build()\n        .unwrap()\n        .get(&format!(\"http://{}/sensitive\", mid_server.addr()))\n        .header(\n            reqwest::header::COOKIE,\n            reqwest::header::HeaderValue::from_static(\"foo=bar\"),\n        )\n        .send()\n        .await\n        .unwrap();\n}\n\n#[tokio::test]\nasync fn test_redirect_policy_can_return_errors() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.uri(), \"/loop\");\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"/loop\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/loop\", server.addr());\n    let err = reqwest::get(&url).await.unwrap_err();\n    assert!(err.is_redirect());\n}\n\n#[tokio::test]\nasync fn test_redirect_policy_can_stop_redirects_without_an_error() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.uri(), \"/no-redirect\");\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"/dont\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/no-redirect\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .redirect(reqwest::redirect::Policy::none())\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::FOUND);\n}\n\n#[tokio::test]\nasync fn test_referer_is_not_set_if_disabled() {\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/no-refer\" {\n            http::Response::builder()\n                .status(302)\n                .header(\"location\", \"/dst\")\n                .body(Body::default())\n                .unwrap()\n        } else {\n            assert_eq!(req.uri(), \"/dst\");\n            assert_eq!(req.headers().get(\"referer\"), None);\n\n            http::Response::default()\n        }\n    });\n\n    reqwest::Client::builder()\n        .referer(false)\n        .build()\n        .unwrap()\n        .get(&format!(\"http://{}/no-refer\", server.addr()))\n        .send()\n        .await\n        .unwrap();\n}\n\n#[tokio::test]\nasync fn test_invalid_location_stops_redirect_gh484() {\n    let server = server::http(move |_req| async move {\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"http://www.yikes{KABOOM}\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/yikes\", server.addr());\n\n    let res = reqwest::get(&url).await.unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::FOUND);\n}\n\n#[tokio::test]\nasync fn test_invalid_scheme_is_rejected() {\n    let server = server::http(move |_req| async move {\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"htt://www.yikes.com/\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/yikes\", server.addr());\n\n    let err = reqwest::get(&url).await.unwrap_err();\n    assert!(err.is_builder());\n}\n\n#[cfg(feature = \"cookies\")]\n#[tokio::test]\nasync fn test_redirect_302_with_set_cookies() {\n    let code = 302;\n    let server = server::http(move |req| async move {\n        if req.uri() == \"/302\" {\n            http::Response::builder()\n                .status(302)\n                .header(\"location\", \"/dst\")\n                .header(\"set-cookie\", \"key=value\")\n                .body(Body::default())\n                .unwrap()\n        } else {\n            assert_eq!(req.uri(), \"/dst\");\n            assert_eq!(req.headers()[\"cookie\"], \"key=value\");\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/{}\", server.addr(), code);\n    let dst = format!(\"http://{}/{}\", server.addr(), \"dst\");\n\n    let client = reqwest::ClientBuilder::new()\n        .cookie_store(true)\n        .build()\n        .unwrap();\n    let res = client.get(&url).send().await.unwrap();\n\n    assert_eq!(res.url().as_str(), dst);\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[cfg(feature = \"__rustls\")]\n#[tokio::test]\n#[ignore = \"Needs TLS support in the test server\"]\nasync fn test_redirect_https_only_enforced_gh1312() {\n    let server = server::http(move |_req| async move {\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"http://insecure\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"https://{}/yikes\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .tls_danger_accept_invalid_certs(true)\n        .tls_backend_rustls()\n        .https_only(true)\n        .build()\n        .expect(\"client builder\")\n        .get(&url)\n        .send()\n        .await;\n\n    let err = res.unwrap_err();\n    assert!(err.is_redirect());\n}\n\n#[tokio::test]\nasync fn test_redirect_limit_to_1() {\n    let server = server::http(move |req| async move {\n        let i: i32 = req\n            .uri()\n            .path()\n            .rsplit('/')\n            .next()\n            .unwrap()\n            .parse::<i32>()\n            .unwrap();\n        assert!(req.uri().path().ends_with(&format!(\"/redirect/{i}\")));\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", format!(\"/redirect/{}\", i + 1))\n            .body(Body::default())\n            .unwrap()\n    });\n    // The number at the end of the uri indicates the total number of redirections\n    let url = format!(\"http://{}/redirect/0\", server.addr());\n\n    let client = reqwest::Client::builder()\n        .redirect(reqwest::redirect::Policy::limited(1))\n        .build()\n        .unwrap();\n    let res = client.get(&url).send().await.unwrap_err();\n    // If the maximum limit is 1, then the final uri should be /redirect/1\n    assert_eq!(\n        res.url().unwrap().as_str(),\n        format!(\"http://{}/redirect/1\", server.addr()).as_str()\n    );\n    assert!(res.is_redirect());\n}\n\n#[tokio::test]\nasync fn test_redirect_custom() {\n    let server = server::http(move |req| async move {\n        assert!(req.uri().path().ends_with(\"/foo\"));\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"/should_not_be_called\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/foo\", server.addr());\n\n    let res = reqwest::Client::builder()\n        .redirect(reqwest::redirect::Policy::custom(|attempt| {\n            if attempt.url().path().ends_with(\"/should_not_be_called\") {\n                attempt.stop()\n            } else {\n                attempt.follow()\n            }\n        }))\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.url().as_str(), url);\n    assert_eq!(res.status(), reqwest::StatusCode::FOUND);\n}\n\n#[tokio::test]\nasync fn test_scheme_only_check_after_policy_return_follow() {\n    let server = server::http(move |_| async move {\n        http::Response::builder()\n            .status(302)\n            .header(\"location\", \"htt://www.yikes.com/\")\n            .body(Body::default())\n            .unwrap()\n    });\n\n    let url = format!(\"http://{}/yikes\", server.addr());\n    let res = reqwest::Client::builder()\n        .redirect(reqwest::redirect::Policy::custom(|attempt| attempt.stop()))\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await;\n\n    assert!(res.is_ok());\n    assert_eq!(res.unwrap().status(), reqwest::StatusCode::FOUND);\n\n    let res = reqwest::Client::builder()\n        .redirect(reqwest::redirect::Policy::custom(|attempt| {\n            attempt.follow()\n        }))\n        .build()\n        .unwrap()\n        .get(&url)\n        .send()\n        .await;\n\n    assert!(res.is_err());\n    assert!(res.unwrap_err().is_builder());\n}\n\n#[tokio::test]\nasync fn test_redirect_301_302_303_empty_payload_headers() {\n    let client = reqwest::Client::new();\n    let codes = [301u16, 302, 303];\n    for &code in &codes {\n        let redirect = server::http(move |mut req| async move {\n            if req.method() == \"POST\" {\n                let data = req\n                    .body_mut()\n                    .frame()\n                    .await\n                    .unwrap()\n                    .unwrap()\n                    .into_data()\n                    .unwrap();\n\n                assert_eq!(&*data, b\"Hello\");\n                if req.headers().get(reqwest::header::CONTENT_LENGTH).is_some() {\n                    assert_eq!(req.headers()[reqwest::header::CONTENT_LENGTH], \"5\");\n                }\n                assert_eq!(req.uri(), &*format!(\"/{code}\"));\n\n                http::Response::builder()\n                    .header(\"location\", \"/dst\")\n                    .header(\"server\", \"test-dst\")\n                    .status(code)\n                    .body(Body::default())\n                    .unwrap()\n            } else {\n                assert_eq!(req.method(), \"GET\");\n                assert!(req.headers().get(reqwest::header::CONTENT_TYPE).is_none());\n                assert!(req.headers().get(reqwest::header::CONTENT_LENGTH).is_none());\n                assert!(req\n                    .headers()\n                    .get(reqwest::header::CONTENT_ENCODING)\n                    .is_none());\n                http::Response::builder()\n                    .header(\"server\", \"test-dst\")\n                    .body(Body::default())\n                    .unwrap()\n            }\n        });\n\n        let url = format!(\"http://{}/{}\", redirect.addr(), code);\n        let dst = format!(\"http://{}/{}\", redirect.addr(), \"dst\");\n        let res = client\n            .post(&url)\n            .body(\"Hello\")\n            .header(reqwest::header::CONTENT_TYPE, \"text/plain\")\n            .header(reqwest::header::CONTENT_LENGTH, \"5\")\n            .header(reqwest::header::CONTENT_ENCODING, \"identity\")\n            .send()\n            .await\n            .unwrap();\n        assert_eq!(res.url().as_str(), dst);\n        assert_eq!(res.status(), 200);\n        assert_eq!(\n            res.headers().get(reqwest::header::SERVER).unwrap(),\n            &\"test-dst\"\n        );\n    }\n}\n"
  },
  {
    "path": "tests/retry.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse support::server;\n\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::Arc;\n\n#[tokio::test]\nasync fn retries_apply_in_scope() {\n    let _ = env_logger::try_init();\n    let cnt = Arc::new(AtomicUsize::new(0));\n    let server = server::http(move |_req| {\n        let cnt = cnt.clone();\n        async move {\n            if cnt.fetch_add(1, Ordering::Relaxed) == 0 {\n                // first req is bad\n                http::Response::builder()\n                    .status(http::StatusCode::SERVICE_UNAVAILABLE)\n                    .body(Default::default())\n                    .unwrap()\n            } else {\n                http::Response::default()\n            }\n        }\n    });\n\n    let scope = server.addr().ip().to_string();\n    let retries = reqwest::retry::for_host(scope).classify_fn(|req_rep| {\n        if req_rep.status() == Some(http::StatusCode::SERVICE_UNAVAILABLE) {\n            req_rep.retryable()\n        } else {\n            req_rep.success()\n        }\n    });\n\n    let url = format!(\"http://{}\", server.addr());\n    let resp = reqwest::Client::builder()\n        .retry(retries)\n        .build()\n        .unwrap()\n        .get(url)\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(resp.status(), 200);\n}\n\n#[cfg(feature = \"http2\")]\n#[tokio::test(flavor = \"multi_thread\", worker_threads = 2)]\nasync fn default_retries_have_a_limit() {\n    let _ = env_logger::try_init();\n\n    let server = server::http_with_config(\n        move |req| async move {\n            assert_eq!(req.version(), http::Version::HTTP_2);\n            // refused forever\n            Err(h2::Error::from(h2::Reason::REFUSED_STREAM))\n        },\n        |_| {},\n    );\n\n    let client = reqwest::Client::builder()\n        .http2_prior_knowledge()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let _err = client.get(url).send().await.unwrap_err();\n}\n\n// NOTE: using the default \"current_thread\" runtime here would cause the test to\n// fail, because the only thread would block until `panic_rx` receives a\n// notification while the client needs to be driven to get the graceful shutdown\n// done.\n#[cfg(feature = \"http2\")]\n#[tokio::test(flavor = \"multi_thread\", worker_threads = 2)]\nasync fn highly_concurrent_requests_to_http2_server_with_low_max_concurrent_streams() {\n    let client = reqwest::Client::builder()\n        .http2_prior_knowledge()\n        .build()\n        .unwrap();\n\n    let server = server::http_with_config(\n        move |req| async move {\n            assert_eq!(req.version(), http::Version::HTTP_2);\n            Ok::<_, std::convert::Infallible>(http::Response::default())\n        },\n        |builder| {\n            builder.http2().max_concurrent_streams(1);\n        },\n    );\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let futs = (0..100).map(|_| {\n        let client = client.clone();\n        let url = url.clone();\n        async move {\n            let res = client.get(&url).send().await.unwrap();\n            assert_eq!(res.status(), reqwest::StatusCode::OK);\n        }\n    });\n    futures_util::future::join_all(futs).await;\n}\n\n#[cfg(feature = \"http2\")]\n#[tokio::test]\nasync fn highly_concurrent_requests_to_slow_http2_server_with_low_max_concurrent_streams() {\n    use support::delay_server;\n\n    let client = reqwest::Client::builder()\n        .http2_prior_knowledge()\n        .build()\n        .unwrap();\n\n    let server = delay_server::Server::new(\n        move |req| async move {\n            assert_eq!(req.version(), http::Version::HTTP_2);\n            http::Response::default()\n        },\n        |http| {\n            http.http2().max_concurrent_streams(1);\n        },\n        std::time::Duration::from_secs(2),\n    )\n    .await;\n\n    let url = format!(\"http://{}\", server.addr());\n\n    let futs = (0..100).map(|_| {\n        let client = client.clone();\n        let url = url.clone();\n        async move {\n            let res = client.get(&url).send().await.unwrap();\n            assert_eq!(res.status(), reqwest::StatusCode::OK);\n        }\n    });\n    futures_util::future::join_all(futs).await;\n\n    server.shutdown().await;\n}\n"
  },
  {
    "path": "tests/support/crl.pem",
    "content": "-----BEGIN X509 CRL-----\nMIIBnjCBhwIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJjYRcNMjQwOTI2\nMDA0MjU1WhcNMjQxMDI2MDA0MjU1WjAUMBICAQEXDTI0MDkyNjAwNDI0NlqgMDAu\nMB8GA1UdIwQYMBaAFDxOaZI8zUaGX7mXAZ9Zd8jhyC3sMAsGA1UdFAQEAgIQATAN\nBgkqhkiG9w0BAQsFAAOCAQEAsqBa289UYKAOaH2gp3yC7YBF7uVZ25i3WV/InKjK\nzT/fFzZ9rL87ofl0VuR0GPAfwLXFQ96vYUg/nrlxF/A6FmQKf9JSlVBIVXaS2uyk\nfmdVX8fdU13uD2uKThT5Fojk5nKAeui0xwjTHqe9BjyDscQ5d5pkLIJUj/JbQmRF\nD/OtEpYQZMAdHLDF0a/9v69g/evlPlpTcikAU+T8rXp45rrsuuUgyhJ00UnE41j8\nMmMi3cn23JjFTyOrYx5g/0VFUNcwZpgZSnxNvFbcoh9oHHqS+UDESrwQmkmwrVvH\na7PEJq5ZPtjUPa0i7oFNa9cC+11Doo5bxkpCWhypvgTUzw==\n-----END X509 CRL-----\n"
  },
  {
    "path": "tests/support/delay_layer.rs",
    "content": "use std::{\n    future::Future,\n    pin::Pin,\n    task::{Context, Poll},\n    time::Duration,\n};\n\nuse pin_project_lite::pin_project;\nuse tokio::time::Sleep;\nuse tower::{BoxError, Layer, Service};\n\n/// This tower layer injects an arbitrary delay before calling downstream layers.\n#[derive(Clone)]\npub struct DelayLayer {\n    delay: Duration,\n}\n\nimpl DelayLayer {\n    pub const fn new(delay: Duration) -> Self {\n        DelayLayer { delay }\n    }\n}\n\nimpl<S> Layer<S> for DelayLayer {\n    type Service = Delay<S>;\n    fn layer(&self, service: S) -> Self::Service {\n        Delay::new(service, self.delay)\n    }\n}\n\nimpl std::fmt::Debug for DelayLayer {\n    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n        f.debug_struct(\"DelayLayer\")\n            .field(\"delay\", &self.delay)\n            .finish()\n    }\n}\n\n/// This tower service injects an arbitrary delay before calling downstream layers.\n#[derive(Debug, Clone)]\npub struct Delay<S> {\n    inner: S,\n    delay: Duration,\n}\nimpl<S> Delay<S> {\n    pub fn new(inner: S, delay: Duration) -> Self {\n        Delay { inner, delay }\n    }\n}\n\nimpl<S, Request> Service<Request> for Delay<S>\nwhere\n    S: Service<Request>,\n    S::Error: Into<BoxError>,\n{\n    type Response = S::Response;\n\n    type Error = BoxError;\n\n    type Future = ResponseFuture<S::Future>;\n\n    fn poll_ready(\n        &mut self,\n        cx: &mut std::task::Context<'_>,\n    ) -> std::task::Poll<Result<(), Self::Error>> {\n        match self.inner.poll_ready(cx) {\n            Poll::Pending => Poll::Pending,\n            Poll::Ready(r) => Poll::Ready(r.map_err(Into::into)),\n        }\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        let response = self.inner.call(req);\n        let sleep = tokio::time::sleep(self.delay);\n\n        ResponseFuture::new(response, sleep)\n    }\n}\n\n// `Delay` response future\npin_project! {\n    #[derive(Debug)]\n    pub struct ResponseFuture<S> {\n        #[pin]\n        response: S,\n        #[pin]\n        sleep: Sleep,\n    }\n}\n\nimpl<S> ResponseFuture<S> {\n    pub(crate) fn new(response: S, sleep: Sleep) -> Self {\n        ResponseFuture { response, sleep }\n    }\n}\n\nimpl<F, S, E> Future for ResponseFuture<F>\nwhere\n    F: Future<Output = Result<S, E>>,\n    E: Into<BoxError>,\n{\n    type Output = Result<S, BoxError>;\n\n    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        let this = self.project();\n\n        // First poll the sleep until complete\n        match this.sleep.poll(cx) {\n            Poll::Pending => return Poll::Pending,\n            Poll::Ready(_) => {}\n        }\n\n        // Then poll the inner future\n        match this.response.poll(cx) {\n            Poll::Ready(v) => Poll::Ready(v.map_err(Into::into)),\n            Poll::Pending => Poll::Pending,\n        }\n    }\n}\n"
  },
  {
    "path": "tests/support/delay_server.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![allow(unused)]\nuse std::convert::Infallible;\nuse std::future::Future;\nuse std::net;\nuse std::time::Duration;\n\nuse futures_util::FutureExt;\nuse http::{Request, Response};\nuse hyper::service::service_fn;\nuse tokio::net::TcpListener;\nuse tokio::select;\nuse tokio::sync::oneshot;\n\n/// This server, unlike [`super::server::Server`], allows for delaying the\n/// specified amount of time after each TCP connection is established. This is\n/// useful for testing the behavior of the client when the server is slow.\n///\n/// For example, in case of HTTP/2, once the TCP/TLS connection is established,\n/// both endpoints are supposed to send a preface and an initial `SETTINGS`\n/// frame (See [RFC9113 3.4] for details). What if these frames are delayed for\n/// whatever reason? This server allows for testing such scenarios.\n///\n/// [RFC9113 3.4]: https://www.rfc-editor.org/rfc/rfc9113.html#name-http-2-connection-preface\npub struct Server {\n    addr: net::SocketAddr,\n    shutdown_tx: Option<oneshot::Sender<()>>,\n    server_terminated_rx: oneshot::Receiver<()>,\n}\n\ntype Builder = hyper_util::server::conn::auto::Builder<hyper_util::rt::TokioExecutor>;\n\nimpl Server {\n    pub async fn new<F1, Fut, F2, Bu>(func: F1, apply_config: F2, delay: Duration) -> Self\n    where\n        F1: Fn(Request<hyper::body::Incoming>) -> Fut + Clone + Send + 'static,\n        Fut: Future<Output = Response<reqwest::Body>> + Send + 'static,\n        F2: FnOnce(&mut Builder) -> Bu + Send + 'static,\n    {\n        let (shutdown_tx, shutdown_rx) = oneshot::channel();\n        let (server_terminated_tx, server_terminated_rx) = oneshot::channel();\n\n        let tcp_listener = TcpListener::bind(\"127.0.0.1:0\").await.unwrap();\n        let addr = tcp_listener.local_addr().unwrap();\n\n        tokio::spawn(async move {\n            let mut builder =\n                hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());\n            apply_config(&mut builder);\n\n            tokio::spawn(async move {\n                let builder = builder;\n                let (connection_shutdown_tx, connection_shutdown_rx) = oneshot::channel();\n                let connection_shutdown_rx = connection_shutdown_rx.shared();\n                let mut shutdown_rx = std::pin::pin!(shutdown_rx);\n\n                let mut handles = Vec::new();\n                loop {\n                    select! {\n                        _ = shutdown_rx.as_mut() => {\n                            connection_shutdown_tx.send(()).unwrap();\n                            break;\n                        }\n                        res = tcp_listener.accept() => {\n                            let (stream, _) = res.unwrap();\n                            let io = hyper_util::rt::TokioIo::new(stream);\n\n\n                            let handle = tokio::spawn({\n                                let connection_shutdown_rx = connection_shutdown_rx.clone();\n                                let func = func.clone();\n                                let svc = service_fn(move |req| {\n                                    let fut = func(req);\n                                    async move {\n                                    Ok::<_, Infallible>(fut.await)\n                                }});\n                                let builder = builder.clone();\n\n                                async move {\n                                    let fut = builder.serve_connection_with_upgrades(io, svc);\n                                    tokio::time::sleep(delay).await;\n\n                                    let mut conn = std::pin::pin!(fut);\n\n                                    select! {\n                                        _ = conn.as_mut() => {}\n                                        _ = connection_shutdown_rx => {\n                                            conn.as_mut().graceful_shutdown();\n                                            conn.await.unwrap();\n                                        }\n                                    }\n                                }\n                            });\n\n                            handles.push(handle);\n                        }\n                    }\n                }\n\n                futures_util::future::join_all(handles).await;\n                server_terminated_tx.send(()).unwrap();\n            });\n        });\n\n        Self {\n            addr,\n            shutdown_tx: Some(shutdown_tx),\n            server_terminated_rx,\n        }\n    }\n\n    pub async fn shutdown(mut self) {\n        if let Some(tx) = self.shutdown_tx.take() {\n            let _ = tx.send(());\n        }\n\n        self.server_terminated_rx.await.unwrap();\n    }\n\n    pub fn addr(&self) -> net::SocketAddr {\n        self.addr\n    }\n}\n"
  },
  {
    "path": "tests/support/error.rs",
    "content": "use std::error::Error as StdError;\n\npub fn inspect<E>(err: E) -> Vec<String>\nwhere\n    E: Into<Box<dyn StdError + Send + Sync>>,\n{\n    let berr = err.into();\n    let mut err = Some(&*berr as &(dyn StdError + 'static));\n    let mut errs = Vec::new();\n    while let Some(e) = err {\n        errs.push(e.to_string());\n        err = e.source();\n    }\n    errs\n}\n"
  },
  {
    "path": "tests/support/mod.rs",
    "content": "#![allow(dead_code)]\n\npub mod delay_layer;\npub mod delay_server;\npub mod error;\npub mod not_tcp;\npub mod server;\n\n// TODO: remove once done converting to new support server?\n#[allow(unused)]\npub static DEFAULT_USER_AGENT: &str =\n    concat!(env!(\"CARGO_PKG_NAME\"), \"/\", env!(\"CARGO_PKG_VERSION\"));\n"
  },
  {
    "path": "tests/support/not_tcp.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(unix)]\n\nuse std::convert::Infallible;\nuse std::future::Future;\nuse std::sync::mpsc as std_mpsc;\nuse std::thread;\nuse std::time::Duration;\n\nuse tokio::runtime;\nuse tokio::sync::oneshot;\n\npub struct Server {\n    path: std::path::PathBuf,\n    panic_rx: std_mpsc::Receiver<()>,\n    events_rx: std_mpsc::Receiver<Event>,\n    shutdown_tx: Option<oneshot::Sender<()>>,\n}\n\n#[non_exhaustive]\npub enum Event {\n    ConnectionClosed,\n}\n\nimpl Server {\n    pub fn path(&self) -> &std::path::Path {\n        &self.path\n    }\n\n    pub fn events(&mut self) -> Vec<Event> {\n        let mut events = Vec::new();\n        while let Ok(event) = self.events_rx.try_recv() {\n            events.push(event);\n        }\n        events\n    }\n}\n\nimpl Drop for Server {\n    fn drop(&mut self) {\n        if let Some(tx) = self.shutdown_tx.take() {\n            let _ = tx.send(());\n        }\n\n        if !::std::thread::panicking() {\n            self.panic_rx\n                .recv_timeout(Duration::from_secs(3))\n                .expect(\"test server should not panic\");\n        }\n    }\n}\n\npub fn uds<F, Fut>(func: F) -> Server\nwhere\n    F: Fn(http::Request<hyper::body::Incoming>) -> Fut + Clone + Send + 'static,\n    Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n{\n    uds_with_config(func, |_builder| {})\n}\n\ntype Builder = hyper_util::server::conn::auto::Builder<hyper_util::rt::TokioExecutor>;\n\npub fn uds_with_config<F1, Fut, F2, Bu>(func: F1, apply_config: F2) -> Server\nwhere\n    F1: Fn(http::Request<hyper::body::Incoming>) -> Fut + Clone + Send + 'static,\n    Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n    F2: FnOnce(&mut Builder) -> Bu + Send + 'static,\n{\n    // Spawn new runtime in thread to prevent reactor execution context conflict\n    let test_name = thread::current().name().unwrap_or(\"<unknown>\").to_string();\n    thread::spawn(move || {\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let path = random_tmp_path();\n        let listener = rt.block_on(async {\n            tokio::net::UnixListener::bind(&path)\n                .unwrap()\n        });\n\n        let (shutdown_tx, mut shutdown_rx) = oneshot::channel();\n        let (panic_tx, panic_rx) = std_mpsc::channel();\n        let (events_tx, events_rx) = std_mpsc::channel();\n        let tname = format!(\n            \"test({})-support-server\",\n            test_name,\n        );\n\n        let close_path = path.clone();\n\n        thread::Builder::new()\n            .name(tname)\n            .spawn(move || {\n                rt.block_on(async move {\n                    let mut builder =\n                        hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());\n                    apply_config(&mut builder);\n\n                    loop {\n                        tokio::select! {\n                            _ = &mut shutdown_rx => {\n                                break;\n                            }\n                            accepted = listener.accept() => {\n                                let (io, _) = accepted.expect(\"accepted\");\n                                let func = func.clone();\n                                let svc = hyper::service::service_fn(move |req| {\n                                    let fut = func(req);\n                                    async move { Ok::<_, Infallible>(fut.await) }\n                                });\n                                let builder = builder.clone();\n                                let events_tx = events_tx.clone();\n                                tokio::spawn(async move {\n                                    let _ = builder.serve_connection_with_upgrades(hyper_util::rt::TokioIo::new(io), svc).await;\n                                    let _ = events_tx.send(Event::ConnectionClosed);\n                                });\n                            }\n                        }\n                    }\n                    let _ = std::fs::remove_file(close_path);\n                    let _ = panic_tx.send(());\n                });\n            })\n            .expect(\"thread spawn\");\n        Server {\n            path,\n            panic_rx,\n            events_rx,\n            shutdown_tx: Some(shutdown_tx),\n        }\n    })\n    .join()\n    .unwrap()\n}\n\nfn random_tmp_path() -> std::path::PathBuf {\n    use std::hash::BuildHasher;\n\n    let mut buf = std::env::temp_dir();\n\n    // libstd uses system random to create each one\n    let rng = std::collections::hash_map::RandomState::new();\n    let n = rng.hash_one(\"reqwest-uds-sock\");\n\n    buf.push(format!(\"reqwest-test-uds-sock-{}\", n));\n\n    buf\n}\n"
  },
  {
    "path": "tests/support/server.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\nuse std::convert::Infallible;\nuse std::future::Future;\nuse std::net;\nuse std::sync::mpsc as std_mpsc;\nuse std::thread;\nuse std::time::Duration;\n\nuse tokio::io::AsyncReadExt;\nuse tokio::net::TcpStream;\nuse tokio::runtime;\nuse tokio::sync::oneshot;\n\n#[cfg(feature = \"http3\")]\nstatic CRYPTO_PROVIDER_INSTALLED: std::sync::OnceLock<bool> = std::sync::OnceLock::new();\n\npub struct Server {\n    addr: net::SocketAddr,\n    panic_rx: std_mpsc::Receiver<()>,\n    events_rx: std_mpsc::Receiver<Event>,\n    shutdown_tx: Option<oneshot::Sender<()>>,\n}\n\n#[non_exhaustive]\npub enum Event {\n    ConnectionClosed,\n}\n\nimpl Server {\n    pub fn addr(&self) -> net::SocketAddr {\n        self.addr\n    }\n\n    pub fn events(&mut self) -> Vec<Event> {\n        let mut events = Vec::new();\n        while let Ok(event) = self.events_rx.try_recv() {\n            events.push(event);\n        }\n        events\n    }\n}\n\nimpl Drop for Server {\n    fn drop(&mut self) {\n        if let Some(tx) = self.shutdown_tx.take() {\n            let _ = tx.send(());\n        }\n\n        if !::std::thread::panicking() {\n            self.panic_rx\n                .recv_timeout(Duration::from_secs(3))\n                .expect(\"test server should not panic\");\n        }\n    }\n}\n\npub fn http<F, Fut>(func: F) -> Server\nwhere\n    F: Fn(http::Request<hyper::body::Incoming>) -> Fut + Clone + Send + 'static,\n    Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n{\n    let infall = move |req| {\n        let fut = func(req);\n        async move { Ok::<_, Infallible>(fut.await) }\n    };\n    http_with_config(infall, |_builder| {})\n}\n\ntype Builder = hyper_util::server::conn::auto::Builder<hyper_util::rt::TokioExecutor>;\n\npub fn http_with_config<F1, Fut, E, F2, Bu>(func: F1, apply_config: F2) -> Server\nwhere\n    F1: Fn(http::Request<hyper::body::Incoming>) -> Fut + Clone + Send + 'static,\n    Fut: Future<Output = Result<http::Response<reqwest::Body>, E>> + Send + 'static,\n    E: Into<Box<dyn std::error::Error + Send + Sync>>,\n    F2: FnOnce(&mut Builder) -> Bu + Send + 'static,\n{\n    // Spawn new runtime in thread to prevent reactor execution context conflict\n    let test_name = thread::current().name().unwrap_or(\"<unknown>\").to_string();\n    thread::spawn(move || {\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let listener = rt.block_on(async move {\n            tokio::net::TcpListener::bind(&std::net::SocketAddr::from(([127, 0, 0, 1], 0)))\n                .await\n                .unwrap()\n        });\n        let addr = listener.local_addr().unwrap();\n\n        let (shutdown_tx, mut shutdown_rx) = oneshot::channel();\n        let (panic_tx, panic_rx) = std_mpsc::channel();\n        let (events_tx, events_rx) = std_mpsc::channel();\n        let tname = format!(\n            \"test({})-support-server\",\n            test_name,\n        );\n        thread::Builder::new()\n            .name(tname)\n            .spawn(move || {\n                rt.block_on(async move {\n                    let mut builder =\n                        hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());\n                    apply_config(&mut builder);\n                    let mut tasks = tokio::task::JoinSet::new();\n                    let graceful = hyper_util::server::graceful::GracefulShutdown::new();\n\n                    loop {\n                        tokio::select! {\n                            _ = &mut shutdown_rx => {\n                                graceful.shutdown().await;\n                                break;\n                            }\n                            accepted = listener.accept() => {\n                                let (io, _) = accepted.expect(\"accepted\");\n                                let func = func.clone();\n                                let svc = hyper::service::service_fn(func);\n                                let builder = builder.clone();\n                                let events_tx = events_tx.clone();\n                                let watcher = graceful.watcher();\n\n                                tasks.spawn(async move {\n                                    let conn = builder.serve_connection_with_upgrades(hyper_util::rt::TokioIo::new(io), svc);\n                                    let _ = watcher.watch(conn).await;\n                                    let _ = events_tx.send(Event::ConnectionClosed);\n                                });\n                            }\n                        }\n                    }\n\n                    // try to drain\n                    while let Some(result) = tasks.join_next().await {\n                        if let Err(e) = result {\n                            if e.is_panic() {\n                                std::panic::resume_unwind(e.into_panic());\n                            }\n                        }\n                    }\n                    let _ = panic_tx.send(());\n                });\n            })\n            .expect(\"thread spawn\");\n        Server {\n            addr,\n            panic_rx,\n            events_rx,\n            shutdown_tx: Some(shutdown_tx),\n        }\n    })\n    .join()\n    .unwrap()\n}\n\n#[cfg(feature = \"http3\")]\n#[derive(Debug, Default)]\npub struct Http3 {\n    addr: Option<std::net::SocketAddr>,\n}\n\n#[cfg(feature = \"http3\")]\nimpl Http3 {\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    pub fn with_addr(mut self, addr: std::net::SocketAddr) -> Self {\n        self.addr = Some(addr);\n        self\n    }\n\n    pub fn build<F1, Fut>(self, func: F1) -> Server\n    where\n        F1: Fn(\n                http::Request<\n                    http_body_util::combinators::BoxBody<bytes::Bytes, h3::error::StreamError>,\n                >,\n            ) -> Fut\n            + Clone\n            + Send\n            + 'static,\n        Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n    {\n        self.build_server(func, None)\n    }\n\n    pub fn build_with_stop_sending_before_response<F1, Fut>(\n        self,\n        func: F1,\n        code: h3::error::Code,\n    ) -> Server\n    where\n        F1: Fn(\n                http::Request<\n                    http_body_util::combinators::BoxBody<bytes::Bytes, h3::error::StreamError>,\n                >,\n            ) -> Fut\n            + Clone\n            + Send\n            + 'static,\n        Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n    {\n        self.build_server(func, Some(code))\n    }\n\n    fn build_server<F1, Fut>(\n        self,\n        func: F1,\n        stop_sending_before_response: Option<h3::error::Code>,\n    ) -> Server\n    where\n        F1: Fn(\n                http::Request<\n                    http_body_util::combinators::BoxBody<bytes::Bytes, h3::error::StreamError>,\n                >,\n            ) -> Fut\n            + Clone\n            + Send\n            + 'static,\n        Fut: Future<Output = http::Response<reqwest::Body>> + Send + 'static,\n    {\n        use bytes::Buf;\n        use http_body_util::BodyExt;\n        use quinn::crypto::rustls::QuicServerConfig;\n        use std::sync::Arc;\n\n        let addr = self.addr.unwrap_or_else(|| \"[::1]:0\".parse().unwrap());\n\n        // Spawn new runtime in thread to prevent reactor execution context conflict\n        let test_name = thread::current().name().unwrap_or(\"<unknown>\").to_string();\n        thread::spawn(move || {\n            let rt = runtime::Builder::new_current_thread()\n                .enable_all()\n                .build()\n                .expect(\"new rt\");\n\n            let cert = std::fs::read(\"tests/support/server.cert\").unwrap().into();\n            let key = std::fs::read(\"tests/support/server.key\").unwrap().try_into().unwrap();\n\n            CRYPTO_PROVIDER_INSTALLED.get_or_init(install_default_crypto_provider);\n\n            let mut tls_config = rustls::ServerConfig::builder()\n                .with_no_client_auth()\n                .with_single_cert(vec![cert], key)\n                .unwrap();\n            tls_config.max_early_data_size = u32::MAX;\n            tls_config.alpn_protocols = vec![b\"h3\".into()];\n\n            let server_config = quinn::ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(tls_config).unwrap()));\n            let endpoint = rt.block_on(async move {\n                quinn::Endpoint::server(server_config, addr).unwrap()\n            });\n            let addr = endpoint.local_addr().unwrap();\n\n            let (shutdown_tx, mut shutdown_rx) = oneshot::channel();\n            let (panic_tx, panic_rx) = std_mpsc::channel();\n            let (events_tx, events_rx) = std_mpsc::channel();\n            let tname = format!(\n                \"test({})-support-server\",\n                test_name,\n            );\n            thread::Builder::new()\n                .name(tname)\n                .spawn(move || {\n                    rt.block_on(async move {\n\n                        loop {\n                            tokio::select! {\n                                _ = &mut shutdown_rx => {\n                                    break;\n                                }\n                                Some(accepted) = endpoint.accept() => {\n                                    let conn = accepted.await.expect(\"accepted\");\n                                    let mut h3_conn = h3::server::Connection::new(h3_quinn::Connection::new(conn)).await.unwrap();\n                                    let events_tx = events_tx.clone();\n                                    let func = func.clone();\n                                    tokio::spawn(async move {\n                                        while let Ok(Some(resolver)) = h3_conn.accept().await {\n                                            let events_tx = events_tx.clone();\n                                            let func = func.clone();\n                                            tokio::spawn(async move {\n                                                if let Ok((req, stream)) = resolver.resolve_request().await {\n                                                    let (mut tx, mut rx) = stream.split();\n                                                    if let Some(code) = stop_sending_before_response {\n                                                        rx.stop_sending(code);\n                                                    }\n                                                    let body = futures_util::stream::unfold(rx, |mut rx| async move {\n                                                        match rx.recv_data().await {\n                                                            Ok(Some(mut buf)) => {\n                                                                Some((Ok(hyper::body::Frame::data(buf.copy_to_bytes(buf.remaining()))), rx))\n                                                            },\n                                                            Ok(None) => None,\n                                                            Err(err) => {\n                                                                Some((Err(err), rx))\n                                                            }\n                                                        }\n                                                    });\n                                                    let body = BodyExt::boxed(http_body_util::StreamBody::new(body));\n                                                    let resp = func(req.map(move |()| body)).await;\n                                                    let (parts, mut body) = resp.into_parts();\n                                                    let resp = http::Response::from_parts(parts, ());\n                                                    tx.send_response(resp).await.unwrap();\n\n                                                    while let Some(Ok(frame)) = body.frame().await {\n                                                        if let Ok(data) = frame.into_data() {\n                                                            tx.send_data(data).await.unwrap();\n                                                        }\n                                                    }\n                                                    tx.finish().await.unwrap();\n                                                    events_tx.send(Event::ConnectionClosed).unwrap();\n                                                }\n                                            });\n                                        }\n                                    });\n                                }\n                            }\n                        }\n                        let _ = panic_tx.send(());\n                    });\n                })\n                .expect(\"thread spawn\");\n            Server {\n                addr,\n                panic_rx,\n                events_rx,\n                shutdown_tx: Some(shutdown_tx),\n            }\n        })\n        .join()\n        .unwrap()\n    }\n}\n\n#[cfg(feature = \"http3\")]\nfn install_default_crypto_provider() -> bool {\n    #[cfg(not(any(feature = \"__rustls-ring\", feature = \"__rustls-aws-lc-rs\")))]\n    panic!(\"No provider set\");\n\n    #[cfg(all(feature = \"__rustls-ring\", not(feature = \"__rustls-aws-lc-rs\")))]\n    rustls::crypto::ring::default_provider()\n        .install_default()\n        .expect(\"failed to install the default Ring TLS provider\");\n\n    #[cfg(feature = \"__rustls-aws-lc-rs\")]\n    rustls::crypto::aws_lc_rs::default_provider()\n        .install_default()\n        .expect(\"failed to install the default TLS provider\");\n\n    true\n}\n\npub fn low_level_with_response<F>(do_response: F) -> Server\nwhere\n    for<'c> F: Fn(&'c [u8], &'c mut TcpStream) -> Box<dyn Future<Output = ()> + Send + 'c>\n        + Clone\n        + Send\n        + 'static,\n{\n    // Spawn new runtime in thread to prevent reactor execution context conflict\n    let test_name = thread::current().name().unwrap_or(\"<unknown>\").to_string();\n    thread::spawn(move || {\n        let rt = runtime::Builder::new_current_thread()\n            .enable_all()\n            .build()\n            .expect(\"new rt\");\n        let listener = rt.block_on(async move {\n            tokio::net::TcpListener::bind(&std::net::SocketAddr::from(([127, 0, 0, 1], 0)))\n                .await\n                .unwrap()\n        });\n        let addr = listener.local_addr().unwrap();\n\n        let (shutdown_tx, mut shutdown_rx) = oneshot::channel();\n        let (panic_tx, panic_rx) = std_mpsc::channel();\n        let (events_tx, events_rx) = std_mpsc::channel();\n        let tname = format!(\"test({})-support-server\", test_name,);\n        thread::Builder::new()\n            .name(tname)\n            .spawn(move || {\n                rt.block_on(async move {\n                    loop {\n                        tokio::select! {\n                            _ = &mut shutdown_rx => {\n                                break;\n                            }\n                            accepted = listener.accept() => {\n                                let (io, _) = accepted.expect(\"accepted\");\n                                let do_response = do_response.clone();\n                                let events_tx = events_tx.clone();\n                                tokio::spawn(async move {\n                                    low_level_server_client(io, do_response).await;\n                                    let _ = events_tx.send(Event::ConnectionClosed);\n                                });\n                            }\n                        }\n                    }\n                    let _ = panic_tx.send(());\n                });\n            })\n            .expect(\"thread spawn\");\n        Server {\n            addr,\n            panic_rx,\n            events_rx,\n            shutdown_tx: Some(shutdown_tx),\n        }\n    })\n    .join()\n    .unwrap()\n}\n\nasync fn low_level_server_client<F>(mut client_socket: TcpStream, do_response: F)\nwhere\n    for<'c> F: Fn(&'c [u8], &'c mut TcpStream) -> Box<dyn Future<Output = ()> + Send + 'c>,\n{\n    loop {\n        let request = low_level_read_http_request(&mut client_socket)\n            .await\n            .expect(\"read_http_request failed\");\n        if request.is_empty() {\n            // connection closed by client\n            break;\n        }\n\n        Box::into_pin(do_response(&request, &mut client_socket)).await;\n    }\n}\n\nasync fn low_level_read_http_request(\n    client_socket: &mut TcpStream,\n) -> core::result::Result<Vec<u8>, std::io::Error> {\n    let mut buf = Vec::new();\n\n    // Read until the delimiter \"\\r\\n\\r\\n\" is found\n    loop {\n        let mut temp_buffer = [0; 1024];\n        let n = client_socket.read(&mut temp_buffer).await?;\n\n        if n == 0 {\n            break;\n        }\n\n        buf.extend_from_slice(&temp_buffer[..n]);\n\n        if let Some(pos) = buf.windows(4).position(|window| window == b\"\\r\\n\\r\\n\") {\n            return Ok(buf.drain(..pos + 4).collect());\n        }\n    }\n\n    Ok(buf)\n}\n"
  },
  {
    "path": "tests/timeouts.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse support::server;\n\nuse std::time::Duration;\n\n#[tokio::test]\nasync fn client_timeout() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_millis(300)).await;\n            http::Response::default()\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n\n    let res = client.get(&url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_timeout());\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[tokio::test]\nasync fn request_timeout() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_millis(300)).await;\n            http::Response::default()\n        }\n    });\n\n    let client = reqwest::Client::builder().no_proxy().build().unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n\n    let res = client\n        .get(&url)\n        .timeout(Duration::from_millis(100))\n        .send()\n        .await;\n\n    let err = res.unwrap_err();\n\n    if cfg!(not(target_arch = \"wasm32\")) {\n        assert!(err.is_timeout() && !err.is_connect());\n    } else {\n        assert!(err.is_timeout());\n    }\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[tokio::test]\nasync fn connect_timeout() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::Client::builder()\n        .connect_timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = \"http://192.0.2.1:81/slow\";\n\n    let res = client\n        .get(url)\n        .timeout(Duration::from_millis(1000))\n        .send()\n        .await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn connect_many_timeout_succeeds() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::default() });\n    let port = server.addr().port();\n\n    let client = reqwest::Client::builder()\n        .resolve_to_addrs(\n            \"many_addrs\",\n            &[\"192.0.2.1:81\".parse().unwrap(), server.addr()],\n        )\n        .connect_timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://many_addrs:{port}/eventual\");\n\n    let _res = client\n        .get(url)\n        .timeout(Duration::from_millis(1000))\n        .send()\n        .await\n        .unwrap();\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\n#[tokio::test]\nasync fn connect_many_timeout() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::Client::builder()\n        .resolve_to_addrs(\n            \"many_addrs\",\n            &[\n                \"192.0.2.1:81\".parse().unwrap(),\n                \"192.0.2.2:81\".parse().unwrap(),\n            ],\n        )\n        .connect_timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = \"http://many_addrs:81/slow\".to_string();\n\n    let res = client\n        .get(url)\n        .timeout(Duration::from_millis(1000))\n        .send()\n        .await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_connect() && err.is_timeout());\n}\n\n#[cfg(feature = \"stream\")]\n#[tokio::test]\nasync fn response_timeout() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // immediate response, but delayed body\n            let body = reqwest::Body::wrap_stream(futures_util::stream::once(async {\n                tokio::time::sleep(Duration::from_secs(1)).await;\n                Ok::<_, std::convert::Infallible>(\"Hello\")\n            }));\n\n            http::Response::new(body)\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .timeout(Duration::from_millis(500))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n    let res = client.get(&url).send().await.expect(\"Failed to get\");\n    let body = res.text().await;\n\n    let err = body.unwrap_err();\n\n    assert!(err.is_timeout());\n}\n\n#[tokio::test]\nasync fn read_timeout_applies_to_headers() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_millis(300)).await;\n            http::Response::default()\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .read_timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n\n    let res = client.get(&url).send().await;\n\n    let err = res.unwrap_err();\n\n    assert!(err.is_timeout());\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[cfg(feature = \"stream\")]\n#[tokio::test]\nasync fn read_timeout_applies_to_body() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // immediate response, but delayed body\n            let body = reqwest::Body::wrap_stream(futures_util::stream::once(async {\n                tokio::time::sleep(Duration::from_millis(300)).await;\n                Ok::<_, std::convert::Infallible>(\"Hello\")\n            }));\n\n            http::Response::new(body)\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .read_timeout(Duration::from_millis(100))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n    let res = client.get(&url).send().await.expect(\"Failed to get\");\n    let body = res.text().await;\n\n    let err = body.unwrap_err();\n\n    assert!(err.is_timeout());\n}\n\n#[cfg(feature = \"stream\")]\n#[tokio::test]\nasync fn read_timeout_allows_slow_response_body() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| {\n        async {\n            // immediate response, but body that has slow chunks\n\n            let slow = futures_util::stream::unfold(0, |state| async move {\n                if state < 3 {\n                    tokio::time::sleep(Duration::from_millis(100)).await;\n                    Some((\n                        Ok::<_, std::convert::Infallible>(state.to_string()),\n                        state + 1,\n                    ))\n                } else {\n                    None\n                }\n            });\n            let body = reqwest::Body::wrap_stream(slow);\n\n            http::Response::new(body)\n        }\n    });\n\n    let client = reqwest::Client::builder()\n        .read_timeout(Duration::from_millis(200))\n        //.timeout(Duration::from_millis(200))\n        .no_proxy()\n        .build()\n        .unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n    let res = client.get(&url).send().await.expect(\"Failed to get\");\n    let body = res.text().await.expect(\"body text\");\n\n    assert_eq!(body, \"012\");\n}\n\n/// Tests that internal client future cancels when the oneshot channel\n/// is canceled.\n#[cfg(feature = \"blocking\")]\n#[test]\nfn timeout_closes_connection() {\n    let _ = env_logger::try_init();\n\n    // Make Client drop *after* the Server, so the background doesn't\n    // close too early.\n    let client = reqwest::blocking::Client::builder()\n        .timeout(Duration::from_millis(500))\n        .build()\n        .unwrap();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_secs(2)).await;\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/closes\", server.addr());\n    let err = client.get(&url).send().unwrap_err();\n\n    assert!(err.is_timeout());\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn timeout_blocking_request() {\n    let _ = env_logger::try_init();\n\n    // Make Client drop *after* the Server, so the background doesn't\n    // close too early.\n    let client = reqwest::blocking::Client::builder().build().unwrap();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_secs(2)).await;\n            http::Response::default()\n        }\n    });\n\n    let url = format!(\"http://{}/closes\", server.addr());\n    let err = client\n        .get(&url)\n        .timeout(Duration::from_millis(500))\n        .send()\n        .unwrap_err();\n\n    assert!(err.is_timeout());\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn connect_timeout_blocking_request() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::blocking::Client::builder()\n        .connect_timeout(Duration::from_millis(100))\n        .build()\n        .unwrap();\n\n    // never returns\n    let url = \"http://192.0.2.1:81/slow\";\n\n    let err = client.get(url).send().unwrap_err();\n\n    assert!(err.is_timeout());\n}\n\n#[cfg(feature = \"blocking\")]\n#[cfg(feature = \"stream\")]\n#[test]\nfn blocking_request_timeout_body() {\n    let _ = env_logger::try_init();\n\n    let client = reqwest::blocking::Client::builder()\n        // this should be overridden\n        .connect_timeout(Duration::from_millis(200))\n        // this should be overridden\n        .timeout(Duration::from_millis(200))\n        .build()\n        .unwrap();\n\n    let server = server::http(move |_req| {\n        async {\n            // immediate response, but delayed body\n            let body = reqwest::Body::wrap_stream(futures_util::stream::once(async {\n                tokio::time::sleep(Duration::from_secs(1)).await;\n                Ok::<_, std::convert::Infallible>(\"Hello\")\n            }));\n\n            http::Response::new(body)\n        }\n    });\n\n    let url = format!(\"http://{}/closes\", server.addr());\n    let res = client\n        .get(&url)\n        // longer than client timeout\n        .timeout(Duration::from_secs(5))\n        .send()\n        .expect(\"get response\");\n\n    let text = res.text().unwrap();\n    assert_eq!(text, \"Hello\");\n}\n\n#[cfg(feature = \"blocking\")]\n#[test]\nfn write_timeout_large_body() {\n    let _ = env_logger::try_init();\n    let body = vec![b'x'; 20_000];\n    let len = 8192;\n\n    // Make Client drop *after* the Server, so the background doesn't\n    // close too early.\n    let client = reqwest::blocking::Client::builder()\n        .timeout(Duration::from_millis(500))\n        .build()\n        .unwrap();\n\n    let server = server::http(move |_req| {\n        async {\n            // delay returning the response\n            tokio::time::sleep(Duration::from_secs(2)).await;\n            http::Response::default()\n        }\n    });\n\n    let cursor = std::io::Cursor::new(body);\n    let url = format!(\"http://{}/write-timeout\", server.addr());\n    let err = client\n        .post(&url)\n        .body(reqwest::blocking::Body::sized(cursor, len as u64))\n        .send()\n        .unwrap_err();\n\n    assert!(err.is_timeout());\n    assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));\n}\n\n#[tokio::test]\nasync fn response_body_timeout_forwards_size_hint() {\n    let _ = env_logger::try_init();\n\n    let server = server::http(move |_req| async { http::Response::new(b\"hello\".to_vec().into()) });\n\n    let client = reqwest::Client::builder().no_proxy().build().unwrap();\n\n    let url = format!(\"http://{}/slow\", server.addr());\n\n    let res = client\n        .get(&url)\n        .timeout(Duration::from_secs(1))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.content_length(), Some(5));\n}\n"
  },
  {
    "path": "tests/upgrade.rs",
    "content": "#![cfg(not(target_arch = \"wasm32\"))]\n#![cfg(not(feature = \"rustls-no-provider\"))]\nmod support;\nuse support::server;\nuse tokio::io::{AsyncReadExt, AsyncWriteExt};\n\n#[tokio::test]\nasync fn http_upgrade() {\n    let server = server::http(move |req| {\n        assert_eq!(req.method(), \"GET\");\n        assert_eq!(req.headers()[\"connection\"], \"upgrade\");\n        assert_eq!(req.headers()[\"upgrade\"], \"foobar\");\n\n        tokio::spawn(async move {\n            let mut upgraded = hyper_util::rt::TokioIo::new(hyper::upgrade::on(req).await.unwrap());\n\n            let mut buf = vec![0; 7];\n            upgraded.read_exact(&mut buf).await.unwrap();\n            assert_eq!(buf, b\"foo=bar\");\n\n            upgraded.write_all(b\"bar=foo\").await.unwrap();\n        });\n\n        async {\n            http::Response::builder()\n                .status(http::StatusCode::SWITCHING_PROTOCOLS)\n                .header(http::header::CONNECTION, \"upgrade\")\n                .header(http::header::UPGRADE, \"foobar\")\n                .body(reqwest::Body::default())\n                .unwrap()\n        }\n    });\n\n    let res = reqwest::Client::builder()\n        .build()\n        .unwrap()\n        .get(format!(\"http://{}\", server.addr()))\n        .header(http::header::CONNECTION, \"upgrade\")\n        .header(http::header::UPGRADE, \"foobar\")\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), http::StatusCode::SWITCHING_PROTOCOLS);\n    let mut upgraded = res.upgrade().await.unwrap();\n\n    upgraded.write_all(b\"foo=bar\").await.unwrap();\n\n    let mut buf = vec![];\n    upgraded.read_to_end(&mut buf).await.unwrap();\n    assert_eq!(buf, b\"bar=foo\");\n}\n"
  },
  {
    "path": "tests/wasm_simple.rs",
    "content": "#![cfg(target_arch = \"wasm32\")]\nuse std::time::Duration;\n\nuse wasm_bindgen::prelude::*;\nuse wasm_bindgen_test::*;\nwasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);\n\n#[wasm_bindgen]\nextern \"C\" {\n    // Use `js_namespace` here to bind `console.log(..)` instead of just\n    // `log(..)`\n    #[wasm_bindgen(js_namespace = console)]\n    fn log(s: &str);\n}\n\n#[wasm_bindgen_test]\nasync fn simple_example() {\n    let res = reqwest::get(\"https://hyper.rs\")\n        .await\n        .expect(\"http get example\");\n    log(&format!(\"Status: {}\", res.status()));\n\n    let body = res.text().await.expect(\"response to utf-8 text\");\n    log(&format!(\"Body:\\n\\n{body}\"));\n}\n\n#[wasm_bindgen_test]\nasync fn request_with_timeout() {\n    let client = reqwest::Client::new();\n    let err = client\n        .get(\"https://hyper.rs/not-cached\")\n        .timeout(Duration::from_millis(1))\n        .send()\n        .await\n        .expect_err(\"Expected error from aborted request\");\n\n    assert!(err.is_request());\n    assert!(err.is_timeout());\n}\n\n#[wasm_bindgen_test]\n#[cfg(feature = \"json\")]\nfn preserve_content_type_if_set_manually() {\n    use http::{header::CONTENT_TYPE, HeaderValue};\n    use reqwest::Client;\n    use std::collections::HashMap;\n\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let content_type = HeaderValue::from_static(\"application/vnd.api+json\");\n    let req = Client::new()\n        .post(\"https://google.com/\")\n        .header(CONTENT_TYPE, &content_type)\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(content_type, req.headers().get(CONTENT_TYPE).unwrap());\n}\n\n#[wasm_bindgen_test]\n#[cfg(feature = \"json\")]\nfn add_default_json_content_type_if_not_set_manually() {\n    use http::header::CONTENT_TYPE;\n    use reqwest::Client;\n    use std::collections::HashMap;\n\n    let mut map = HashMap::new();\n    map.insert(\"body\", \"json\");\n    let req = Client::new()\n        .post(\"https://google.com/\")\n        .json(&map)\n        .build()\n        .expect(\"request is not valid\");\n\n    assert_eq!(\"application/json\", req.headers().get(CONTENT_TYPE).unwrap());\n}\n"
  },
  {
    "path": "tests/zstd.rs",
    "content": "mod support;\nuse support::server;\nuse tokio::io::AsyncWriteExt;\n\n#[tokio::test]\nasync fn zstd_response() {\n    zstd_case(10_000, 4096).await;\n}\n\n#[tokio::test]\nasync fn zstd_single_byte_chunks() {\n    zstd_case(10, 1).await;\n}\n\n#[tokio::test]\nasync fn test_zstd_empty_body() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.method(), \"HEAD\");\n\n        http::Response::builder()\n            .header(\"content-encoding\", \"zstd\")\n            .body(Default::default())\n            .unwrap()\n    });\n\n    let client = reqwest::Client::new();\n    let res = client\n        .head(&format!(\"http://{}/zstd\", server.addr()))\n        .send()\n        .await\n        .unwrap();\n\n    let body = res.text().await.unwrap();\n\n    assert_eq!(body, \"\");\n}\n\n#[tokio::test]\nasync fn test_accept_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"application/json\");\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"zstd\"));\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT,\n            reqwest::header::HeaderValue::from_static(\"application/json\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\n#[tokio::test]\nasync fn test_accept_encoding_header_is_not_changed_if_set() {\n    let server = server::http(move |req| async move {\n        assert_eq!(req.headers()[\"accept\"], \"*/*\");\n        assert_eq!(req.headers()[\"accept-encoding\"], \"identity\");\n        http::Response::default()\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/accept-encoding\", server.addr()))\n        .header(\n            reqwest::header::ACCEPT_ENCODING,\n            reqwest::header::HeaderValue::from_static(\"identity\"),\n        )\n        .send()\n        .await\n        .unwrap();\n\n    assert_eq!(res.status(), reqwest::StatusCode::OK);\n}\n\nasync fn zstd_case(response_size: usize, chunk_size: usize) {\n    use futures_util::stream::StreamExt;\n\n    let content: String = (0..response_size)\n        .into_iter()\n        .map(|i| format!(\"test {i}\"))\n        .collect();\n\n    let zstded_content = zstd_crate::encode_all(content.as_bytes(), 3).unwrap();\n\n    let mut response = format!(\n        \"\\\n         HTTP/1.1 200 OK\\r\\n\\\n         Server: test-accept\\r\\n\\\n         Content-Encoding: zstd\\r\\n\\\n         Content-Length: {}\\r\\n\\\n         \\r\\n\",\n        &zstded_content.len()\n    )\n    .into_bytes();\n    response.extend(&zstded_content);\n\n    let server = server::http(move |req| {\n        assert!(req.headers()[\"accept-encoding\"]\n            .to_str()\n            .unwrap()\n            .contains(\"zstd\"));\n\n        let zstded = zstded_content.clone();\n        async move {\n            let len = zstded.len();\n            let stream =\n                futures_util::stream::unfold((zstded, 0), move |(zstded, pos)| async move {\n                    let chunk = zstded.chunks(chunk_size).nth(pos)?.to_vec();\n\n                    Some((chunk, (zstded, pos + 1)))\n                });\n\n            let body = reqwest::Body::wrap_stream(stream.map(Ok::<_, std::convert::Infallible>));\n\n            http::Response::builder()\n                .header(\"content-encoding\", \"zstd\")\n                .header(\"content-length\", len)\n                .body(body)\n                .unwrap()\n        }\n    });\n\n    let client = reqwest::Client::new();\n\n    let res = client\n        .get(&format!(\"http://{}/zstd\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let body = res.text().await.expect(\"text\");\n    assert_eq!(body, content);\n}\n\nconst COMPRESSED_RESPONSE_HEADERS: &[u8] = b\"HTTP/1.1 200 OK\\x0d\\x0a\\\n            Content-Type: text/plain\\x0d\\x0a\\\n            Connection: keep-alive\\x0d\\x0a\\\n            Content-Encoding: zstd\\x0d\\x0a\";\n\nconst RESPONSE_CONTENT: &str = \"some message here\";\n\nfn zstd_compress(input: &[u8]) -> Vec<u8> {\n    zstd_crate::encode_all(input, 3).unwrap()\n}\n\n#[tokio::test]\nasync fn test_non_chunked_non_fragmented_response() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let zstded_content = zstd_compress(RESPONSE_CONTENT.as_bytes());\n            let content_length_header =\n                format!(\"Content-Length: {}\\r\\n\\r\\n\", zstded_content.len()).into_bytes();\n            let response = [\n                COMPRESSED_RESPONSE_HEADERS,\n                &content_length_header,\n                &zstded_content,\n            ]\n            .concat();\n\n            client_socket\n                .write_all(response.as_slice())\n                .await\n                .expect(\"response write_all failed\");\n            client_socket.flush().await.expect(\"response flush failed\");\n        })\n    });\n\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n}\n\n// Big response can have multiple ZSTD frames in it\n#[tokio::test]\nasync fn test_non_chunked_non_fragmented_multiple_frames_response() {\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            // Split the content into two parts\n            let content_bytes = RESPONSE_CONTENT.as_bytes();\n            let mid = content_bytes.len() / 2;\n            // Compress each part separately to create multiple ZSTD frames\n            let compressed_part1 = zstd_crate::encode_all(&content_bytes[0..mid], 3).unwrap();\n            let compressed_part2 = zstd_crate::encode_all(&content_bytes[mid..], 3).unwrap();\n            // Concatenate the compressed frames\n            let mut zstded_content = compressed_part1;\n            zstded_content.extend_from_slice(&compressed_part2);\n            // Set Content-Length to the total length of the concatenated frames\n            let content_length_header =\n                format!(\"Content-Length: {}\\r\\n\\r\\n\", zstded_content.len()).into_bytes();\n            let response = [\n                COMPRESSED_RESPONSE_HEADERS,\n                &content_length_header,\n                &zstded_content,\n            ]\n            .concat();\n\n            client_socket\n                .write_all(response.as_slice())\n                .await\n                .expect(\"response write_all failed\");\n            client_socket.flush().await.expect(\"response flush failed\");\n        })\n    });\n\n    let res = reqwest::Client::new()\n        .get(format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_multiple_frames_in_one_chunk() {\n    // Define constants for delay and timing margin\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000); // 1-second delay\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50); // Margin for timing assertions\n\n    // Set up a low-level server\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            // Split RESPONSE_CONTENT into two parts\n            let mid = RESPONSE_CONTENT.len() / 2;\n            let part1 = &RESPONSE_CONTENT[0..mid];\n            let part2 = &RESPONSE_CONTENT[mid..];\n\n            // Compress each part separately to create two ZSTD frames\n            let compressed_part1 = zstd_compress(part1.as_bytes());\n            let compressed_part2 = zstd_compress(part2.as_bytes());\n\n            // Concatenate the frames into a single chunk's data\n            let chunk_data = [compressed_part1.as_slice(), compressed_part2.as_slice()].concat();\n\n            // Calculate the chunk size in bytes\n            let chunk_size = chunk_data.len();\n\n            // Prepare the initial response part: headers + chunk size\n            let headers = [\n                COMPRESSED_RESPONSE_HEADERS, // e.g., \"HTTP/1.1 200 OK\\r\\nContent-Encoding: zstd\\r\\n\"\n                b\"Transfer-Encoding: chunked\\r\\n\\r\\n\", // Indicate chunked encoding\n                format!(\"{:x}\\r\\n\", chunk_size).as_bytes(), // Chunk size in hex\n            ]\n            .concat();\n\n            // Send headers + chunk size + chunk data\n            client_socket\n                .write_all([headers.as_slice(), &chunk_data].concat().as_slice())\n                .await\n                .expect(\"write_all failed\");\n            client_socket.flush().await.expect(\"flush failed\");\n\n            // Introduce a delay to simulate fragmentation\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            // Send chunk terminator + final chunk\n            client_socket\n                .write_all(b\"\\r\\n0\\r\\n\\r\\n\")\n                .await\n                .expect(\"write_all failed\");\n            client_socket.flush().await.expect(\"flush failed\");\n        })\n    });\n\n    // Record the start time for delay verification\n    let start = tokio::time::Instant::now();\n\n    let res = reqwest::Client::new()\n        .get(format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"Failed to get response\");\n\n    // Verify the decompressed response matches the original content\n    assert_eq!(\n        res.text().await.expect(\"Failed to read text\"),\n        RESPONSE_CONTENT\n    );\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_connection_reuse_with_chunked_fragmented_multiple_frames_in_one_chunk() {\n    // Define constants for delay and timing margin\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000); // 1-second delay\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50); // Margin for timing assertions\n\n    // We will record the peer addresses of each client request here\n    let peer_addrs = std::sync::Arc::new(std::sync::Mutex::new(Vec::<std::net::SocketAddr>::new()));\n    let peer_addrs_clone = peer_addrs.clone();\n\n    // Set up a low-level server (it will reuse existing client connection, executing callback for each client request)\n    let server = server::low_level_with_response(move |_raw_request, client_socket| {\n        let peer_addrs = peer_addrs_clone.clone();\n        Box::new(async move {\n            // Split RESPONSE_CONTENT into two parts\n            let mid = RESPONSE_CONTENT.len() / 2;\n            let part1 = &RESPONSE_CONTENT[0..mid];\n            let part2 = &RESPONSE_CONTENT[mid..];\n\n            // Compress each part separately to create two ZSTD frames\n            let compressed_part1 = zstd_compress(part1.as_bytes());\n            let compressed_part2 = zstd_compress(part2.as_bytes());\n\n            // Concatenate the frames into a single chunk's data\n            let chunk_data = [compressed_part1.as_slice(), compressed_part2.as_slice()].concat();\n\n            // Calculate the chunk size in bytes\n            let chunk_size = chunk_data.len();\n\n            // Prepare the initial response part: headers + chunk size\n            let headers = [\n                COMPRESSED_RESPONSE_HEADERS, // e.g., \"HTTP/1.1 200 OK\\r\\nContent-Encoding: zstd\\r\\n\"\n                b\"Transfer-Encoding: chunked\\r\\n\\r\\n\", // Indicate chunked encoding\n                format!(\"{:x}\\r\\n\", chunk_size).as_bytes(), // Chunk size in hex\n            ]\n            .concat();\n\n            // Send headers + chunk size + chunk data\n            client_socket\n                .write_all([headers.as_slice(), &chunk_data].concat().as_slice())\n                .await\n                .expect(\"write_all failed\");\n            client_socket.flush().await.expect(\"flush failed\");\n\n            // Introduce a delay to simulate fragmentation\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            peer_addrs\n                .lock()\n                .unwrap()\n                .push(client_socket.peer_addr().unwrap());\n\n            // Send chunk terminator + final chunk\n            client_socket\n                .write_all(b\"\\r\\n0\\r\\n\\r\\n\")\n                .await\n                .expect(\"write_all failed\");\n            client_socket.flush().await.expect(\"flush failed\");\n        })\n    });\n\n    let client = reqwest::Client::builder()\n        .pool_idle_timeout(std::time::Duration::from_secs(30))\n        .pool_max_idle_per_host(1)\n        .build()\n        .unwrap();\n\n    const NUMBER_OF_REQUESTS: usize = 5;\n\n    for _ in 0..NUMBER_OF_REQUESTS {\n        // Record the start time for delay verification\n        let start = tokio::time::Instant::now();\n\n        let res = client\n            .get(format!(\"http://{}/\", server.addr()))\n            .send()\n            .await\n            .expect(\"Failed to get response\");\n\n        // Verify the decompressed response matches the original content\n        assert_eq!(\n            res.text().await.expect(\"Failed to read text\"),\n            RESPONSE_CONTENT\n        );\n        assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n    }\n\n    drop(client);\n\n    // Check that all peer addresses are the same\n    let peer_addrs = peer_addrs.lock().unwrap();\n    assert_eq!(\n        peer_addrs.len(),\n        NUMBER_OF_REQUESTS,\n        \"Expected {} peer addresses, but got {}\",\n        NUMBER_OF_REQUESTS,\n        peer_addrs.len()\n    );\n    let first_addr = peer_addrs[0];\n    assert!(\n        peer_addrs.iter().all(|addr| addr == &first_addr),\n        \"All peer addresses should be the same, but found differences: {:?}\",\n        peer_addrs\n    );\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_1() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let zstded_content = zstd_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    zstded_content.len()\n                )\n                .as_bytes(),\n                &zstded_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_2() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let zstded_content = zstd_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    zstded_content.len()\n                )\n                .as_bytes(),\n                &zstded_content,\n                b\"\\r\\n\",\n            ]\n            .concat();\n            let response_second_part = b\"0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    assert_eq!(res.text().await.expect(\"text\"), RESPONSE_CONTENT);\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n\n#[tokio::test]\nasync fn test_chunked_fragmented_response_with_extra_bytes() {\n    const DELAY_BETWEEN_RESPONSE_PARTS: tokio::time::Duration =\n        tokio::time::Duration::from_millis(1000);\n    const DELAY_MARGIN: tokio::time::Duration = tokio::time::Duration::from_millis(50);\n\n    let server = server::low_level_with_response(|_raw_request, client_socket| {\n        Box::new(async move {\n            let zstded_content = zstd_compress(RESPONSE_CONTENT.as_bytes());\n            let response_first_part = [\n                COMPRESSED_RESPONSE_HEADERS,\n                format!(\n                    \"Transfer-Encoding: chunked\\r\\n\\r\\n{:x}\\r\\n\",\n                    zstded_content.len()\n                )\n                .as_bytes(),\n                &zstded_content,\n            ]\n            .concat();\n            let response_second_part = b\"\\r\\n2ab\\r\\n0\\r\\n\\r\\n\";\n\n            client_socket\n                .write_all(response_first_part.as_slice())\n                .await\n                .expect(\"response_first_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_first_part flush failed\");\n\n            tokio::time::sleep(DELAY_BETWEEN_RESPONSE_PARTS).await;\n\n            client_socket\n                .write_all(response_second_part)\n                .await\n                .expect(\"response_second_part write_all failed\");\n            client_socket\n                .flush()\n                .await\n                .expect(\"response_second_part flush failed\");\n        })\n    });\n\n    let start = tokio::time::Instant::now();\n    let res = reqwest::Client::new()\n        .get(&format!(\"http://{}/\", server.addr()))\n        .send()\n        .await\n        .expect(\"response\");\n\n    let err = res.text().await.expect_err(\"there must be an error\");\n    assert!(err.is_decode());\n    assert!(start.elapsed() >= DELAY_BETWEEN_RESPONSE_PARTS - DELAY_MARGIN);\n}\n"
  }
]