{"record":{"id":"c5c358de4f5f02e0","repo":"seanmonstar/warp","slug":"not-found","errorCode":null,"errorMessage":"not_found","messagePattern":"not_found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"src/filters/host.rs","lineNumber":28,"sourceCode":"/// host and port) in the request.\n///\n/// Authority is specified either in the `Host` header or in the target URI.\n///\n/// # Example\n///\n/// ```\n/// use warp::Filter;\n///\n/// let multihost =\n///     warp::host::exact(\"foo.com\").map(|| \"you've reached foo.com\")\n///     .or(warp::host::exact(\"bar.com\").map(|| \"you've reached bar.com\"));\n/// ```\npub fn exact(expected: &str) -> impl Filter<Extract = (), Error = Rejection> + Clone {\n    let expected = Authority::from_str(expected).expect(\"invalid host/authority\");\n    optional()\n        .and_then(move |option: Option<Authority>| match option {\n            Some(authority) if authority == expected => future::ok(()),\n            _ => future::err(reject::not_found()),\n        })\n        .untuple_one()\n}\n\n/// Creates a `Filter` that looks for an authority (target server's host\n/// and port) in the request.\n///\n/// Authority is specified either in the `Host` header or in the target URI.\n///\n/// If found, extracts the `Authority`, otherwise continues the request,\n/// extracting `None`.\n///\n/// Rejects with `400 Bad Request` if the `Host` header is malformed or if there\n/// is a mismatch between the `Host` header and the target URI.\n///\n/// # Example\n///\n/// ```","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/seanmonstar/warp/blob/ff34d7213ed55ec342304aa7ff6ac4b351da9e66/src/filters/host.rs#L10-L46","documentation":"warp::host::exact (src/filters/host.rs:28) rejects with 404 not_found when the request's Authority (Host header / authority) does not equal the expected string. The filter extracts the authority via host::optional() and, unless it matches exactly, returns reject::not_found(). Panics at construction if the expected string is not a valid authority.","triggerScenarios":"A request arrives whose Host header (including port) differs from the value passed to warp::host::exact(\"api.example.com\") — e.g. host::exact(\"example.com\") receiving \"example.com:443\", an internal IP, localhost, or a vhost mismatch through a reverse proxy.","commonSituations":"Behind nginx/ALB that forwards the upstream host instead of the original one (missing proxy_set_header Host); testing locally with localhost when the filter expects the production domain; forgetting the port in the expected authority; TLS/SNI mismatch; migrating domains without updating the filter.","solutions":["Match the exact authority including port: warp::host::exact(\"example.com:443\") when requests carry a port","Configure the reverse proxy to pass the original Host through (nginx: proxy_set_header Host $host;)","Use host::optional() yourself and compare only the host part if you want port-insensitive matching","Remove or relax the host filter if vhost discrimination is not actually needed","Test with curl -H \"Host: example.com\" to confirm the filter matches the intended value"],"exampleFix":"// before\nlet routes = warp::host::exact(\"example.com\").and(api());\n// after (accept both bare host and host:port)\nlet routes = warp::host::optional()\n    .and_then(|opt: Option<http::uri::Authority>| async move {\n        match opt {\n            Some(a) if a.host() == \"example.com\" => Ok(()),\n            _ => Err(warp::reject::not_found()),\n        }\n    })\n    .untuple_one()\n    .and(api());","handlingStrategy":"validation","validationCode":"// verify what authority the server actually receives\ncurl -s -o /dev/null -D - -H \"Host: example.com:443\" https://api.example.com/route\n// compare against the exact string passed to warp::host::exact","typeGuard":"fn host_matches(authority: &http::uri::Authority, expected_host: &str) -> bool {\n    authority.host() == expected_host\n}","tryCatchPattern":"let route = warp::host::exact(\"example.com\")\n    .and(api())\n    .recover(|rej: warp::Rejection| async move {\n        if rej.is_not_found() {\n            Ok(warp::reply::with_status(\"unknown host\", warp::http::StatusCode::NOT_FOUND))\n        } else {\n            Err(rej)\n        }\n    });","preventionTips":["Include the port in host::exact when clients send one (e.g. \":443\")","Set proxy_set_header Host $host; in nginx or equivalent in other proxies","Prefer comparing authority.host() for port-insensitive matching","Add a startup test hitting the route with the production Host header","Validate the expected string is a proper authority to avoid the construction panic"],"tags":["http","host-header","routing","warp"],"backgroundTag":"host-header-mismatch","analyzedSha":"ff34d7213ed55ec342304aa7ff6ac4b351da9e66","analyzedAt":"2026-09-09T16:57:46.316Z","contentChangedAt":"2026-09-09T16:57:46.316Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}