Don't inherit fallbacks when using Router::nest_service (#1956)

This commit is contained in:
David Pedersen 2023-04-22 16:19:32 +02:00 committed by GitHub
parent db300efc33
commit d1765d9a00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 9 additions and 81 deletions

View file

@ -50,6 +50,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
type inference issues when calling `ServiceExt` methods on a `Router` ([#1835])
- **breaking:** Removed `axum::Server` as it was removed in hyper 1.0. Instead
use `axum::serve(listener, service)` or hyper/hyper-util for more configuration options ([#1868])
- **breaking:** Only inherit fallbacks for routers nested with `Router::nest`.
Routers nested with `Router::nest_service` will no longer inherit fallbacks ([#1956])
[#1664]: https://github.com/tokio-rs/axum/pull/1664
[#1751]: https://github.com/tokio-rs/axum/pull/1751
@ -58,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#1835]: https://github.com/tokio-rs/axum/pull/1835
[#1850]: https://github.com/tokio-rs/axum/pull/1850
[#1868]: https://github.com/tokio-rs/axum/pull/1868
[#1956]: https://github.com/tokio-rs/axum/pull/1956
# 0.6.16 (18. April, 2023)

View file

@ -19,7 +19,6 @@ use std::{
marker::PhantomData,
task::{Context, Poll},
};
use sync_wrapper::SyncWrapper;
use tower_layer::Layer;
use tower_service::Service;
@ -285,43 +284,15 @@ where
}
}
pub(crate) fn call_with_state(
&mut self,
mut req: Request,
state: S,
) -> RouteFuture<Infallible> {
// required for opaque routers to still inherit the fallback
// TODO(david): remove this feature in 0.7
if !self.default_fallback {
req.extensions_mut().insert(SuperFallback(SyncWrapper::new(
self.fallback_router.clone(),
)));
}
pub(crate) fn call_with_state(&mut self, req: Request, state: S) -> RouteFuture<Infallible> {
match self.path_router.call_with_state(req, state) {
Ok(future) => future,
Err((mut req, state)) => {
let super_fallback = req
.extensions_mut()
.remove::<SuperFallback<S>>()
.map(|SuperFallback(path_router)| path_router.into_inner());
if let Some(mut super_fallback) = super_fallback {
return super_fallback
.call_with_state(req, state)
.unwrap_or_else(|_| unreachable!());
Err((req, state)) => match self.fallback_router.call_with_state(req, state) {
Ok(future) => future,
Err((_req, _state)) => {
unreachable!("the default fallback added in `Router::new` matches everything")
}
match self.fallback_router.call_with_state(req, state) {
Ok(future) => future,
Err((_req, _state)) => {
unreachable!(
"the default fallback added in `Router::new` \
matches everything"
)
}
}
}
},
}
}
@ -662,8 +633,6 @@ impl<S> fmt::Debug for Endpoint<S> {
}
}
struct SuperFallback<S>(SyncWrapper<PathRouter<S, true>>);
#[test]
#[allow(warnings)]
fn traits() {

View file

@ -1,5 +1,3 @@
use tower::ServiceExt;
use super::*;
use crate::middleware::{map_request, map_response};
@ -166,48 +164,6 @@ async fn also_inherits_default_layered_fallback() {
assert_eq!(res.text().await, "outer");
}
#[crate::test]
async fn fallback_inherited_into_nested_router_service() {
let inner = Router::new()
.route(
"/bar",
get(|State(state): State<&'static str>| async move { state }),
)
.with_state("inner");
// with a different state
let app = Router::new()
.nest_service("/foo", inner)
.fallback(outer_fallback);
let client = TestClient::new(app);
let res = client.get("/foo/not-found").send().await;
assert_eq!(res.status(), StatusCode::NOT_FOUND);
assert_eq!(res.text().await, "outer");
}
#[crate::test]
async fn fallback_inherited_into_nested_opaque_service() {
let inner = Router::new()
.route(
"/bar",
get(|State(state): State<&'static str>| async move { state }),
)
.with_state("inner")
// even if the service is made more opaque it should still inherit the fallback
.boxed_clone();
// with a different state
let app = Router::new()
.nest_service("/foo", inner)
.fallback(outer_fallback);
let client = TestClient::new(app);
let res = client.get("/foo/not-found").send().await;
assert_eq!(res.status(), StatusCode::NOT_FOUND);
assert_eq!(res.text().await, "outer");
}
#[crate::test]
async fn nest_fallback_on_inner() {
let app = Router::new()