From 657a0893b51f581b0090747cfdbe95070d126483 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Wed, 29 Jun 2022 22:48:44 +0200 Subject: [PATCH] fix `MatchedPath` with `Router`s nested with `nest_service` --- axum/src/extract/matched_path.rs | 16 ++++++++++++++++ axum/src/routing/mod.rs | 21 +++++++++++++++++++-- axum/src/routing/tests/nest.rs | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/axum/src/extract/matched_path.rs b/axum/src/extract/matched_path.rs index 9a3381e1..192983cd 100644 --- a/axum/src/extract/matched_path.rs +++ b/axum/src/extract/matched_path.rs @@ -178,4 +178,20 @@ mod tests { ), ); } + + #[tokio::test] + async fn nested_opaque_routers_append_to_matched_path() { + let app = Router::new().nest_service( + "/:a", + Router::new().route( + "/:b", + get(|path: MatchedPath| async move { path.as_str().to_owned() }), + ), + ); + + let client = TestClient::new(app); + + let res = client.get("/foo/bar").send().await; + assert_eq!(res.text().await, "/:a/:b"); + } } diff --git a/axum/src/routing/mod.rs b/axum/src/routing/mod.rs index 563d27d2..a4a52585 100644 --- a/axum/src/routing/mod.rs +++ b/axum/src/routing/mod.rs @@ -98,6 +98,7 @@ impl fmt::Debug for Router { } pub(crate) const NEST_TAIL_PARAM: &str = "__private__axum_nest_tail_param"; +const NEST_TAIL_PARAM_CAPTURE: &str = "/*__private__axum_nest_tail_param"; impl Router where @@ -416,8 +417,24 @@ where #[cfg(feature = "matched-path")] if let Some(matched_path) = self.node.route_id_to_path.get(&id) { - req.extensions_mut() - .insert(crate::extract::MatchedPath(Arc::clone(matched_path))); + use crate::extract::MatchedPath; + + let matched_path = if let Some(previous) = req.extensions_mut().get::() { + // a previous `MatchedPath` might exist if we're inside a nested Router + let previous = if let Some(previous) = + previous.as_str().strip_suffix(NEST_TAIL_PARAM_CAPTURE) + { + previous + } else { + previous.as_str() + }; + + let matched_path = format!("{}{}", previous, matched_path); + matched_path.into() + } else { + Arc::clone(matched_path) + }; + req.extensions_mut().insert(MatchedPath(matched_path)); } else { #[cfg(debug_assertions)] panic!("should always have a matched path for a route id"); diff --git a/axum/src/routing/tests/nest.rs b/axum/src/routing/tests/nest.rs index 6c2a6c67..7113d2b7 100644 --- a/axum/src/routing/tests/nest.rs +++ b/axum/src/routing/tests/nest.rs @@ -414,7 +414,7 @@ nested_route_test!(nest_3, nest = "", route = "/a/", expected = "/a/"); nested_route_test!(nest_4, nest = "/", route = "/", expected = "/"); nested_route_test!(nest_5, nest = "/", route = "/a", expected = "/a"); nested_route_test!(nest_6, nest = "/", route = "/a/", expected = "/a/"); -nested_route_test!(nest_7, nest = "/a/", route = "/", expected = "/a"); +nested_route_test!(nest_7, nest = "/a", route = "/", expected = "/a"); nested_route_test!(nest_8, nest = "/a", route = "/a", expected = "/a/a"); nested_route_test!(nest_9, nest = "/a", route = "/a/", expected = "/a/a/"); nested_route_test!(nest_11, nest = "/a/", route = "/", expected = "/a/");