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/latest/axum/extract/index.html 6 7 use crate::response::IntoResponse; 8 use async_trait::async_trait; 9 use http::{request::Parts, Request}; 10 use std::convert::Infallible; 11 12 pub mod rejection; 13 14 mod default_body_limit; 15 mod from_ref; 16 mod request_parts; 17 mod tuple; 18 19 pub(crate) use self::default_body_limit::DefaultBodyLimitKind; 20 pub use self::{default_body_limit::DefaultBodyLimit, from_ref::FromRef}; 21 22 mod private { 23 #[derive(Debug, Clone, Copy)] 24 pub enum ViaParts {} 25 26 #[derive(Debug, Clone, Copy)] 27 pub enum ViaRequest {} 28 } 29 30 /// Types that can be created from request parts. 31 /// 32 /// Extractors that implement `FromRequestParts` cannot consume the request body and can thus be 33 /// run in any order for handlers. 34 /// 35 /// If your extractor needs to consume the request body then you should implement [`FromRequest`] 36 /// and not [`FromRequestParts`]. 37 /// 38 /// See [`axum::extract`] for more general docs about extractors. 39 /// 40 /// [`axum::extract`]: https://docs.rs/axum/0.6.0/axum/extract/index.html 41 #[async_trait] 42 #[cfg_attr( 43 nightly_error_messages, 44 rustc_on_unimplemented( 45 note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/latest/axum/extract/index.html` for details", 46 ) 47 )] 48 pub trait FromRequestParts<S>: Sized { 49 /// If the extractor fails it'll use this "rejection" type. A rejection is 50 /// a kind of error that can be converted into a response. 51 type Rejection: IntoResponse; 52 53 /// Perform the extraction. from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection>54 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection>; 55 } 56 57 /// Types that can be created from requests. 58 /// 59 /// Extractors that implement `FromRequest` can consume the request body and can thus only be run 60 /// once for handlers. 61 /// 62 /// If your extractor doesn't need to consume the request body then you should implement 63 /// [`FromRequestParts`] and not [`FromRequest`]. 64 /// 65 /// See [`axum::extract`] for more general docs about extractors. 66 /// 67 /// # What is the `B` type parameter? 68 /// 69 /// `FromRequest` is generic over the request body (the `B` in 70 /// [`http::Request<B>`]). This is to allow `FromRequest` to be usable with any 71 /// type of request body. This is necessary because some middleware change the 72 /// request body, for example to add timeouts. 73 /// 74 /// If you're writing your own `FromRequest` that wont be used outside your 75 /// application, and not using any middleware that changes the request body, you 76 /// can most likely use `axum::body::Body`. 77 /// 78 /// If you're writing a library that's intended for others to use, it's recommended 79 /// to keep the generic type parameter: 80 /// 81 /// ```rust 82 /// use axum::{ 83 /// async_trait, 84 /// extract::FromRequest, 85 /// http::{self, Request}, 86 /// }; 87 /// 88 /// struct MyExtractor; 89 /// 90 /// #[async_trait] 91 /// impl<S, B> FromRequest<S, B> for MyExtractor 92 /// where 93 /// // these bounds are required by `async_trait` 94 /// B: Send + 'static, 95 /// S: Send + Sync, 96 /// { 97 /// type Rejection = http::StatusCode; 98 /// 99 /// async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { 100 /// // ... 101 /// # unimplemented!() 102 /// } 103 /// } 104 /// ``` 105 /// 106 /// This ensures your extractor is as flexible as possible. 107 /// 108 /// [`http::Request<B>`]: http::Request 109 /// [`axum::extract`]: https://docs.rs/axum/0.6.0/axum/extract/index.html 110 #[async_trait] 111 #[cfg_attr( 112 nightly_error_messages, 113 rustc_on_unimplemented( 114 note = "Function argument is not a valid axum extractor. \nSee `https://docs.rs/axum/latest/axum/extract/index.html` for details", 115 ) 116 )] 117 pub trait FromRequest<S, B, M = private::ViaRequest>: Sized { 118 /// If the extractor fails it'll use this "rejection" type. A rejection is 119 /// a kind of error that can be converted into a response. 120 type Rejection: IntoResponse; 121 122 /// Perform the extraction. from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection>123 async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection>; 124 } 125 126 #[async_trait] 127 impl<S, B, T> FromRequest<S, B, private::ViaParts> for T 128 where 129 B: Send + 'static, 130 S: Send + Sync, 131 T: FromRequestParts<S>, 132 { 133 type Rejection = <Self as FromRequestParts<S>>::Rejection; 134 from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection>135 async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { 136 let (mut parts, _) = req.into_parts(); 137 Self::from_request_parts(&mut parts, state).await 138 } 139 } 140 141 #[async_trait] 142 impl<S, T> FromRequestParts<S> for Option<T> 143 where 144 T: FromRequestParts<S>, 145 S: Send + Sync, 146 { 147 type Rejection = Infallible; 148 from_request_parts( parts: &mut Parts, state: &S, ) -> Result<Option<T>, Self::Rejection>149 async fn from_request_parts( 150 parts: &mut Parts, 151 state: &S, 152 ) -> Result<Option<T>, Self::Rejection> { 153 Ok(T::from_request_parts(parts, state).await.ok()) 154 } 155 } 156 157 #[async_trait] 158 impl<S, T, B> FromRequest<S, B> for Option<T> 159 where 160 T: FromRequest<S, B>, 161 B: Send + 'static, 162 S: Send + Sync, 163 { 164 type Rejection = Infallible; 165 from_request(req: Request<B>, state: &S) -> Result<Option<T>, Self::Rejection>166 async fn from_request(req: Request<B>, state: &S) -> Result<Option<T>, Self::Rejection> { 167 Ok(T::from_request(req, state).await.ok()) 168 } 169 } 170 171 #[async_trait] 172 impl<S, T> FromRequestParts<S> for Result<T, T::Rejection> 173 where 174 T: FromRequestParts<S>, 175 S: Send + Sync, 176 { 177 type Rejection = Infallible; 178 from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection>179 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { 180 Ok(T::from_request_parts(parts, state).await) 181 } 182 } 183 184 #[async_trait] 185 impl<S, T, B> FromRequest<S, B> for Result<T, T::Rejection> 186 where 187 T: FromRequest<S, B>, 188 B: Send + 'static, 189 S: Send + Sync, 190 { 191 type Rejection = Infallible; 192 from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection>193 async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { 194 Ok(T::from_request(req, state).await) 195 } 196 } 197