diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md index b3c8d3bedd9..117bb7d6e56 100644 --- a/axum/CHANGELOG.md +++ b/axum/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # Unreleased -- None. +- **fixed:** Fallback handlers on nested routers returning 404 # 0.7.4 (13. January, 2024) diff --git a/axum/src/routing/path_router.rs b/axum/src/routing/path_router.rs index e9353dc7485..47f8ddce3a7 100644 --- a/axum/src/routing/path_router.rs +++ b/axum/src/routing/path_router.rs @@ -180,6 +180,7 @@ where .expect("no path for route id. This is a bug in axum. Please file an issue"); let path = path_for_nested_route(prefix, inner_path); + let route_nested_root = !path.ends_with('/') && "/".eq(inner_path.as_ref()); let layer = ( StripPrefix::layer(prefix), @@ -187,9 +188,18 @@ where ); match endpoint.layer(layer) { Endpoint::MethodRouter(method_router) => { + if IS_FALLBACK && route_nested_root { + let path = format!("{path}/"); + self.route(&path, method_router.clone())?; + } self.route(&path, method_router)?; } Endpoint::Route(route) => { + if IS_FALLBACK && route_nested_root { + let path = format!("{path}/"); + self.route_endpoint(&path, Endpoint::Route(route.clone()))?; + } + self.route_endpoint(&path, Endpoint::Route(route))?; } } diff --git a/axum/src/routing/tests/nest.rs b/axum/src/routing/tests/nest.rs index 0e6008123bb..92b221a2cb6 100644 --- a/axum/src/routing/tests/nest.rs +++ b/axum/src/routing/tests/nest.rs @@ -383,6 +383,19 @@ async fn nesting_with_root_inner_router() { assert_eq!(res.status(), StatusCode::OK); } +#[tokio::test] +async fn nesting_with_root_inner_fallback() { + let app = Router::new().nest("/router", Router::new().fallback(get(|| async {}))); + + let client = TestClient::new(app); + + let res = client.get("/router").await; + assert_eq!(res.status(), StatusCode::OK); + + let res = client.get("/router/").await; + assert_eq!(res.status(), StatusCode::OK); +} + macro_rules! nested_route_test { ( $name:ident,