Skip to main content

a3s_boot/routing/route/
builders.rs

1use super::definition::RouteDefinition;
2use crate::routing::handler::RouteHandler;
3use crate::{
4    BootRequest, BootResponse, HttpMethod, ModuleRef, OpenApiResponse, Result, SseEvent, Validate,
5};
6use futures_core::Stream;
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9use std::future::Future;
10
11impl RouteDefinition {
12    pub fn all<H>(path: impl Into<String>, handler: H) -> Result<Self>
13    where
14        H: RouteHandler,
15    {
16        Self::new(HttpMethod::All, path, handler)
17    }
18
19    pub fn all_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
20    where
21        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
22        H: RouteHandler,
23    {
24        Self::new_scoped(HttpMethod::All, path, factory)
25    }
26
27    pub fn all_json<H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
28    where
29        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
30        Fut: Future<Output = Result<R>> + Send + 'static,
31        R: Serialize + Send + 'static,
32    {
33        Self::all_json_with_status(path, 200, handler)
34    }
35
36    pub fn all_json_with_status<H, Fut, R>(
37        path: impl Into<String>,
38        status: u16,
39        handler: H,
40    ) -> Result<Self>
41    where
42        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
43        Fut: Future<Output = Result<R>> + Send + 'static,
44        R: Serialize + Send + 'static,
45    {
46        Self::json_response_with_status(HttpMethod::All, path, status, handler)
47    }
48
49    pub fn get<H>(path: impl Into<String>, handler: H) -> Result<Self>
50    where
51        H: RouteHandler,
52    {
53        Self::new(HttpMethod::Get, path, handler)
54    }
55
56    pub fn get_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
57    where
58        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
59        H: RouteHandler,
60    {
61        Self::new_scoped(HttpMethod::Get, path, factory)
62    }
63
64    pub fn get_json<H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
65    where
66        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
67        Fut: Future<Output = Result<R>> + Send + 'static,
68        R: Serialize + Send + 'static,
69    {
70        Self::get_json_with_status(path, 200, handler)
71    }
72
73    pub fn get_json_with_status<H, Fut, R>(
74        path: impl Into<String>,
75        status: u16,
76        handler: H,
77    ) -> Result<Self>
78    where
79        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
80        Fut: Future<Output = Result<R>> + Send + 'static,
81        R: Serialize + Send + 'static,
82    {
83        Self::json_response_with_status(HttpMethod::Get, path, status, handler)
84    }
85
86    pub fn sse<H, Fut, S>(path: impl Into<String>, handler: H) -> Result<Self>
87    where
88        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
89        Fut: Future<Output = Result<S>> + Send + 'static,
90        S: Stream<Item = Result<SseEvent>> + Send + 'static,
91    {
92        Self::new(HttpMethod::Get, path, move |request: BootRequest| {
93            let future = request
94                .require_accepts_event_stream()
95                .map(|()| handler(request));
96            async move {
97                let stream = future?.await?;
98                Ok(BootResponse::sse(stream))
99            }
100        })
101    }
102
103    pub fn post<H>(path: impl Into<String>, handler: H) -> Result<Self>
104    where
105        H: RouteHandler,
106    {
107        Self::new(HttpMethod::Post, path, handler)
108    }
109
110    pub fn post_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
111    where
112        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
113        H: RouteHandler,
114    {
115        Self::new_scoped(HttpMethod::Post, path, factory)
116    }
117
118    pub fn post_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
119    where
120        T: DeserializeOwned + Send + 'static,
121        H: Fn(T) -> Fut + Send + Sync + 'static,
122        Fut: Future<Output = Result<R>> + Send + 'static,
123        R: Serialize + Send + 'static,
124    {
125        Self::post_json_with_status(path, 200, handler)
126    }
127
128    pub fn post_json_with_status<T, H, Fut, R>(
129        path: impl Into<String>,
130        status: u16,
131        handler: H,
132    ) -> Result<Self>
133    where
134        T: DeserializeOwned + Send + 'static,
135        H: Fn(T) -> Fut + Send + Sync + 'static,
136        Fut: Future<Output = Result<R>> + Send + 'static,
137        R: Serialize + Send + 'static,
138    {
139        Self::json_with_status(HttpMethod::Post, path, status, handler)
140    }
141
142    pub fn post_validated_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
143    where
144        T: DeserializeOwned + Validate + Send + 'static,
145        H: Fn(T) -> Fut + Send + Sync + 'static,
146        Fut: Future<Output = Result<R>> + Send + 'static,
147        R: Serialize + Send + 'static,
148    {
149        Self::post_validated_json_with_status(path, 200, handler)
150    }
151
152    pub fn post_validated_json_with_status<T, H, Fut, R>(
153        path: impl Into<String>,
154        status: u16,
155        handler: H,
156    ) -> Result<Self>
157    where
158        T: DeserializeOwned + Validate + Send + 'static,
159        H: Fn(T) -> Fut + Send + Sync + 'static,
160        Fut: Future<Output = Result<R>> + Send + 'static,
161        R: Serialize + Send + 'static,
162    {
163        Self::validated_json_with_status(HttpMethod::Post, path, status, handler)
164    }
165
166    pub fn put<H>(path: impl Into<String>, handler: H) -> Result<Self>
167    where
168        H: RouteHandler,
169    {
170        Self::new(HttpMethod::Put, path, handler)
171    }
172
173    pub fn put_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
174    where
175        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
176        H: RouteHandler,
177    {
178        Self::new_scoped(HttpMethod::Put, path, factory)
179    }
180
181    pub fn put_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
182    where
183        T: DeserializeOwned + Send + 'static,
184        H: Fn(T) -> Fut + Send + Sync + 'static,
185        Fut: Future<Output = Result<R>> + Send + 'static,
186        R: Serialize + Send + 'static,
187    {
188        Self::put_json_with_status(path, 200, handler)
189    }
190
191    pub fn put_json_with_status<T, H, Fut, R>(
192        path: impl Into<String>,
193        status: u16,
194        handler: H,
195    ) -> Result<Self>
196    where
197        T: DeserializeOwned + Send + 'static,
198        H: Fn(T) -> Fut + Send + Sync + 'static,
199        Fut: Future<Output = Result<R>> + Send + 'static,
200        R: Serialize + Send + 'static,
201    {
202        Self::json_with_status(HttpMethod::Put, path, status, handler)
203    }
204
205    pub fn put_validated_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
206    where
207        T: DeserializeOwned + Validate + Send + 'static,
208        H: Fn(T) -> Fut + Send + Sync + 'static,
209        Fut: Future<Output = Result<R>> + Send + 'static,
210        R: Serialize + Send + 'static,
211    {
212        Self::put_validated_json_with_status(path, 200, handler)
213    }
214
215    pub fn put_validated_json_with_status<T, H, Fut, R>(
216        path: impl Into<String>,
217        status: u16,
218        handler: H,
219    ) -> Result<Self>
220    where
221        T: DeserializeOwned + Validate + Send + 'static,
222        H: Fn(T) -> Fut + Send + Sync + 'static,
223        Fut: Future<Output = Result<R>> + Send + 'static,
224        R: Serialize + Send + 'static,
225    {
226        Self::validated_json_with_status(HttpMethod::Put, path, status, handler)
227    }
228
229    pub fn patch<H>(path: impl Into<String>, handler: H) -> Result<Self>
230    where
231        H: RouteHandler,
232    {
233        Self::new(HttpMethod::Patch, path, handler)
234    }
235
236    pub fn patch_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
237    where
238        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
239        H: RouteHandler,
240    {
241        Self::new_scoped(HttpMethod::Patch, path, factory)
242    }
243
244    pub fn patch_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
245    where
246        T: DeserializeOwned + Send + 'static,
247        H: Fn(T) -> Fut + Send + Sync + 'static,
248        Fut: Future<Output = Result<R>> + Send + 'static,
249        R: Serialize + Send + 'static,
250    {
251        Self::patch_json_with_status(path, 200, handler)
252    }
253
254    pub fn patch_json_with_status<T, H, Fut, R>(
255        path: impl Into<String>,
256        status: u16,
257        handler: H,
258    ) -> Result<Self>
259    where
260        T: DeserializeOwned + Send + 'static,
261        H: Fn(T) -> Fut + Send + Sync + 'static,
262        Fut: Future<Output = Result<R>> + Send + 'static,
263        R: Serialize + Send + 'static,
264    {
265        Self::json_with_status(HttpMethod::Patch, path, status, handler)
266    }
267
268    pub fn patch_validated_json<T, H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
269    where
270        T: DeserializeOwned + Validate + Send + 'static,
271        H: Fn(T) -> Fut + Send + Sync + 'static,
272        Fut: Future<Output = Result<R>> + Send + 'static,
273        R: Serialize + Send + 'static,
274    {
275        Self::patch_validated_json_with_status(path, 200, handler)
276    }
277
278    pub fn patch_validated_json_with_status<T, H, Fut, R>(
279        path: impl Into<String>,
280        status: u16,
281        handler: H,
282    ) -> Result<Self>
283    where
284        T: DeserializeOwned + Validate + Send + 'static,
285        H: Fn(T) -> Fut + Send + Sync + 'static,
286        Fut: Future<Output = Result<R>> + Send + 'static,
287        R: Serialize + Send + 'static,
288    {
289        Self::validated_json_with_status(HttpMethod::Patch, path, status, handler)
290    }
291
292    pub fn delete<H>(path: impl Into<String>, handler: H) -> Result<Self>
293    where
294        H: RouteHandler,
295    {
296        Self::new(HttpMethod::Delete, path, handler)
297    }
298
299    pub fn delete_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
300    where
301        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
302        H: RouteHandler,
303    {
304        Self::new_scoped(HttpMethod::Delete, path, factory)
305    }
306
307    pub fn delete_json<H, Fut, R>(path: impl Into<String>, handler: H) -> Result<Self>
308    where
309        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
310        Fut: Future<Output = Result<R>> + Send + 'static,
311        R: Serialize + Send + 'static,
312    {
313        Self::delete_json_with_status(path, 200, handler)
314    }
315
316    pub fn delete_json_with_status<H, Fut, R>(
317        path: impl Into<String>,
318        status: u16,
319        handler: H,
320    ) -> Result<Self>
321    where
322        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
323        Fut: Future<Output = Result<R>> + Send + 'static,
324        R: Serialize + Send + 'static,
325    {
326        Self::json_response_with_status(HttpMethod::Delete, path, status, handler)
327    }
328
329    pub fn options<H>(path: impl Into<String>, handler: H) -> Result<Self>
330    where
331        H: RouteHandler,
332    {
333        Self::new(HttpMethod::Options, path, handler)
334    }
335
336    pub fn options_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
337    where
338        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
339        H: RouteHandler,
340    {
341        Self::new_scoped(HttpMethod::Options, path, factory)
342    }
343
344    pub fn head<H>(path: impl Into<String>, handler: H) -> Result<Self>
345    where
346        H: RouteHandler,
347    {
348        Self::new(HttpMethod::Head, path, handler)
349    }
350
351    pub fn head_scoped<F, H>(path: impl Into<String>, factory: F) -> Result<Self>
352    where
353        F: Fn(&ModuleRef) -> Result<H> + Send + Sync + 'static,
354        H: RouteHandler,
355    {
356        Self::new_scoped(HttpMethod::Head, path, factory)
357    }
358
359    fn json_with_status<T, H, Fut, R>(
360        method: HttpMethod,
361        path: impl Into<String>,
362        status: u16,
363        handler: H,
364    ) -> Result<Self>
365    where
366        T: DeserializeOwned + Send + 'static,
367        H: Fn(T) -> Fut + Send + Sync + 'static,
368        Fut: Future<Output = Result<R>> + Send + 'static,
369        R: Serialize + Send + 'static,
370    {
371        Self::new(method, path, move |request: BootRequest| {
372            let future = request
373                .require_json_content_type()
374                .and_then(|()| request.require_accepts_json())
375                .and_then(|()| request.json::<T>())
376                .map(&handler);
377            async move {
378                let body = future?.await?;
379                BootResponse::json_with_status(status, &body)
380            }
381        })
382        .map(|route| route.with_response(status, OpenApiResponse::description("Success")))
383    }
384
385    fn json_response_with_status<H, Fut, R>(
386        method: HttpMethod,
387        path: impl Into<String>,
388        status: u16,
389        handler: H,
390    ) -> Result<Self>
391    where
392        H: Fn(BootRequest) -> Fut + Send + Sync + 'static,
393        Fut: Future<Output = Result<R>> + Send + 'static,
394        R: Serialize + Send + 'static,
395    {
396        Self::new(method, path, move |request: BootRequest| {
397            let future = request.require_accepts_json().map(|()| handler(request));
398            async move {
399                let body = future?.await?;
400                BootResponse::json_with_status(status, &body)
401            }
402        })
403        .map(|route| route.with_response(status, OpenApiResponse::description("Success")))
404    }
405
406    fn validated_json_with_status<T, H, Fut, R>(
407        method: HttpMethod,
408        path: impl Into<String>,
409        status: u16,
410        handler: H,
411    ) -> Result<Self>
412    where
413        T: DeserializeOwned + Validate + Send + 'static,
414        H: Fn(T) -> Fut + Send + Sync + 'static,
415        Fut: Future<Output = Result<R>> + Send + 'static,
416        R: Serialize + Send + 'static,
417    {
418        Self::json_with_status(method, path, status, handler)
419            .map(|route| route.with_body_validation::<T>().with_validation())
420    }
421}