33use std:: {
44 convert:: Infallible ,
55 future:: Future ,
6- marker:: PhantomData ,
76 pin:: Pin ,
87 task:: { Context , Poll } ,
98} ;
109
1110use actix_http:: { Method , Uri } ;
12- use actix_utils:: future:: { ok, Ready } ;
1311use futures_core:: ready;
1412use pin_project_lite:: pin_project;
1513
@@ -66,33 +64,17 @@ pub trait FromRequest: Sized {
6664 /// The associated error which can be returned.
6765 type Error : Into < Error > ;
6866
69- /// Future that resolves to a `Self`.
70- ///
71- /// To use an async function or block, the futures must be boxed. The following snippet will be
72- /// common when creating async/await extractors (that do not consume the body).
73- ///
74- /// ```ignore
75- /// type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
76- /// // or
77- /// type Future = futures_util::future::LocalBoxFuture<'static, Result<Self, Self::Error>>;
78- ///
79- /// fn from_request(req: HttpRequest, ...) -> Self::Future {
80- /// let req = req.clone();
81- /// Box::pin(async move {
82- /// ...
83- /// })
84- /// }
85- /// ```
86- type Future : Future < Output = Result < Self , Self :: Error > > ;
87-
88- /// Create a `Self` from request parts asynchronously.
89- fn from_request ( req : & HttpRequest , payload : & mut Payload ) -> Self :: Future ;
67+ /// Creates a `Self` from request parts asynchronously.
68+ fn from_request (
69+ req : & HttpRequest ,
70+ payload : & mut Payload ,
71+ ) -> impl Future < Output = Result < Self , Self :: Error > > ;
9072
9173 /// Create a `Self` from request head asynchronously.
9274 ///
9375 /// This method is short for `T::from_request(req, &mut Payload::None)`.
94- fn extract ( req : & HttpRequest ) -> Self :: Future {
95- Self :: from_request ( req, & mut Payload :: None )
76+ fn extract ( req : & HttpRequest ) -> impl Future < Output = Result < Self , Self :: Error > > {
77+ async { Self :: from_request ( req, & mut Payload :: None ) . await }
9678 }
9779}
9880
@@ -146,12 +128,19 @@ where
146128 T : FromRequest ,
147129{
148130 type Error = Infallible ;
149- type Future = FromRequestOptFuture < T :: Future > ;
150131
151132 #[ inline]
152- fn from_request ( req : & HttpRequest , payload : & mut Payload ) -> Self :: Future {
153- FromRequestOptFuture {
154- fut : T :: from_request ( req, payload) ,
133+ async fn from_request ( req : & HttpRequest , payload : & mut Payload ) -> Result < Self , Self :: Error > {
134+ match T :: from_request ( req, payload) . await {
135+ Ok ( t) => Ok ( Some ( t) ) ,
136+ Err ( err) => {
137+ log:: debug!(
138+ "Error from `Option<{}>` extractor: {}" ,
139+ std:: any:: type_name:: <T >( ) ,
140+ err. into( )
141+ ) ;
142+ Ok ( None )
143+ }
155144 }
156145 }
157146}
@@ -203,9 +192,11 @@ where
203192///
204193/// impl FromRequest for Thing {
205194/// type Error = Error;
206- /// type Future = Ready<Result<Thing, Error>>;
207195///
208- /// fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
196+ /// async fn from_request(
197+ /// req: &HttpRequest,
198+ /// payload: &mut dev::Payload,
199+ /// ) -> Result<Self, Self::Error> {
209200/// if rand::random() {
210201/// ok(Thing { name: "thingy".into() })
211202/// } else {
@@ -232,36 +223,10 @@ where
232223 T :: Error : Into < E > ,
233224{
234225 type Error = Infallible ;
235- type Future = FromRequestResFuture < T :: Future , E > ;
236226
237227 #[ inline]
238- fn from_request ( req : & HttpRequest , payload : & mut Payload ) -> Self :: Future {
239- FromRequestResFuture {
240- fut : T :: from_request ( req, payload) ,
241- _phantom : PhantomData ,
242- }
243- }
244- }
245-
246- pin_project ! {
247- pub struct FromRequestResFuture <Fut , E > {
248- #[ pin]
249- fut: Fut ,
250- _phantom: PhantomData <E >,
251- }
252- }
253-
254- impl < Fut , T , Ei , E > Future for FromRequestResFuture < Fut , E >
255- where
256- Fut : Future < Output = Result < T , Ei > > ,
257- Ei : Into < E > ,
258- {
259- type Output = Result < Result < T , E > , Infallible > ;
260-
261- fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
262- let this = self . project ( ) ;
263- let res = ready ! ( this. fut. poll( cx) ) ;
264- Poll :: Ready ( Ok ( res. map_err ( Into :: into) ) )
228+ async fn from_request ( req : & HttpRequest , payload : & mut Payload ) -> Result < Self , Self :: Error > {
229+ Ok ( T :: from_request ( req, payload) . await . map_err ( Into :: into) )
265230 }
266231}
267232
@@ -279,10 +244,9 @@ where
279244/// ```
280245impl FromRequest for Uri {
281246 type Error = Infallible ;
282- type Future = Ready < Result < Self , Self :: Error > > ;
283247
284- fn from_request ( req : & HttpRequest , _: & mut Payload ) -> Self :: Future {
285- ok ( req. uri ( ) . clone ( ) )
248+ async fn from_request ( req : & HttpRequest , _: & mut Payload ) -> Result < Self , Self :: Error > {
249+ Ok ( req. uri ( ) . clone ( ) )
286250 }
287251}
288252
@@ -300,10 +264,9 @@ impl FromRequest for Uri {
300264/// ```
301265impl FromRequest for Method {
302266 type Error = Infallible ;
303- type Future = Ready < Result < Self , Self :: Error > > ;
304267
305- fn from_request ( req : & HttpRequest , _: & mut Payload ) -> Self :: Future {
306- ok ( req. method ( ) . clone ( ) )
268+ async fn from_request ( req : & HttpRequest , _: & mut Payload ) -> Result < Self , Self :: Error > {
269+ Ok ( req. method ( ) . clone ( ) )
307270 }
308271}
309272
@@ -319,88 +282,24 @@ mod tuple_from_req {
319282 impl <$( $T: FromRequest + ' static ) ,+> FromRequest for ( $( $T, ) +)
320283 {
321284 type Error = Error ;
322- type Future = $fut<$( $T) ,+>;
323-
324- fn from_request( req: & HttpRequest , payload: & mut Payload ) -> Self :: Future {
325- $fut {
326- $(
327- $T: ExtractFuture :: Future {
328- fut: $T:: from_request( req, payload)
329- } ,
330- ) +
331- }
332- }
333- }
334285
335- pin_project! {
336- pub struct $fut<$( $T: FromRequest ) ,+> {
286+ async fn from_request( req: & HttpRequest , payload: & mut Payload ) -> Result <Self , Self :: Error > {
337287 $(
338- #[ pin]
339- $T: ExtractFuture <$T:: Future , $T>,
288+ let $T = $T:: from_request( req, payload) . await . map_err( Into :: into) ?;
340289 ) +
341- }
342- }
343290
344- impl <$( $T: FromRequest ) ,+> Future for $fut<$( $T) ,+>
345- {
346- type Output = Result <( $( $T, ) +) , Error >;
347-
348- fn poll( self : Pin <& mut Self >, cx: & mut Context <' _>) -> Poll <Self :: Output > {
349- let mut this = self . project( ) ;
350-
351- let mut ready = true ;
352- $(
353- match this. $T. as_mut( ) . project( ) {
354- ExtractProj :: Future { fut } => match fut. poll( cx) {
355- Poll :: Ready ( Ok ( output) ) => {
356- let _ = this. $T. as_mut( ) . project_replace( ExtractFuture :: Done { output } ) ;
357- } ,
358- Poll :: Ready ( Err ( err) ) => return Poll :: Ready ( Err ( err. into( ) ) ) ,
359- Poll :: Pending => ready = false ,
360- } ,
361- ExtractProj :: Done { .. } => { } ,
362- ExtractProj :: Empty => unreachable!( "FromRequest polled after finished" ) ,
363- }
364- ) +
365-
366- if ready {
367- Poll :: Ready ( Ok (
368- ( $(
369- match this. $T. project_replace( ExtractFuture :: Empty ) {
370- ExtractReplaceProj :: Done { output } => output,
371- _ => unreachable!( "FromRequest polled after finished" ) ,
372- } ,
373- ) +)
374- ) )
375- } else {
376- Poll :: Pending
377- }
291+ Ok ( ( $( $T, ) +) )
378292 }
379293 }
380294 } ;
381295 }
382296
383- pin_project ! {
384- #[ project = ExtractProj ]
385- #[ project_replace = ExtractReplaceProj ]
386- enum ExtractFuture <Fut , Res > {
387- Future {
388- #[ pin]
389- fut: Fut
390- } ,
391- Done {
392- output: Res ,
393- } ,
394- Empty
395- }
396- }
397-
398297 impl FromRequest for ( ) {
399298 type Error = Infallible ;
400- type Future = Ready < Result < Self , Self :: Error > > ;
401299
402- fn from_request ( _: & HttpRequest , _: & mut Payload ) -> Self :: Future {
403- ok ( ( ) )
300+ #[ inline]
301+ async fn from_request ( _: & HttpRequest , _: & mut Payload ) -> Result < Self , Self :: Error > {
302+ Ok ( ( ) )
404303 }
405304 }
406305
0 commit comments