wasm_runner_sdk/
handler.rs

1//! Handler trait and implementations for request handlers.
2//!
3//! The Handler trait enables ergonomic function handlers with automatic
4//! extraction of request data.
5
6use crate::extract::FromRequest;
7use crate::request::Request;
8use crate::response::IntoResponse;
9
10/// Trait for request handlers.
11///
12/// This trait is implemented for functions that take extractors and return
13/// something that implements `IntoResponse`. You typically don't need to
14/// implement this trait manually - it's automatically implemented for
15/// functions with up to 6 extractor arguments.
16pub trait Handler<Args> {
17    /// The response type returned by this handler.
18    type Output: IntoResponse;
19
20    /// Handles the request and returns a response.
21    fn call(self, req: &mut Request) -> Self::Output;
22}
23
24// Implementation for functions with no arguments
25impl<F, R> Handler<()> for F
26where
27    F: FnOnce() -> R,
28    R: IntoResponse,
29{
30    type Output = R;
31
32    fn call(self, _req: &mut Request) -> Self::Output {
33        self()
34    }
35}
36
37// Implementation for functions with 1 extractor
38impl<F, R, T1> Handler<(T1,)> for F
39where
40    F: FnOnce(T1) -> R,
41    R: IntoResponse,
42    T1: FromRequest,
43    T1::Error: IntoResponse,
44{
45    type Output = Result<R, T1::Error>;
46
47    fn call(self, req: &mut Request) -> Self::Output {
48        let t1 = T1::from_request(req)?;
49        Ok(self(t1))
50    }
51}
52
53// Implementation for functions with 2 extractors
54impl<F, R, T1, T2> Handler<(T1, T2)> for F
55where
56    F: FnOnce(T1, T2) -> R,
57    R: IntoResponse,
58    T1: FromRequest,
59    T1::Error: IntoResponse,
60    T2: FromRequest,
61    T2::Error: IntoResponse,
62{
63    type Output = Result<R, ExtractErrors2<T1::Error, T2::Error>>;
64
65    fn call(self, req: &mut Request) -> Self::Output {
66        let t1 = T1::from_request(req).map_err(ExtractErrors2::E1)?;
67        let t2 = T2::from_request(req).map_err(ExtractErrors2::E2)?;
68        Ok(self(t1, t2))
69    }
70}
71
72// Implementation for functions with 3 extractors
73impl<F, R, T1, T2, T3> Handler<(T1, T2, T3)> for F
74where
75    F: FnOnce(T1, T2, T3) -> R,
76    R: IntoResponse,
77    T1: FromRequest,
78    T1::Error: IntoResponse,
79    T2: FromRequest,
80    T2::Error: IntoResponse,
81    T3: FromRequest,
82    T3::Error: IntoResponse,
83{
84    type Output = Result<R, ExtractErrors3<T1::Error, T2::Error, T3::Error>>;
85
86    fn call(self, req: &mut Request) -> Self::Output {
87        let t1 = T1::from_request(req).map_err(ExtractErrors3::E1)?;
88        let t2 = T2::from_request(req).map_err(ExtractErrors3::E2)?;
89        let t3 = T3::from_request(req).map_err(ExtractErrors3::E3)?;
90        Ok(self(t1, t2, t3))
91    }
92}
93
94// Implementation for functions with 4 extractors
95impl<F, R, T1, T2, T3, T4> Handler<(T1, T2, T3, T4)> for F
96where
97    F: FnOnce(T1, T2, T3, T4) -> R,
98    R: IntoResponse,
99    T1: FromRequest,
100    T1::Error: IntoResponse,
101    T2: FromRequest,
102    T2::Error: IntoResponse,
103    T3: FromRequest,
104    T3::Error: IntoResponse,
105    T4: FromRequest,
106    T4::Error: IntoResponse,
107{
108    type Output = Result<R, ExtractErrors4<T1::Error, T2::Error, T3::Error, T4::Error>>;
109
110    fn call(self, req: &mut Request) -> Self::Output {
111        let t1 = T1::from_request(req).map_err(ExtractErrors4::E1)?;
112        let t2 = T2::from_request(req).map_err(ExtractErrors4::E2)?;
113        let t3 = T3::from_request(req).map_err(ExtractErrors4::E3)?;
114        let t4 = T4::from_request(req).map_err(ExtractErrors4::E4)?;
115        Ok(self(t1, t2, t3, t4))
116    }
117}
118
119// Implementation for functions with 5 extractors
120impl<F, R, T1, T2, T3, T4, T5> Handler<(T1, T2, T3, T4, T5)> for F
121where
122    F: FnOnce(T1, T2, T3, T4, T5) -> R,
123    R: IntoResponse,
124    T1: FromRequest,
125    T1::Error: IntoResponse,
126    T2: FromRequest,
127    T2::Error: IntoResponse,
128    T3: FromRequest,
129    T3::Error: IntoResponse,
130    T4: FromRequest,
131    T4::Error: IntoResponse,
132    T5: FromRequest,
133    T5::Error: IntoResponse,
134{
135    type Output = Result<R, ExtractErrors5<T1::Error, T2::Error, T3::Error, T4::Error, T5::Error>>;
136
137    fn call(self, req: &mut Request) -> Self::Output {
138        let t1 = T1::from_request(req).map_err(ExtractErrors5::E1)?;
139        let t2 = T2::from_request(req).map_err(ExtractErrors5::E2)?;
140        let t3 = T3::from_request(req).map_err(ExtractErrors5::E3)?;
141        let t4 = T4::from_request(req).map_err(ExtractErrors5::E4)?;
142        let t5 = T5::from_request(req).map_err(ExtractErrors5::E5)?;
143        Ok(self(t1, t2, t3, t4, t5))
144    }
145}
146
147// Implementation for functions with 6 extractors
148impl<F, R, T1, T2, T3, T4, T5, T6> Handler<(T1, T2, T3, T4, T5, T6)> for F
149where
150    F: FnOnce(T1, T2, T3, T4, T5, T6) -> R,
151    R: IntoResponse,
152    T1: FromRequest,
153    T1::Error: IntoResponse,
154    T2: FromRequest,
155    T2::Error: IntoResponse,
156    T3: FromRequest,
157    T3::Error: IntoResponse,
158    T4: FromRequest,
159    T4::Error: IntoResponse,
160    T5: FromRequest,
161    T5::Error: IntoResponse,
162    T6: FromRequest,
163    T6::Error: IntoResponse,
164{
165    type Output = Result<
166        R,
167        ExtractErrors6<T1::Error, T2::Error, T3::Error, T4::Error, T5::Error, T6::Error>,
168    >;
169
170    fn call(self, req: &mut Request) -> Self::Output {
171        let t1 = T1::from_request(req).map_err(ExtractErrors6::E1)?;
172        let t2 = T2::from_request(req).map_err(ExtractErrors6::E2)?;
173        let t3 = T3::from_request(req).map_err(ExtractErrors6::E3)?;
174        let t4 = T4::from_request(req).map_err(ExtractErrors6::E4)?;
175        let t5 = T5::from_request(req).map_err(ExtractErrors6::E5)?;
176        let t6 = T6::from_request(req).map_err(ExtractErrors6::E6)?;
177        Ok(self(t1, t2, t3, t4, t5, t6))
178    }
179}
180
181// Error wrapper types for multiple extractors
182
183/// Error type for handlers with 2 extractors.
184pub enum ExtractErrors2<E1, E2> {
185    E1(E1),
186    E2(E2),
187}
188
189impl<E1: IntoResponse, E2: IntoResponse> IntoResponse for ExtractErrors2<E1, E2> {
190    fn into_response(self) -> crate::response::Response {
191        match self {
192            ExtractErrors2::E1(e) => e.into_response(),
193            ExtractErrors2::E2(e) => e.into_response(),
194        }
195    }
196}
197
198/// Error type for handlers with 3 extractors.
199pub enum ExtractErrors3<E1, E2, E3> {
200    E1(E1),
201    E2(E2),
202    E3(E3),
203}
204
205impl<E1: IntoResponse, E2: IntoResponse, E3: IntoResponse> IntoResponse
206    for ExtractErrors3<E1, E2, E3>
207{
208    fn into_response(self) -> crate::response::Response {
209        match self {
210            ExtractErrors3::E1(e) => e.into_response(),
211            ExtractErrors3::E2(e) => e.into_response(),
212            ExtractErrors3::E3(e) => e.into_response(),
213        }
214    }
215}
216
217/// Error type for handlers with 4 extractors.
218pub enum ExtractErrors4<E1, E2, E3, E4> {
219    E1(E1),
220    E2(E2),
221    E3(E3),
222    E4(E4),
223}
224
225impl<E1: IntoResponse, E2: IntoResponse, E3: IntoResponse, E4: IntoResponse> IntoResponse
226    for ExtractErrors4<E1, E2, E3, E4>
227{
228    fn into_response(self) -> crate::response::Response {
229        match self {
230            ExtractErrors4::E1(e) => e.into_response(),
231            ExtractErrors4::E2(e) => e.into_response(),
232            ExtractErrors4::E3(e) => e.into_response(),
233            ExtractErrors4::E4(e) => e.into_response(),
234        }
235    }
236}
237
238/// Error type for handlers with 5 extractors.
239pub enum ExtractErrors5<E1, E2, E3, E4, E5> {
240    E1(E1),
241    E2(E2),
242    E3(E3),
243    E4(E4),
244    E5(E5),
245}
246
247impl<E1: IntoResponse, E2: IntoResponse, E3: IntoResponse, E4: IntoResponse, E5: IntoResponse>
248    IntoResponse for ExtractErrors5<E1, E2, E3, E4, E5>
249{
250    fn into_response(self) -> crate::response::Response {
251        match self {
252            ExtractErrors5::E1(e) => e.into_response(),
253            ExtractErrors5::E2(e) => e.into_response(),
254            ExtractErrors5::E3(e) => e.into_response(),
255            ExtractErrors5::E4(e) => e.into_response(),
256            ExtractErrors5::E5(e) => e.into_response(),
257        }
258    }
259}
260
261/// Error type for handlers with 6 extractors.
262pub enum ExtractErrors6<E1, E2, E3, E4, E5, E6> {
263    E1(E1),
264    E2(E2),
265    E3(E3),
266    E4(E4),
267    E5(E5),
268    E6(E6),
269}
270
271impl<
272        E1: IntoResponse,
273        E2: IntoResponse,
274        E3: IntoResponse,
275        E4: IntoResponse,
276        E5: IntoResponse,
277        E6: IntoResponse,
278    > IntoResponse for ExtractErrors6<E1, E2, E3, E4, E5, E6>
279{
280    fn into_response(self) -> crate::response::Response {
281        match self {
282            ExtractErrors6::E1(e) => e.into_response(),
283            ExtractErrors6::E2(e) => e.into_response(),
284            ExtractErrors6::E3(e) => e.into_response(),
285            ExtractErrors6::E4(e) => e.into_response(),
286            ExtractErrors6::E5(e) => e.into_response(),
287            ExtractErrors6::E6(e) => e.into_response(),
288        }
289    }
290}