1#![doc = include_str!("readme.md")]
2
3use http::{Method, Uri, Version, header::HeaderMap};
4use serde::de::DeserializeOwned;
5use std::fmt;
6
7#[derive(Debug)]
11pub struct RequestParts {
12 pub method: Method,
14 pub uri: Uri,
16 pub version: Version,
18 pub headers: HeaderMap,
20 pub path_params: Vec<(String, String)>,
22}
23
24impl RequestParts {
25 pub fn new(method: Method, uri: Uri, version: Version, headers: HeaderMap) -> Self {
27 Self { method, uri, version, headers, path_params: Vec::new() }
28 }
29}
30
31pub trait FromRequestParts<S>: Sized {
35 type Error;
37
38 fn from_request_parts(parts: &RequestParts, state: &S) -> Result<Self, Self::Error>;
45}
46
47#[derive(Debug)]
51pub enum ExtractorError {
52 PathRejection(String),
54
55 QueryRejection(String),
57
58 JsonRejection(String),
60
61 FormRejection(String),
63
64 ExtensionRejection(String),
66
67 HostRejection(String),
69
70 TypedHeaderRejection(String),
72
73 CookieRejection(String),
75
76 MultipartRejection(String),
78
79 WebSocketUpgradeRejection(String),
81
82 BytesRejection(String),
84
85 StreamRejection(String),
87
88 Custom(String),
90}
91
92impl fmt::Display for ExtractorError {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 match self {
95 ExtractorError::PathRejection(e) => write!(f, "Path extraction failed: {}", e),
96 ExtractorError::QueryRejection(e) => write!(f, "Query extraction failed: {}", e),
97 ExtractorError::JsonRejection(e) => write!(f, "Json extraction failed: {}", e),
98 ExtractorError::FormRejection(e) => write!(f, "Form extraction failed: {}", e),
99 ExtractorError::ExtensionRejection(e) => write!(f, "Extension extraction failed: {}", e),
100 ExtractorError::HostRejection(e) => write!(f, "Host extraction failed: {}", e),
101 ExtractorError::TypedHeaderRejection(e) => write!(f, "TypedHeader extraction failed: {}", e),
102 ExtractorError::CookieRejection(e) => write!(f, "Cookie extraction failed: {}", e),
103 ExtractorError::MultipartRejection(e) => write!(f, "Multipart extraction failed: {}", e),
104 ExtractorError::WebSocketUpgradeRejection(e) => write!(f, "WebSocketUpgrade extraction failed: {}", e),
105 ExtractorError::BytesRejection(e) => write!(f, "Bytes extraction failed: {}", e),
106 ExtractorError::StreamRejection(e) => write!(f, "Stream extraction failed: {}", e),
107 ExtractorError::Custom(msg) => write!(f, "Extractor error: {}", msg),
108 }
109 }
110}
111
112impl std::error::Error for ExtractorError {}
113
114#[derive(Debug, Clone)]
128pub struct Path<T>(pub T);
129
130impl<T, S> FromRequestParts<S> for Path<T>
131where
132 T: std::str::FromStr,
133 T::Err: std::fmt::Display,
134{
135 type Error = ExtractorError;
136
137 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
138 if let Some((_, value)) = parts.path_params.first() {
139 T::from_str(value)
140 .map(Path)
141 .map_err(|e| ExtractorError::PathRejection(format!("Failed to parse path parameter: {}", e)))
142 }
143 else {
144 Err(ExtractorError::PathRejection("No path parameters found".to_string()))
145 }
146 }
147}
148
149#[derive(Debug, Clone, serde::Deserialize)]
170pub struct Query<T>(pub T);
171
172impl<T, S> FromRequestParts<S> for Query<T>
173where
174 T: DeserializeOwned,
175{
176 type Error = ExtractorError;
177
178 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
179 let query = parts.uri.query().unwrap_or_default();
180 serde_urlencoded::from_str(query)
181 .map(Query)
182 .map_err(|e| ExtractorError::QueryRejection(format!("Failed to parse query parameters: {}", e)))
183 }
184}
185
186#[derive(Debug, Clone, serde::Deserialize)]
207pub struct Json<T>(pub T);
208
209#[derive(Debug, Clone, serde::Deserialize)]
230pub struct Form<T>(pub T);
231
232#[derive(Debug, Clone)]
246pub struct Header<T>(pub T);
247
248pub type HttpMethod = Method;
252
253impl<S> FromRequestParts<S> for HttpMethod {
254 type Error = ExtractorError;
255
256 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
257 Ok(parts.method.clone())
258 }
259}
260
261pub type RequestUri = Uri;
265
266impl<S> FromRequestParts<S> for RequestUri {
267 type Error = ExtractorError;
268
269 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
270 Ok(parts.uri.clone())
271 }
272}
273
274impl<S> FromRequestParts<S> for RequestParts {
275 type Error = ExtractorError;
276
277 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
278 Ok(parts.clone())
279 }
280}
281
282impl Clone for RequestParts {
283 fn clone(&self) -> Self {
284 Self {
285 method: self.method.clone(),
286 uri: self.uri.clone(),
287 version: self.version,
288 headers: self.headers.clone(),
289 path_params: self.path_params.clone(),
290 }
291 }
292}
293
294pub type HttpVersion = Version;
298
299impl<S> FromRequestParts<S> for HttpVersion {
300 type Error = ExtractorError;
301
302 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
303 Ok(parts.version)
304 }
305}
306
307pub type Headers = HeaderMap;
311
312impl<S> FromRequestParts<S> for Headers {
313 type Error = ExtractorError;
314
315 fn from_request_parts(parts: &RequestParts, _state: &S) -> Result<Self, Self::Error> {
316 Ok(parts.headers.clone())
317 }
318}
319
320#[derive(Debug, Clone)]
322pub struct Extension<T>(pub T);
323
324#[derive(Debug, Clone)]
326pub struct Multipart;
327
328pub type OriginalUri = http::Uri;
330
331#[derive(Debug, Clone)]
345pub struct State<T>(pub T);
346
347impl<T, S> FromRequestParts<S> for State<T>
348where
349 T: Clone + Send + Sync + 'static,
350 S: std::ops::Deref<Target = T>,
351{
352 type Error = ExtractorError;
353
354 fn from_request_parts(_parts: &RequestParts, state: &S) -> Result<Self, Self::Error> {
355 Ok(State(state.deref().clone()))
356 }
357}
358
359#[derive(Debug, Clone)]
361pub struct WebSocketUpgrade;
362
363pub type Stream = crate::Body;
367
368macro_rules! impl_from_request_parts_tuple {
370 ($($ty:ident),*) => {
371 #[allow(non_snake_case, unused_variables)]
372 impl<S, $($ty,)*> FromRequestParts<S> for ($($ty,)*)
373 where
374 $($ty: FromRequestParts<S, Error = ExtractorError>,)*
375 {
376 type Error = ExtractorError;
377
378 fn from_request_parts(parts: &RequestParts, state: &S) -> Result<Self, Self::Error> {
379 Ok(($(
380 $ty::from_request_parts(parts, state)?,
381 )*))
382 }
383 }
384 };
385}
386
387impl_from_request_parts_tuple!();
388impl_from_request_parts_tuple!(T1);
389impl_from_request_parts_tuple!(T1, T2);
390impl_from_request_parts_tuple!(T1, T2, T3);
391impl_from_request_parts_tuple!(T1, T2, T3, T4);
392impl_from_request_parts_tuple!(T1, T2, T3, T4, T5);
393impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6);
394impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7);
395impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
396impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
397impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
398impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
399impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
400impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
401impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
402impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
403impl_from_request_parts_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);