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#[rustversion::attr(
51    since(1.78),
52    diagnostic::on_unimplemented(
53        note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/0.8/axum/extract/index.html` for details",
54    )
55)]
56pub trait FromRequestParts<S>: Sized {
57    /// If the extractor fails it'll use this "rejection" type. A rejection is
58    /// a kind of error that can be converted into a response.
59    type Rejection: IntoResponse;
60
61    /// Perform the extraction.
62    fn from_request_parts(
63        parts: &mut Parts,
64        state: &S,
65    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
66}
67
68/// Types that can be created from requests.
69///
70/// Extractors that implement `FromRequest` can consume the request body and can thus only be run
71/// once for handlers.
72///
73/// If your extractor doesn't need to consume the request body then you should implement
74/// [`FromRequestParts`] and not [`FromRequest`].
75///
76/// See [`axum::extract`] for more general docs about extractors.
77///
78/// [`axum::extract`]: https://docs.rs/axum/0.8/axum/extract/index.html
79#[rustversion::attr(
80    since(1.78),
81    diagnostic::on_unimplemented(
82        note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/0.8/axum/extract/index.html` for details",
83    )
84)]
85pub trait FromRequest<S, M = private::ViaRequest>: Sized {
86    /// If the extractor fails it'll use this "rejection" type. A rejection is
87    /// a kind of error that can be converted into a response.
88    type Rejection: IntoResponse;
89
90    /// Perform the extraction.
91    fn from_request(
92        req: Request,
93        state: &S,
94    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
95}
96
97impl<S, T> FromRequest<S, private::ViaParts> for T
98where
99    S: Send + Sync,
100    T: FromRequestParts<S>,
101{
102    type Rejection = <Self as FromRequestParts<S>>::Rejection;
103
104    fn from_request(
105        req: Request,
106        state: &S,
107    ) -> impl Future<Output = Result<Self, Self::Rejection>> {
108        let (mut parts, _) = req.into_parts();
109        async move { Self::from_request_parts(&mut parts, state).await }
110    }
111}
112
113impl<S, T> FromRequestParts<S> for Result<T, T::Rejection>
114where
115    T: FromRequestParts<S>,
116    S: Send + Sync,
117{
118    type Rejection = Infallible;
119
120    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
121        Ok(T::from_request_parts(parts, state).await)
122    }
123}
124
125impl<S, T> FromRequest<S> for Result<T, T::Rejection>
126where
127    T: FromRequest<S>,
128    S: Send + Sync,
129{
130    type Rejection = Infallible;
131
132    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
133        Ok(T::from_request(req, state).await)
134    }
135}