mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-27 00:00:24 +02:00
Only allow last extractor to mutate the request (#1272)
* Only allow last extractor to mutate the request * Change `FromRequest` and add `FromRequestParts` trait (#1275) * Add `Once`/`Mut` type parameter for `FromRequest` and `RequestParts` * 🪄 * split traits * `FromRequest` for tuples * Remove `BodyAlreadyExtracted` * don't need fully qualified path * don't export `Once` and `Mut` * remove temp tests * depend on axum again Co-authored-by: Jonas Platte <[email protected]> * Port `Handler` and most extractors (#1277) * Port `Handler` and most extractors * Put `M` inside `Handler` impls, not trait itself * comment out tuples for now * fix lints * Reorder arguments to `Handler` (#1281) I think `Request<B>, Arc<S>` is better since its consistent with `FromRequest` and `FromRequestParts`. * Port most things in axum-extra (#1282) * Port `#[derive(TypedPath)]` and `#[debug_handler]` (#1283) * port #[derive(TypedPath)] * wip: #[debug_handler] * fix #[debug_handler] * don't need itertools * also require `Send` * update expected error * support fully qualified `self` * Implement FromRequest[Parts] for tuples (#1286) * Port docs for axum and axum-core (#1285) * Port axum-extra (#1287) * Port axum-extra * Update axum-core/Cargo.toml Co-authored-by: Jonas Platte <[email protected]> * remove `impl FromRequest for Either*` Co-authored-by: Jonas Platte <[email protected]> * New FromRequest[Parts] trait cleanup (#1288) * Make private module truly private again * Simplify tuple FromRequest implementation * Port `#[derive(FromRequest)]` (#1289) * fix tests * fix docs * revert examples * fix docs link * fix intra docs links * Port examples (#1291) * Document wrapping other extractors (#1292) * axum-extra doesn't need to depend on axum-core (#1294) Missed this in https://github.com/tokio-rs/axum/pull/1287 * Add `FromRequest` changes to changelogs (#1293) * Update changelog * Remove default type for `S` in `Handler` * Clarify which types have default types for `S` * Apply suggestions from code review Co-authored-by: Jonas Platte <[email protected]> Co-authored-by: Jonas Platte <[email protected]> * remove unused import * Rename `Mut` and `Once` (#1296) * fix trybuild expected output Co-authored-by: Jonas Platte <[email protected]>
This commit is contained in:
co-authored by
Jonas Platte
parent
f1769e5134
commit
be624306f4
@@ -24,7 +24,7 @@ pub use self::resource::Resource;
|
||||
pub use axum_macros::TypedPath;
|
||||
|
||||
#[cfg(feature = "typed-routing")]
|
||||
pub use self::typed::{FirstElementIs, TypedPath};
|
||||
pub use self::typed::{SecondElementIs, TypedPath};
|
||||
|
||||
#[cfg(feature = "spa")]
|
||||
pub use self::spa::SpaRouter;
|
||||
@@ -41,7 +41,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_get<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `DELETE` route to the router.
|
||||
@@ -54,7 +54,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_delete<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `HEAD` route to the router.
|
||||
@@ -67,7 +67,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_head<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `OPTIONS` route to the router.
|
||||
@@ -80,7 +80,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_options<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `PATCH` route to the router.
|
||||
@@ -93,7 +93,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_patch<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `POST` route to the router.
|
||||
@@ -106,7 +106,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_post<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `PUT` route to the router.
|
||||
@@ -119,7 +119,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_put<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add a typed `TRACE` route to the router.
|
||||
@@ -132,7 +132,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
|
||||
fn typed_trace<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath;
|
||||
|
||||
/// Add another route to the router with an additional "trailing slash redirect" route.
|
||||
@@ -184,7 +184,7 @@ where
|
||||
fn typed_get<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::get(handler))
|
||||
@@ -194,7 +194,7 @@ where
|
||||
fn typed_delete<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::delete(handler))
|
||||
@@ -204,7 +204,7 @@ where
|
||||
fn typed_head<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::head(handler))
|
||||
@@ -214,7 +214,7 @@ where
|
||||
fn typed_options<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::options(handler))
|
||||
@@ -224,7 +224,7 @@ where
|
||||
fn typed_patch<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::patch(handler))
|
||||
@@ -234,7 +234,7 @@ where
|
||||
fn typed_post<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::post(handler))
|
||||
@@ -244,7 +244,7 @@ where
|
||||
fn typed_put<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::put(handler))
|
||||
@@ -254,7 +254,7 @@ where
|
||||
fn typed_trace<H, T, P>(self, handler: H) -> Self
|
||||
where
|
||||
H: Handler<T, S, B>,
|
||||
T: FirstElementIs<P> + 'static,
|
||||
T: SecondElementIs<P> + 'static,
|
||||
P: TypedPath,
|
||||
{
|
||||
self.route(P::PATH, axum::routing::trace(handler))
|
||||
|
||||
@@ -231,10 +231,10 @@ pub trait TypedPath: std::fmt::Display {
|
||||
}
|
||||
}
|
||||
|
||||
/// Utility trait used with [`RouterExt`] to ensure the first element of a tuple type is a
|
||||
/// Utility trait used with [`RouterExt`] to ensure the second element of a tuple type is a
|
||||
/// given type.
|
||||
///
|
||||
/// If you see it in type errors its most likely because the first argument to your handler doesn't
|
||||
/// If you see it in type errors its most likely because the second argument to your handler doesn't
|
||||
/// implement [`TypedPath`].
|
||||
///
|
||||
/// You normally shouldn't have to use this trait directly.
|
||||
@@ -242,56 +242,56 @@ pub trait TypedPath: std::fmt::Display {
|
||||
/// It is sealed such that it cannot be implemented outside this crate.
|
||||
///
|
||||
/// [`RouterExt`]: super::RouterExt
|
||||
pub trait FirstElementIs<P>: Sealed {}
|
||||
pub trait SecondElementIs<P>: Sealed {}
|
||||
|
||||
macro_rules! impl_first_element_is {
|
||||
macro_rules! impl_second_element_is {
|
||||
( $($ty:ident),* $(,)? ) => {
|
||||
impl<P, $($ty,)*> FirstElementIs<P> for (P, $($ty,)*)
|
||||
impl<M, P, $($ty,)*> SecondElementIs<P> for (M, P, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
|
||||
impl<P, $($ty,)*> Sealed for (P, $($ty,)*)
|
||||
impl<M, P, $($ty,)*> Sealed for (M, P, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
|
||||
impl<P, $($ty,)*> FirstElementIs<P> for (Option<P>, $($ty,)*)
|
||||
impl<M, P, $($ty,)*> SecondElementIs<P> for (M, Option<P>, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
|
||||
impl<P, $($ty,)*> Sealed for (Option<P>, $($ty,)*)
|
||||
impl<M, P, $($ty,)*> Sealed for (M, Option<P>, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
|
||||
impl<P, E, $($ty,)*> FirstElementIs<P> for (Result<P, E>, $($ty,)*)
|
||||
impl<M, P, E, $($ty,)*> SecondElementIs<P> for (M, Result<P, E>, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
|
||||
impl<P, E, $($ty,)*> Sealed for (Result<P, E>, $($ty,)*)
|
||||
impl<M, P, E, $($ty,)*> Sealed for (M, Result<P, E>, $($ty,)*)
|
||||
where
|
||||
P: TypedPath
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
impl_first_element_is!();
|
||||
impl_first_element_is!(T1);
|
||||
impl_first_element_is!(T1, T2);
|
||||
impl_first_element_is!(T1, T2, T3);
|
||||
impl_first_element_is!(T1, T2, T3, T4);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
|
||||
impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
|
||||
impl_second_element_is!();
|
||||
impl_second_element_is!(T1);
|
||||
impl_second_element_is!(T1, T2);
|
||||
impl_second_element_is!(T1, T2, T3);
|
||||
impl_second_element_is!(T1, T2, T3, T4);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
|
||||
impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
|
||||
|
||||
Reference in New Issue
Block a user