@@ -134,13 +134,14 @@ use axum::{
134
134
} ;
135
135
use bytes:: Bytes ;
136
136
use http:: request:: Parts ;
137
+ use paste:: paste;
137
138
use tower_layer:: Layer ;
138
139
use tower_service:: Service ;
139
140
140
141
/// Combines two extractors or responses into a single type.
141
142
///
142
143
/// See the [module docs](self) for examples.
143
- #[ derive( Debug , Clone ) ]
144
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
144
145
#[ must_use]
145
146
pub enum Either < E1 , E2 > {
146
147
#[ allow( missing_docs) ]
@@ -310,39 +311,41 @@ macro_rules! impl_traits_for_either {
310
311
}
311
312
}
312
313
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
+ ) *
328
340
329
- $(
330
341
let req = Request :: from_parts(
331
342
parts. clone( ) ,
332
343
axum:: body:: Body :: new( http_body_util:: Full :: new( bytes. clone( ) ) ) ,
333
344
) ;
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) ) ,
336
348
}
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) ) ,
346
349
}
347
350
}
348
351
}
@@ -421,6 +424,7 @@ mod tests {
421
424
422
425
use super :: * ;
423
426
427
+ #[ derive( Debug , PartialEq ) ]
424
428
struct False ;
425
429
426
430
impl < S > FromRequestParts < S > for False {
@@ -471,4 +475,15 @@ mod tests {
471
475
472
476
assert ! ( matches!( either, Either3 :: E3 ( State ( ( ) ) ) ) ) ;
473
477
}
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
+ }
474
489
}
0 commit comments