axum_core/extract/
mod.rs

1//! Types and traits for extracting data from requests.
2//!
3//! See [`axum::extract`] for more details.
4//!
5//! [`axum::extract`]: https://docs.rs/axum/0.8/axum/extract/index.html
6
7use crate::{body::Body, response::IntoResponse};
8use http::request::Parts;
9use std::convert::Infallible;
10use std::future::Future;
11
12pub mod rejection;
13
14mod default_body_limit;
15mod from_ref;
16mod option;
17mod request_parts;
18mod tuple;
19
20pub(crate) use self::default_body_limit::DefaultBodyLimitKind;
21pub use self::{
22    default_body_limit::DefaultBodyLimit,
23    from_ref::FromRef,
24    option::{OptionalFromRequest, OptionalFromRequestParts},
25};
26
27/// Type alias for [`http::Request`] whose body type defaults to [`Body`], the most common body
28/// type used with axum.
29pub type Request<T = Body> = http::Request<T>;
30
31mod private {
32    #[derive(Debug, Clone, Copy)]
33    pub enum ViaParts {}
34
35    #[derive(Debug, Clone, Copy)]
36    pub enum ViaRequest {}
37}
38
39/// Types that can be created from request parts.
40///
41/// Extractors that implement `FromRequestParts` cannot consume the request body and can thus be
42/// run in any order for handlers.
43///
44/// If your extractor needs to consume the request body then you should implement [`FromRequest`]
45/// and not [`FromRequestParts`].
46///
47/// See [`axum::extract`] for more general docs about extractors.
48///
49/// [`axum::extract`]: https://docs.rs/axum/0.8/axum/extract/index.html
50#[diagnostic::on_unimplemented(
51    note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/0.8/axum/extract/index.html` for details"
52)]
53pub trait FromRequestParts<S>: Sized {
54    /// If the extractor fails it'll use this "rejection" type. A rejection is
55    /// a kind of error that can be converted into a response.
56    type Rejection: IntoResponse;
57
58    /// Perform the extraction.
59    fn from_request_parts(
60        parts: &mut Parts,
61        state: &S,
62    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
63}
64
65/// Types that can be created from requests.
66///
67/// Extractors that implement `FromRequest` can consume the request body and can thus only be run
68/// once for handlers.
69///
70/// If your extractor doesn't need to consume the request body then you should implement
71/// [`FromRequestParts`] and not [`FromRequest`].
72///
73/// See [`axum::extract`] for more general docs about extractors.
74///
75/// [`axum::extract`]: https://docs.rs/axum/0.8/axum/extract/index.html
76#[diagnostic::on_unimplemented(
77    note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/0.8/axum/extract/index.html` for details"
78)]
79pub trait FromRequest<S, M = private::ViaRequest>: Sized {
80    /// If the extractor fails it'll use this "rejection" type. A rejection is
81    /// a kind of error that can be converted into a response.
82    type Rejection: IntoResponse;
83
84    /// Perform the extraction.
85    fn from_request(
86        req: Request,
87        state: &S,
88    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
89}
90
91impl<S, T> FromRequest<S, private::ViaParts> for T
92where
93    S: Send + Sync,
94    T: FromRequestParts<S>,
95{
96    type Rejection = <Self as FromRequestParts<S>>::Rejection;
97
98    fn from_request(
99        req: Request,
100        state: &S,
101    ) -> impl Future<Output = Result<Self, Self::Rejection>> {
102        let (mut parts, _) = req.into_parts();
103        async move { Self::from_request_parts(&mut parts, state).await }
104    }
105}
106
107impl<S, T> FromRequestParts<S> for Result<T, T::Rejection>
108where
109    T: FromRequestParts<S>,
110    S: Send + Sync,
111{
112    type Rejection = Infallible;
113
114    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
115        Ok(T::from_request_parts(parts, state).await)
116    }
117}
118
119impl<S, T> FromRequest<S> for Result<T, T::Rejection>
120where
121    T: FromRequest<S>,
122    S: Send + Sync,
123{
124    type Rejection = Infallible;
125
126    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
127        Ok(T::from_request(req, state).await)
128    }
129}