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
67use crate::{body::Body, response::IntoResponse};
8use http::request::Parts;
9use std::convert::Infallible;
10use std::future::Future;
1112pub mod rejection;
1314mod default_body_limit;
15mod from_ref;
16mod option;
17mod request_parts;
18mod tuple;
1920pub(crate) use self::default_body_limit::DefaultBodyLimitKind;
21pub use self::{
22 default_body_limit::DefaultBodyLimit,
23 from_ref::FromRef,
24 option::{OptionalFromRequest, OptionalFromRequestParts},
25};
2627/// 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>;
3031mod private {
32#[derive(Debug, Clone, Copy)]
33pub enum ViaParts {}
3435#[derive(Debug, Clone, Copy)]
36pub enum ViaRequest {}
37}
3839/// 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.
59type Rejection: IntoResponse;
6061/// Perform the extraction.
62fn from_request_parts(
63 parts: &mut Parts,
64 state: &S,
65 ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
66}
6768/// 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.
88type Rejection: IntoResponse;
8990/// Perform the extraction.
91fn from_request(
92 req: Request,
93 state: &S,
94 ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
95}
9697impl<S, T> FromRequest<S, private::ViaParts> for T
98where
99S: Send + Sync,
100 T: FromRequestParts<S>,
101{
102type Rejection = <Self as FromRequestParts<S>>::Rejection;
103104fn from_request(
105 req: Request,
106 state: &S,
107 ) -> impl Future<Output = Result<Self, Self::Rejection>> {
108let (mut parts, _) = req.into_parts();
109async move { Self::from_request_parts(&mut parts, state).await }
110 }
111}
112113impl<S, T> FromRequestParts<S> for Result<T, T::Rejection>
114where
115T: FromRequestParts<S>,
116 S: Send + Sync,
117{
118type Rejection = Infallible;
119120async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
121Ok(T::from_request_parts(parts, state).await)
122 }
123}
124125impl<S, T> FromRequest<S> for Result<T, T::Rejection>
126where
127T: FromRequest<S>,
128 S: Send + Sync,
129{
130type Rejection = Infallible;
131132async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
133Ok(T::from_request(req, state).await)
134 }
135}