@@ -134,13 +134,14 @@ use axum::{
134134} ;
135135use bytes:: Bytes ;
136136use http:: request:: Parts ;
137+ use paste:: paste;
137138use tower_layer:: Layer ;
138139use tower_service:: Service ;
139140
140141/// Combines two extractors or responses into a single type.
141142///
142143/// See the [module docs](self) for examples.
143- #[ derive( Debug , Clone ) ]
144+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
144145#[ must_use]
145146pub enum Either < E1 , E2 > {
146147 #[ allow( missing_docs) ]
@@ -310,39 +311,41 @@ macro_rules! impl_traits_for_either {
310311 }
311312 }
312313
313- impl <S , $( $ident) ,* , $last> FromRequest <S > for $either<$( $ident) ,* , $last>
314- where
315- S : Send + Sync ,
316- $( $ident: FromRequest <S >) ,* ,
317- $last: FromRequest <S >,
318- $( $ident:: Rejection : Send ) ,* ,
319- $last:: Rejection : IntoResponse + Send ,
320- {
321- type Rejection = EitherRejection <$last:: Rejection >;
322-
323- async fn from_request( req: Request , state: & S ) -> Result <Self , Self :: Rejection > {
324- let ( parts, body) = req. into_parts( ) ;
325- let bytes = Bytes :: from_request( Request :: from_parts( parts. clone( ) , body) , state)
326- . await
327- . map_err( EitherRejection :: Bytes ) ?;
314+ paste! {
315+ impl <S , $( $ident) ,* , $last, $( [ < $ident Via >] ) ,* , [ <$last Via >] > FromRequest <S , ( $( [ < $ident Via >] ) ,* , [ <$last Via >] ) > for $either<$( $ident) ,* , $last>
316+ where
317+ S : Send + Sync ,
318+ $( $ident: FromRequest <S , [ <$ident Via >] >) ,* ,
319+ $last: FromRequest <S , [ <$last Via >] >,
320+ $( $ident:: Rejection : Send ) ,* ,
321+ $last:: Rejection : IntoResponse + Send ,
322+ {
323+ type Rejection = EitherRejection <$last:: Rejection >;
324+
325+ async fn from_request( req: Request , state: & S ) -> Result <Self , Self :: Rejection > {
326+ let ( parts, body) = req. into_parts( ) ;
327+ let bytes = Bytes :: from_request( Request :: from_parts( parts. clone( ) , body) , state)
328+ . await
329+ . map_err( EitherRejection :: Bytes ) ?;
330+
331+ $(
332+ let req = Request :: from_parts(
333+ parts. clone( ) ,
334+ axum:: body:: Body :: new( http_body_util:: Full :: new( bytes. clone( ) ) ) ,
335+ ) ;
336+ if let Ok ( extracted) = $ident:: from_request( req, state) . await {
337+ return Ok ( Self :: $ident( extracted) ) ;
338+ }
339+ ) *
328340
329- $(
330341 let req = Request :: from_parts(
331342 parts. clone( ) ,
332343 axum:: body:: Body :: new( http_body_util:: Full :: new( bytes. clone( ) ) ) ,
333344 ) ;
334- if let Ok ( extracted) = $ident:: from_request( req, state) . await {
335- return Ok ( Self :: $ident( extracted) ) ;
345+ match $last:: from_request( req, state) . await {
346+ Ok ( extracted) => Ok ( Self :: $last( extracted) ) ,
347+ Err ( error) => Err ( EitherRejection :: LastRejection ( error) ) ,
336348 }
337- ) *
338-
339- let req = Request :: from_parts(
340- parts. clone( ) ,
341- axum:: body:: Body :: new( http_body_util:: Full :: new( bytes. clone( ) ) ) ,
342- ) ;
343- match $last:: from_request( req, state) . await {
344- Ok ( extracted) => Ok ( Self :: $last( extracted) ) ,
345- Err ( error) => Err ( EitherRejection :: LastRejection ( error) ) ,
346349 }
347350 }
348351 }
@@ -421,6 +424,7 @@ mod tests {
421424
422425 use super :: * ;
423426
427+ #[ derive( Debug , PartialEq ) ]
424428 struct False ;
425429
426430 impl < S > FromRequestParts < S > for False {
@@ -471,4 +475,15 @@ mod tests {
471475
472476 assert ! ( matches!( either, Either3 :: E3 ( State ( ( ) ) ) ) ) ;
473477 }
478+
479+ #[ tokio:: test]
480+ async fn either_from_request_or_parts ( ) {
481+ let request = Request :: new ( Body :: empty ( ) ) ;
482+
483+ let either = Either :: < False , Bytes > :: from_request ( request, & ( ) )
484+ . await
485+ . unwrap ( ) ;
486+
487+ assert_eq ! ( either, Either :: E2 ( Bytes :: new( ) ) ) ;
488+ }
474489}
0 commit comments