mirror of
https://github.com/tokio-rs/axum.git
synced 2025-09-27 04:50:31 +00:00
support both FromRequest
and FromRequestParts
in Either
This commit is contained in:
parent
b7f815f10d
commit
b5c534d073
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -390,6 +390,7 @@ dependencies = [
|
|||||||
"hyper 1.5.2",
|
"hyper 1.5.2",
|
||||||
"mime",
|
"mime",
|
||||||
"multer",
|
"multer",
|
||||||
|
"paste",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"prost",
|
"prost",
|
||||||
|
@ -57,6 +57,7 @@ http = "1.0.0"
|
|||||||
http-body = "1.0.0"
|
http-body = "1.0.0"
|
||||||
http-body-util = "0.1.0"
|
http-body-util = "0.1.0"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
|
paste = "1.0"
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
rustversion = "1.0.9"
|
rustversion = "1.0.9"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -134,13 +134,14 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http::request::Parts;
|
use http::request::Parts;
|
||||||
|
use paste::paste;
|
||||||
use tower_layer::Layer;
|
use tower_layer::Layer;
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
|
|
||||||
/// Combines two extractors or responses into a single type.
|
/// Combines two extractors or responses into a single type.
|
||||||
///
|
///
|
||||||
/// See the [module docs](self) for examples.
|
/// See the [module docs](self) for examples.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum Either<E1, E2> {
|
pub enum Either<E1, E2> {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@ -310,39 +311,41 @@ macro_rules! impl_traits_for_either {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, $($ident),*, $last> FromRequest<S> for $either<$($ident),*, $last>
|
paste! {
|
||||||
where
|
impl<S, $($ident),*, $last, $([< $ident Via >]),*, [<$last Via>]> FromRequest<S, ($([< $ident Via >]),*, [<$last Via>])> for $either<$($ident),*, $last>
|
||||||
S: Send + Sync,
|
where
|
||||||
$($ident: FromRequest<S>),*,
|
S: Send + Sync,
|
||||||
$last: FromRequest<S>,
|
$($ident: FromRequest<S, [<$ident Via>]>),*,
|
||||||
$($ident::Rejection: Send),*,
|
$last: FromRequest<S, [<$last Via>]>,
|
||||||
$last::Rejection: IntoResponse + Send,
|
$($ident::Rejection: Send),*,
|
||||||
{
|
$last::Rejection: IntoResponse + Send,
|
||||||
type Rejection = EitherRejection<$last::Rejection>;
|
{
|
||||||
|
type Rejection = EitherRejection<$last::Rejection>;
|
||||||
|
|
||||||
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let (parts, body) = req.into_parts();
|
let (parts, body) = req.into_parts();
|
||||||
let bytes = Bytes::from_request(Request::from_parts(parts.clone(), body), state)
|
let bytes = Bytes::from_request(Request::from_parts(parts.clone(), body), state)
|
||||||
.await
|
.await
|
||||||
.map_err(EitherRejection::Bytes)?;
|
.map_err(EitherRejection::Bytes)?;
|
||||||
|
|
||||||
|
$(
|
||||||
|
let req = Request::from_parts(
|
||||||
|
parts.clone(),
|
||||||
|
axum::body::Body::new(http_body_util::Full::new(bytes.clone())),
|
||||||
|
);
|
||||||
|
if let Ok(extracted) = $ident::from_request(req, state).await {
|
||||||
|
return Ok(Self::$ident(extracted));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
$(
|
|
||||||
let req = Request::from_parts(
|
let req = Request::from_parts(
|
||||||
parts.clone(),
|
parts.clone(),
|
||||||
axum::body::Body::new(http_body_util::Full::new(bytes.clone())),
|
axum::body::Body::new(http_body_util::Full::new(bytes.clone())),
|
||||||
);
|
);
|
||||||
if let Ok(extracted) = $ident::from_request(req, state).await {
|
match $last::from_request(req, state).await {
|
||||||
return Ok(Self::$ident(extracted));
|
Ok(extracted) => Ok(Self::$last(extracted)),
|
||||||
|
Err(error) => Err(EitherRejection::LastRejection(error)),
|
||||||
}
|
}
|
||||||
)*
|
|
||||||
|
|
||||||
let req = Request::from_parts(
|
|
||||||
parts.clone(),
|
|
||||||
axum::body::Body::new(http_body_util::Full::new(bytes.clone())),
|
|
||||||
);
|
|
||||||
match $last::from_request(req, state).await {
|
|
||||||
Ok(extracted) => Ok(Self::$last(extracted)),
|
|
||||||
Err(error) => Err(EitherRejection::LastRejection(error)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,6 +424,7 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
struct False;
|
struct False;
|
||||||
|
|
||||||
impl<S> FromRequestParts<S> for False {
|
impl<S> FromRequestParts<S> for False {
|
||||||
@ -471,4 +475,15 @@ mod tests {
|
|||||||
|
|
||||||
assert!(matches!(either, Either3::E3(State(()))));
|
assert!(matches!(either, Either3::E3(State(()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn either_from_request_or_parts() {
|
||||||
|
let request = Request::new(Body::empty());
|
||||||
|
|
||||||
|
let either = Either::<False, Bytes>::from_request(request, &())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(either, Either::E2(Bytes::new()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user