diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 2461cb3a..ce1837c7 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -1,6 +1,9 @@ # Changelog ## Unreleased - 2021-xx-xx +- Add `ServiceRequest::extract` to make it easier to use extractors when writing middlewares. [#2647] + +[#2647]: https://github.com/actix/actix-web/pull/2647 ## 4.0.1 - 2022-02-25 diff --git a/actix-web/src/extract.rs b/actix-web/src/extract.rs index a8b3d456..1b2f0bd1 100644 --- a/actix-web/src/extract.rs +++ b/actix-web/src/extract.rs @@ -18,9 +18,11 @@ use crate::{dev::Payload, Error, HttpRequest}; /// A type that implements [`FromRequest`] is called an **extractor** and can extract data from /// the request. Some types that implement this trait are: [`Json`], [`Header`], and [`Path`]. /// +/// Check out [`ServiceRequest::extract`](crate::dev::ServiceRequest::extract) if you want to +/// leverage extractors when implementing middlewares. +/// /// # Configuration /// An extractor can be customized by injecting the corresponding configuration with one of: -/// /// - [`App::app_data()`][crate::App::app_data] /// - [`Scope::app_data()`][crate::Scope::app_data] /// - [`Resource::app_data()`][crate::Resource::app_data] diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index 426e9d62..a9e809bf 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -24,7 +24,7 @@ use crate::{ guard::{Guard, GuardContext}, info::ConnectionInfo, rmap::ResourceMap, - Error, HttpRequest, HttpResponse, + Error, FromRequest, HttpRequest, HttpResponse, }; pub(crate) type BoxedHttpService = BoxService, Error>; @@ -95,6 +95,31 @@ impl ServiceRequest { (&mut self.req, &mut self.payload) } + /// Derives a type from this request using an [extractor](crate::FromRequest). + /// + /// Returns the `T` extractor's `Future` type which can be `await`ed. This is particularly handy + /// when you want to use an extractor in a middleware implementation. + /// + /// # Examples + /// ``` + /// use actix_web::{ + /// dev::{ServiceRequest, ServiceResponse}, + /// web::Path, Error + /// }; + /// + /// async fn my_helper(mut srv_req: ServiceRequest) -> Result { + /// let path = srv_req.extract::>().await?; + /// // [...] + /// # todo!() + /// } + /// ``` + pub fn extract(&mut self) -> ::Future + where + T: FromRequest, + { + T::from_request(&self.req, &mut self.payload) + } + /// Construct request from parts. pub fn from_parts(req: HttpRequest, payload: Payload) -> Self { #[cfg(debug_assertions)]