Skip to main content

rustbasic_core/
router.rs

1use std::sync::Arc;
2use crate::requests::Request;
3
4
5pub type Response = http::Response<Vec<u8>>;
6
7pub trait IntoResponse {
8    fn into_response(self) -> Response;
9}
10
11impl IntoResponse for Response {
12    fn into_response(self) -> Response {
13        self
14    }
15}
16
17impl IntoResponse for &'static str {
18    fn into_response(self) -> Response {
19        http::Response::builder()
20            .header(http::header::CONTENT_TYPE, "text/plain; charset=utf-8")
21            .body(self.as_bytes().to_vec())
22            .unwrap()
23    }
24}
25
26impl IntoResponse for String {
27    fn into_response(self) -> Response {
28        http::Response::builder()
29            .header(http::header::CONTENT_TYPE, "text/plain; charset=utf-8")
30            .body(self.into_bytes())
31            .unwrap()
32    }
33}
34
35pub struct Html<T>(pub T);
36impl<T: Into<String>> IntoResponse for Html<T> {
37    fn into_response(self) -> Response {
38        http::Response::builder()
39            .header(http::header::CONTENT_TYPE, "text/html; charset=utf-8")
40            .body(self.0.into().into_bytes())
41            .unwrap()
42    }
43}
44
45pub struct Json<T>(pub T);
46impl<T: serde::Serialize> IntoResponse for Json<T> {
47    fn into_response(self) -> Response {
48        let body = serde_json::to_vec(&self.0).unwrap_or_default();
49        http::Response::builder()
50            .header(http::header::CONTENT_TYPE, "application/json")
51            .body(body)
52            .unwrap()
53    }
54}
55
56pub struct Redirect {
57    url: String,
58}
59impl Redirect {
60    pub fn to(url: &str) -> Self {
61        Self { url: url.to_string() }
62    }
63}
64impl IntoResponse for Redirect {
65    fn into_response(self) -> Response {
66        http::Response::builder()
67            .status(http::StatusCode::SEE_OTHER)
68            .header(http::header::LOCATION, &self.url)
69            .body(Vec::new())
70            .unwrap()
71    }
72}
73
74impl IntoResponse for serde_json::Value {
75    fn into_response(self) -> Response {
76        Json(self).into_response()
77    }
78}
79
80impl IntoResponse for http::StatusCode {
81    fn into_response(self) -> Response {
82        http::Response::builder()
83            .status(self)
84            .body(Vec::new())
85            .unwrap()
86    }
87}
88
89impl<T: IntoResponse, E: IntoResponse> IntoResponse for Result<T, E> {
90    fn into_response(self) -> Response {
91        match self {
92            Ok(r) => r.into_response(),
93            Err(e) => e.into_response(),
94        }
95    }
96}
97
98impl<T: IntoResponse> IntoResponse for (http::StatusCode, T) {
99    fn into_response(self) -> Response {
100        let mut res = self.1.into_response();
101        *res.status_mut() = self.0;
102        res
103    }
104}
105
106#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
107pub struct State<T>(pub T);
108
109#[crate::async_trait]
110pub trait Handler<T>: Send + Sync + 'static {
111    async fn call(&self, req: Request) -> Response;
112}
113
114#[crate::async_trait]
115pub trait ErasedHandler: Send + Sync + 'static {
116    async fn call(&self, req: Request) -> Response;
117}
118
119pub struct HandlerWrapper<H, T> {
120    pub(crate) handler: H,
121    pub(crate) _marker: std::marker::PhantomData<T>,
122}
123
124#[crate::async_trait]
125impl<H, T> ErasedHandler for HandlerWrapper<H, T>
126where
127    H: Handler<T>,
128    T: Send + Sync + 'static,
129{
130    async fn call(&self, req: Request) -> Response {
131        self.handler.call(req).await
132    }
133}
134
135// Arity 0: fn() -> R
136#[crate::async_trait]
137impl<F, Fut, R> Handler<()> for F
138where
139    F: Fn() -> Fut + Send + Sync + 'static,
140    Fut: std::future::Future<Output = R> + Send + 'static,
141    R: IntoResponse + Send + 'static,
142{
143    async fn call(&self, _req: Request) -> Response {
144        self().await.into_response()
145    }
146}
147
148// Arity 1: fn(Request) -> R
149#[crate::async_trait]
150impl<F, Fut, R> Handler<(Request,)> for F
151where
152    F: Fn(Request) -> Fut + Send + Sync + 'static,
153    Fut: std::future::Future<Output = R> + Send + 'static,
154    R: IntoResponse + Send + 'static,
155{
156    async fn call(&self, req: Request) -> Response {
157        self(req).await.into_response()
158    }
159}
160
161// Arity 2: fn(State<AppState>, Request) -> R
162#[crate::async_trait]
163impl<F, Fut, R> Handler<(State<crate::AppState>, Request)> for F
164where
165    F: Fn(State<crate::AppState>, Request) -> Fut + Send + Sync + 'static,
166    Fut: std::future::Future<Output = R> + Send + 'static,
167    R: IntoResponse + Send + 'static,
168{
169    async fn call(&self, req: Request) -> Response {
170        let state = State(req.state.clone());
171        self(state, req).await.into_response()
172    }
173}
174
175#[derive(Clone)]
176pub struct MethodRouter {
177    pub(crate) handlers: Vec<(http::Method, Arc<dyn ErasedHandler>)>,
178}
179
180pub fn get<H, T>(handler: H) -> MethodRouter
181where
182    H: Handler<T>,
183    T: Send + Sync + 'static,
184{
185    let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
186        handler,
187        _marker: std::marker::PhantomData,
188    });
189    MethodRouter {
190        handlers: vec![(http::Method::GET, wrapped)],
191    }
192}
193
194pub fn post<H, T>(handler: H) -> MethodRouter
195where
196    H: Handler<T>,
197    T: Send + Sync + 'static,
198{
199    let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
200        handler,
201        _marker: std::marker::PhantomData,
202    });
203    MethodRouter {
204        handlers: vec![(http::Method::POST, wrapped)],
205    }
206}
207
208pub fn put<H, T>(handler: H) -> MethodRouter
209where
210    H: Handler<T>,
211    T: Send + Sync + 'static,
212{
213    let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
214        handler,
215        _marker: std::marker::PhantomData,
216    });
217    MethodRouter {
218        handlers: vec![(http::Method::PUT, wrapped)],
219    }
220}
221
222pub fn patch<H, T>(handler: H) -> MethodRouter
223where
224    H: Handler<T>,
225    T: Send + Sync + 'static,
226{
227    let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
228        handler,
229        _marker: std::marker::PhantomData,
230    });
231    MethodRouter {
232        handlers: vec![(http::Method::PATCH, wrapped)],
233    }
234}
235
236pub fn delete<H, T>(handler: H) -> MethodRouter
237where
238    H: Handler<T>,
239    T: Send + Sync + 'static,
240{
241    let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
242        handler,
243        _marker: std::marker::PhantomData,
244    });
245    MethodRouter {
246        handlers: vec![(http::Method::DELETE, wrapped)],
247    }
248}
249
250impl MethodRouter {
251    pub fn get<H, T>(mut self, handler: H) -> Self
252    where
253        H: Handler<T>,
254        T: Send + Sync + 'static,
255    {
256        let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
257            handler,
258            _marker: std::marker::PhantomData,
259        });
260        self.handlers.push((http::Method::GET, wrapped));
261        self
262    }
263    
264    pub fn post<H, T>(mut self, handler: H) -> Self
265    where
266        H: Handler<T>,
267        T: Send + Sync + 'static,
268    {
269        let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
270            handler,
271            _marker: std::marker::PhantomData,
272        });
273        self.handlers.push((http::Method::POST, wrapped));
274        self
275    }
276    
277    pub fn put<H, T>(mut self, handler: H) -> Self
278    where
279        H: Handler<T>,
280        T: Send + Sync + 'static,
281    {
282        let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
283            handler,
284            _marker: std::marker::PhantomData,
285        });
286        self.handlers.push((http::Method::PUT, wrapped));
287        self
288    }
289
290    pub fn patch<H, T>(mut self, handler: H) -> Self
291    where
292        H: Handler<T>,
293        T: Send + Sync + 'static,
294    {
295        let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
296            handler,
297            _marker: std::marker::PhantomData,
298        });
299        self.handlers.push((http::Method::PATCH, wrapped));
300        self
301    }
302
303    pub fn delete<H, T>(mut self, handler: H) -> Self
304    where
305        H: Handler<T>,
306        T: Send + Sync + 'static,
307    {
308        let wrapped: Arc<dyn ErasedHandler> = Arc::new(HandlerWrapper {
309            handler,
310            _marker: std::marker::PhantomData,
311        });
312        self.handlers.push((http::Method::DELETE, wrapped));
313        self
314    }
315}
316
317#[derive(Clone)]
318pub struct Router<S = ()> {
319    pub(crate) routes: Vec<Arc<Route>>,
320    pub(crate) middlewares: Vec<crate::middleware::MiddlewareFn>,
321    pub(crate) _marker: std::marker::PhantomData<fn() -> S>,
322}
323
324pub struct Route {
325    pub path: String,
326    pub handlers: Vec<(http::Method, Arc<dyn ErasedHandler>)>,
327}
328
329struct MiddlewareHandler {
330    mw: crate::middleware::MiddlewareFn,
331    next: Arc<dyn ErasedHandler>,
332}
333
334#[crate::async_trait]
335impl ErasedHandler for MiddlewareHandler {
336    async fn call(&self, req: Request) -> Response {
337        let chain = Arc::new(crate::middleware::MiddlewareChain::End(self.next.clone()));
338        let next = crate::middleware::Next { chain };
339        (self.mw)(req, next).await
340    }
341}
342
343impl<S> Router<S> {
344    pub fn new() -> Self {
345        Self {
346            routes: Vec::new(),
347            middlewares: Vec::new(),
348            _marker: std::marker::PhantomData,
349        }
350    }
351
352    pub fn route(mut self, path: &str, method_router: MethodRouter) -> Self {
353        self.routes.push(Arc::new(Route {
354            path: path.to_string(),
355            handlers: method_router.handlers,
356        }));
357        self
358    }
359
360    pub fn get_json<T>(self, path: &str, data: T) -> Self
361    where
362        T: serde::Serialize + Clone + Send + Sync + 'static,
363    {
364        let data_clone = data.clone();
365        self.route(path, get(move || {
366            let data = data_clone.clone();
367            async move {
368                Json(data)
369            }
370        }))
371    }
372
373    pub fn get_redirect(self, path: &str, to_url: &str) -> Self {
374        let to_url = to_url.to_string();
375        self.route(path, get(move || {
376            let to = to_url.clone();
377            async move {
378                Redirect::to(&to)
379            }
380        }))
381    }
382
383    pub fn get_view(self, path: &str, template: &'static str, context: serde_json::Value) -> Self {
384        let context_clone = context.clone();
385        self.route(path, get(move |req: Request| {
386            let ctx = context_clone.clone();
387            async move {
388                crate::view::view(&req, template, minijinja::Value::from_serialize(ctx))
389            }
390        }))
391    }
392
393    pub fn merge(mut self, other: Router<S>) -> Self {
394        for other_route in other.routes {
395            let mut handlers_with_mw = Vec::new();
396            for (method, handler) in &other_route.handlers {
397                let mut current_handler = handler.clone();
398                for mw in other.middlewares.iter().rev() {
399                    let next_handler = current_handler.clone();
400                    let mw_clone = mw.clone();
401                    current_handler = Arc::new(MiddlewareHandler {
402                        mw: mw_clone,
403                        next: next_handler,
404                    });
405                }
406                handlers_with_mw.push((method.clone(), current_handler));
407            }
408            self.routes.push(Arc::new(Route {
409                path: other_route.path.clone(),
410                handlers: handlers_with_mw,
411            }));
412        }
413        self
414    }
415
416    pub fn nest(mut self, prefix: &str, other: Router<S>) -> Self {
417        let clean_prefix = prefix.trim_end_matches('/');
418        for other_route in other.routes {
419            let mut handlers_with_mw = Vec::new();
420            for (method, handler) in &other_route.handlers {
421                let mut current_handler = handler.clone();
422                for mw in other.middlewares.iter().rev() {
423                    let next_handler = current_handler.clone();
424                    let mw_clone = mw.clone();
425                    current_handler = Arc::new(MiddlewareHandler {
426                        mw: mw_clone,
427                        next: next_handler,
428                    });
429                }
430                handlers_with_mw.push((method.clone(), current_handler));
431            }
432            let nested_path = format!("{}{}", clean_prefix, other_route.path);
433            self.routes.push(Arc::new(Route {
434                path: nested_path,
435                handlers: handlers_with_mw,
436            }));
437        }
438        self
439    }
440
441    pub fn layer(mut self, mw: crate::middleware::MiddlewareFn) -> Self {
442        self.middlewares.push(mw);
443        self
444    }
445}