//! Types and traits for extracting data from requests. //! //! See [`axum::extract`] for more details. //! //! [`axum::extract`]: https://docs.rs/axum/latest/axum/extract/index.html use crate::response::IntoResponse; use async_trait::async_trait; use http::{request::Parts, Request}; use std::convert::Infallible; pub mod rejection; mod default_body_limit; mod from_ref; mod request_parts; mod tuple; pub(crate) use self::default_body_limit::DefaultBodyLimitKind; pub use self::{default_body_limit::DefaultBodyLimit, from_ref::FromRef}; mod private { #[derive(Debug, Clone, Copy)] pub enum ViaParts {} #[derive(Debug, Clone, Copy)] pub enum ViaRequest {} } /// Types that can be created from request parts. /// /// Extractors that implement `FromRequestParts` cannot consume the request body and can thus be /// run in any order for handlers. /// /// If your extractor needs to consume the request body then you should implement [`FromRequest`] /// and not [`FromRequestParts`]. /// /// See [`axum::extract`] for more general docs about extraxtors. /// /// [`axum::extract`]: https://docs.rs/axum/0.6.0-rc.2/axum/extract/index.html #[async_trait] pub trait FromRequestParts: Sized { /// If the extractor fails it'll use this "rejection" type. A rejection is /// a kind of error that can be converted into a response. type Rejection: IntoResponse; /// Perform the extraction. async fn from_request_parts(parts: &mut Parts, state: &S) -> Result; } /// Types that can be created from requests. /// /// Extractors that implement `FromRequest` can consume the request body and can thus only be run /// once for handlers. /// /// If your extractor doesn't need to consume the request body then you should implement /// [`FromRequestParts`] and not [`FromRequest`]. /// /// See [`axum::extract`] for more general docs about extraxtors. /// /// # What is the `B` type parameter? /// /// `FromRequest` is generic over the request body (the `B` in /// [`http::Request`]). This is to allow `FromRequest` to be usable with any /// type of request body. This is necessary because some middleware change the /// request body, for example to add timeouts. /// /// If you're writing your own `FromRequest` that wont be used outside your /// application, and not using any middleware that changes the request body, you /// can most likely use `axum::body::Body`. /// /// If you're writing a library that's intended for others to use, it's recommended /// to keep the generic type parameter: /// /// ```rust /// use axum::{ /// async_trait, /// extract::FromRequest, /// http::Request, /// }; /// /// struct MyExtractor; /// /// #[async_trait] /// impl FromRequest for MyExtractor /// where /// // this bound is required by `async_trait` /// B: Send + 'static, /// // this bound is also required if the state parameter is not discarded with `_: &S` /// S: Send + Sync, /// { /// type Rejection = http::StatusCode; /// /// async fn from_request(req: Request, state: &S) -> Result { /// // ... /// # unimplemented!() /// } /// } /// ``` /// /// This ensures your extractor is as flexible as possible. /// /// [`http::Request`]: http::Request /// [`axum::extract`]: https://docs.rs/axum/0.6.0-rc.2/axum/extract/index.html #[async_trait] pub trait FromRequest: Sized { /// If the extractor fails it'll use this "rejection" type. A rejection is /// a kind of error that can be converted into a response. type Rejection: IntoResponse; /// Perform the extraction. async fn from_request(req: Request, state: &S) -> Result; } #[async_trait] impl FromRequest for T where B: Send + 'static, S: Send + Sync, T: FromRequestParts, { type Rejection = >::Rejection; async fn from_request(req: Request, state: &S) -> Result { let (mut parts, _) = req.into_parts(); Self::from_request_parts(&mut parts, state).await } } #[async_trait] impl FromRequestParts for Option where T: FromRequestParts, S: Send + Sync, { type Rejection = Infallible; async fn from_request_parts( parts: &mut Parts, state: &S, ) -> Result, Self::Rejection> { Ok(T::from_request_parts(parts, state).await.ok()) } } #[async_trait] impl FromRequest for Option where T: FromRequest, B: Send + 'static, S: Send + Sync, { type Rejection = Infallible; async fn from_request(req: Request, state: &S) -> Result, Self::Rejection> { Ok(T::from_request(req, state).await.ok()) } } #[async_trait] impl FromRequestParts for Result where T: FromRequestParts, S: Send + Sync, { type Rejection = Infallible; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { Ok(T::from_request_parts(parts, state).await) } } #[async_trait] impl FromRequest for Result where T: FromRequest, B: Send + 'static, S: Send + Sync, { type Rejection = Infallible; async fn from_request(req: Request, state: &S) -> Result { Ok(T::from_request(req, state).await) } }