routing: omit the Allow header for non-405 method not allowed fallbacks (#3465)

This commit is contained in:
othelot
2025-09-16 08:29:01 +00:00
committed by GitHub
parent 1073468163
commit ab593bbab7
3 changed files with 24 additions and 3 deletions
+2 -2
View File
@@ -48,8 +48,8 @@ async fn fallback_two() -> impl IntoResponse { /* ... */ }
## Setting the `Allow` header
By default `MethodRouter` will set the `Allow` header when returning `405 Method
Not Allowed`. This is also done when the fallback is used unless the response
generated by the fallback already sets the `Allow` header.
Not Allowed`. This is also done when the fallback returns `405 Method Not Allowed`
unless the response generated by the fallback already sets the `Allow` header.
This means if you use `fallback` to accept additional methods, you should make
sure you set the `Allow` header correctly.
+5 -1
View File
@@ -161,7 +161,11 @@ impl<E> Future for RouteFuture<E> {
res = res.map(|_| Body::empty());
}
} else if *this.top_level {
set_allow_header(res.headers_mut(), this.allow_header);
if res.status() == http::StatusCode::METHOD_NOT_ALLOWED {
// From https://httpwg.org/specs/rfc9110.html#field.allow:
// An origin server MUST generate an `Allow` header field in a 405 (Method Not Allowed) response and MAY do so in any other response.
set_allow_header(res.headers_mut(), this.allow_header);
}
// make sure to set content-length before removing the body
set_content_length(&res.size_hint(), res.headers_mut());
+17
View File
@@ -329,6 +329,23 @@ async fn merge_router_with_fallback_into_empty() {
assert_eq!(res.text().await, "outer");
}
#[crate::test]
async fn mna_fallback_not_405() {
let app = Router::new()
.route("/path", get(|| async { "path" }))
.method_not_allowed_fallback(|| async { (http::StatusCode::NOT_FOUND, "Not Found") });
let client = TestClient::new(app);
let method_not_allowed_fallback = client.post("/path").await;
assert_eq!(
method_not_allowed_fallback.status(),
http::StatusCode::NOT_FOUND
);
assert_eq!(method_not_allowed_fallback.headers().get(ALLOW), None);
assert_eq!(method_not_allowed_fallback.text().await, "Not Found");
}
#[crate::test]
async fn mna_fallback_with_existing_fallback() {
let app = Router::new()