Skip to main content

volter_core/
handler.rs

1//! The [`Handler`] trait and its blanket impls.
2//!
3//! A `Handler` is any async function whose arguments are extractors and
4//! whose return type implements [`IntoResponse`].  Blanket impls exist for
5//! zero-argument functions, single-extractor functions (both parts-only and
6//! body-consuming), and multi-extractor functions (N >= 2 arguments).
7//!
8//! For multi-extractor handlers the convention is:
9//!
10//! - The first N-1 arguments implement [`FromRequestParts`].
11//! - The last argument implements [`FromRequest`].
12//!
13//! Since every [`FromRequestParts`] type also automatically implements
14//! [`FromRequest`] (see `extract.rs`), a single blanket impl per tuple size
15//! handles both "all parts" and "body last" cases.
16
17use std::future::Future;
18use std::pin::Pin;
19
20use crate::body::{BoxBody, Request, Response};
21use crate::extract::{FromRequest, FromRequestParts};
22use crate::into_response::IntoResponse;
23
24/// A request handler: any async function whose arguments are extractors,
25/// and whose return type implements [`IntoResponse`].
26///
27/// `T` is a marker type parameter used to disambiguate handler function
28/// arities/argument types via blanket impls (see the impl for `()` below).
29pub trait Handler<T, S>: Clone + Send + Sized + 'static {
30    /// The future returned by [`Handler::call`].
31    type Future: Future<Output = Response> + Send + 'static;
32
33    /// Invoke the handler.
34    fn call(self, req: Request, state: S) -> Self::Future;
35}
36
37// ---------------------------------------------------------------------------
38// Blanket impl for zero-argument handlers
39// ---------------------------------------------------------------------------
40
41/// Blanket impl for closures / functions that take zero extractors.
42///
43/// Any async fn `F: Fn() -> Fut` where `Fut: Future<Output = R>` and
44/// `R: IntoResponse` is a valid zero-argument handler.
45impl<F, Fut, R, S> Handler<(), S> for F
46where
47    F: Fn() -> Fut + Clone + Send + 'static,
48    Fut: Future<Output = R> + Send + 'static,
49    R: IntoResponse,
50{
51    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
52
53    fn call(self, _req: Request, _state: S) -> Self::Future {
54        Box::pin(async move { (self)().await.into_response() })
55    }
56}
57
58// ---------------------------------------------------------------------------
59// Blanket impl for single-extractor handlers
60// ---------------------------------------------------------------------------
61
62/// Blanket impl for handlers that take a single extractor argument.
63///
64/// Any async fn `F: Fn(E) -> Fut` where `Fut: Future<Output = R>`,
65/// `R: IntoResponse`, and `E: FromRequest<S, BoxBody>` is a valid handler.
66///
67/// The argument `E` is extracted via [`FromRequest::from_request`], which
68/// gets the full request (including body).  For parts-only extractors the
69/// blanket in `extract.rs` turns this into a simple parts extraction,
70/// dropping the body.  For body-consuming extractors (like [`Json<T>`]) the
71/// body is read and deserialized as normal.
72///
73/// This single blanket replaces what were previously separate impls for
74/// [`FromRequestParts`] (marker `(E,)`) and [`FromRequest`] (marker
75/// `(E, BoxBody)`), because every [`FromRequestParts`] type now also
76/// implements [`FromRequest`] via the blanket in `extract.rs`.
77impl<F, Fut, R, S, E> Handler<(E,), S> for F
78where
79    F: Fn(E) -> Fut + Clone + Send + 'static,
80    Fut: Future<Output = R> + Send + 'static,
81    R: IntoResponse,
82    S: Clone + Send + 'static,
83    E: FromRequest<S, BoxBody> + Send + 'static,
84{
85    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
86
87    fn call(self, req: Request, state: S) -> Self::Future {
88        Box::pin(async move {
89            let extracted = match E::from_request(req, &state).await {
90                Ok(v) => v,
91                Err(rejection) => return rejection.into_response(),
92            };
93            (self)(extracted).await.into_response()
94        })
95    }
96}
97
98// ---------------------------------------------------------------------------
99// Multi-extractor handler impls (2, 3, 4, 5 arguments)
100// ---------------------------------------------------------------------------
101
102/// 2-argument handler: `fn(A, B) -> Fut`.
103///
104/// `A` is extracted via [`FromRequestParts`], `B` is extracted via
105/// [`FromRequest`].  If `A` fails, the body is never touched.
106impl<F, Fut, R, S, A, B> Handler<(A, B), S> for F
107where
108    F: Fn(A, B) -> Fut + Clone + Send + 'static,
109    Fut: Future<Output = R> + Send + 'static,
110    R: IntoResponse,
111    S: Clone + Send + 'static,
112    A: FromRequestParts<S> + Send + 'static,
113    B: FromRequest<S, BoxBody> + Send + 'static,
114{
115    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
116
117    fn call(self, req: Request, state: S) -> Self::Future {
118        Box::pin(async move {
119            let (mut parts, body) = req.into_parts();
120            let a = match A::from_request_parts(&mut parts, &state).await {
121                Ok(v) => v,
122                Err(e) => return e.into_response(),
123            };
124            let b = match B::from_request(Request::from_parts(parts, body), &state).await {
125                Ok(v) => v,
126                Err(e) => return e.into_response(),
127            };
128            (self)(a, b).await.into_response()
129        })
130    }
131}
132
133/// 3-argument handler: `fn(A, B, C) -> Fut`.
134///
135/// `A` and `B` are extracted via [`FromRequestParts`]; `C` is extracted
136/// via [`FromRequest`].  If any of `A` or `B` fails, the body is never
137/// touched.
138impl<F, Fut, R, S, A, B, C> Handler<(A, B, C), S> for F
139where
140    F: Fn(A, B, C) -> Fut + Clone + Send + 'static,
141    Fut: Future<Output = R> + Send + 'static,
142    R: IntoResponse,
143    S: Clone + Send + 'static,
144    A: FromRequestParts<S> + Send + 'static,
145    B: FromRequestParts<S> + Send + 'static,
146    C: FromRequest<S, BoxBody> + Send + 'static,
147{
148    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
149
150    fn call(self, req: Request, state: S) -> Self::Future {
151        Box::pin(async move {
152            let (mut parts, body) = req.into_parts();
153            let a = match A::from_request_parts(&mut parts, &state).await {
154                Ok(v) => v,
155                Err(e) => return e.into_response(),
156            };
157            let b = match B::from_request_parts(&mut parts, &state).await {
158                Ok(v) => v,
159                Err(e) => return e.into_response(),
160            };
161            let c = match C::from_request(Request::from_parts(parts, body), &state).await {
162                Ok(v) => v,
163                Err(e) => return e.into_response(),
164            };
165            (self)(a, b, c).await.into_response()
166        })
167    }
168}
169
170/// 4-argument handler: `fn(A, B, C, D) -> Fut`.
171///
172/// `A`, `B`, and `C` are extracted via [`FromRequestParts`]; `D` is
173/// extracted via [`FromRequest`].
174impl<F, Fut, R, S, A, B, C, D> Handler<(A, B, C, D), S> for F
175where
176    F: Fn(A, B, C, D) -> Fut + Clone + Send + 'static,
177    Fut: Future<Output = R> + Send + 'static,
178    R: IntoResponse,
179    S: Clone + Send + 'static,
180    A: FromRequestParts<S> + Send + 'static,
181    B: FromRequestParts<S> + Send + 'static,
182    C: FromRequestParts<S> + Send + 'static,
183    D: FromRequest<S, BoxBody> + Send + 'static,
184{
185    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
186
187    fn call(self, req: Request, state: S) -> Self::Future {
188        Box::pin(async move {
189            let (mut parts, body) = req.into_parts();
190            let a = match A::from_request_parts(&mut parts, &state).await {
191                Ok(v) => v,
192                Err(e) => return e.into_response(),
193            };
194            let b = match B::from_request_parts(&mut parts, &state).await {
195                Ok(v) => v,
196                Err(e) => return e.into_response(),
197            };
198            let c = match C::from_request_parts(&mut parts, &state).await {
199                Ok(v) => v,
200                Err(e) => return e.into_response(),
201            };
202            let d = match D::from_request(Request::from_parts(parts, body), &state).await {
203                Ok(v) => v,
204                Err(e) => return e.into_response(),
205            };
206            (self)(a, b, c, d).await.into_response()
207        })
208    }
209}
210
211/// 5-argument handler: `fn(A, B, C, D, E) -> Fut`.
212///
213/// `A`, `B`, `C`, `D` are extracted via [`FromRequestParts`]; `E` is
214/// extracted via [`FromRequest`].
215impl<F, Fut, R, S, A, B, C, D, E> Handler<(A, B, C, D, E), S> for F
216where
217    F: Fn(A, B, C, D, E) -> Fut + Clone + Send + 'static,
218    Fut: Future<Output = R> + Send + 'static,
219    R: IntoResponse,
220    S: Clone + Send + 'static,
221    A: FromRequestParts<S> + Send + 'static,
222    B: FromRequestParts<S> + Send + 'static,
223    C: FromRequestParts<S> + Send + 'static,
224    D: FromRequestParts<S> + Send + 'static,
225    E: FromRequest<S, BoxBody> + Send + 'static,
226{
227    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
228
229    fn call(self, req: Request, state: S) -> Self::Future {
230        Box::pin(async move {
231            let (mut parts, body) = req.into_parts();
232            let a = match A::from_request_parts(&mut parts, &state).await {
233                Ok(v) => v,
234                Err(e) => return e.into_response(),
235            };
236            let b = match B::from_request_parts(&mut parts, &state).await {
237                Ok(v) => v,
238                Err(e) => return e.into_response(),
239            };
240            let c = match C::from_request_parts(&mut parts, &state).await {
241                Ok(v) => v,
242                Err(e) => return e.into_response(),
243            };
244            let d = match D::from_request_parts(&mut parts, &state).await {
245                Ok(v) => v,
246                Err(e) => return e.into_response(),
247            };
248            let e = match E::from_request(Request::from_parts(parts, body), &state).await {
249                Ok(v) => v,
250                Err(e) => return e.into_response(),
251            };
252            (self)(a, b, c, d, e).await.into_response()
253        })
254    }
255}