diff --git a/axum/src/routing/mod.rs b/axum/src/routing/mod.rs index db378aa6..704a58b4 100644 --- a/axum/src/routing/mod.rs +++ b/axum/src/routing/mod.rs @@ -664,11 +664,11 @@ where let path = req.uri().path().to_owned(); - // the `unwrap` is safe because `self.state` is always some if `R = WithState`, which it is - let prev = req - .extensions_mut() - .insert(State(self.state.as_ref().unwrap().clone())); - debug_assert!(prev.is_none()); + if req.extensions().get::>().is_none() { + // the `unwrap` is safe because `self.state` is always some if `R = WithState`, which it is + req.extensions_mut() + .insert(State(self.state.as_ref().unwrap().clone())); + } match self.node.at(&path) { Ok(match_) => self.call_route(match_, req), diff --git a/axum/src/routing/tests/merge.rs b/axum/src/routing/tests/merge.rs index b7c7b142..90afa568 100644 --- a/axum/src/routing/tests/merge.rs +++ b/axum/src/routing/tests/merge.rs @@ -417,5 +417,34 @@ async fn middleware_that_return_early() { #[tokio::test] async fn merging_with_different_state() { - todo!() + #[derive(Clone)] + struct AppState { + inner: InnerState, + } + + #[derive(Clone)] + struct InnerState { + value: &'static str, + } + + impl From for InnerState { + fn from(state: AppState) -> Self { + state.inner + } + } + + let inner_router = Router::new().route( + "/a", + get(|State(state): State| async move { state.value }), + ); + + let app = Router::with_state(AppState { + inner: InnerState { value: "inner" }, + }) + .merge(inner_router.map_state(Into::into)); + + let client = TestClient::new(app); + + let res = client.get("/a").send().await; + assert_eq!(res.text().await, "inner"); } diff --git a/axum/src/routing/tests/nest.rs b/axum/src/routing/tests/nest.rs index 99fd5972..54f3dc05 100644 --- a/axum/src/routing/tests/nest.rs +++ b/axum/src/routing/tests/nest.rs @@ -404,7 +404,7 @@ async fn nesting_with_different_state() { } } - let inner_router = Router::::new().route( + let inner_router = Router::new().route( "/b", get(|State(state): State| async move { state.value }), ); @@ -433,15 +433,15 @@ macro_rules! nested_route_test { #[tokio::test] async fn $name() { let inner = Router::new().route($route_path, get(|| async {})); - let app = Router::new().nest($nested_path, inner); - let client = TestClient::new(app.state(())); + let app = Router::without_state().nest($nested_path, inner); + let client = TestClient::new(app); let res = client.get($expected_path).send().await; let status = res.status(); assert_eq!(status, StatusCode::OK, "Router"); let inner = Router::new().route($route_path, get(|| async {})).state(()); - let app = Router::new().nest_service($nested_path, inner); - let client = TestClient::new(app.state(())); + let app = Router::without_state().nest_service($nested_path, inner); + let client = TestClient::new(app); let res = client.get(dbg!($expected_path)).send().await; assert_eq!(res.status(), StatusCode::OK, "opaque"); }