mco_http/route/
mod.rs

1use std::any::Any;
2use std::fmt::{Debug, Formatter};
3use std::ops::Deref;
4use crate::net::Fresh;
5use crate::server::{Handler, Request, Response};
6use crate::status::StatusCode;
7use crate::uri::RequestUri::AbsolutePath;
8use std::sync::Arc;
9use crate::runtime::{SyncHashMap, SyncVec};
10use crate::uri::RequestUri;
11
12pub struct HandleBox {
13    pub url: String,
14    pub inner: Box<dyn Handler>,
15}
16
17impl Debug for HandleBox {
18    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
19        f.debug_struct("HandleBox")
20            .field("url", &self.url)
21            .field("inner", &"*")
22            .finish()
23    }
24}
25
26pub trait MiddleWare: Send + Sync {
27    /// if you call take Response, next handle will be not run
28    fn handle(&self, req: &mut Request, res: &mut Option<Response>);
29}
30
31impl<T: MiddleWare> MiddleWare for Arc<T> {
32    fn handle(&self, req: &mut Request, res: &mut Option<Response>) {
33        T::handle(self, req, res)
34    }
35}
36
37impl<F> MiddleWare for F where F: Fn(&mut Request, &mut Option<Response>), F: Sync + Send {
38    fn handle(&self, req: &mut Request, res: &mut Option<Response>) {
39        self(req, res)
40    }
41}
42
43pub struct Route {
44    pub container: SyncHashMap<String, Arc<Box<dyn Any>>>,
45    pub middleware: SyncVec<Box<dyn MiddleWare>>,
46    pub handlers: SyncHashMap<String, HandleBox>,
47}
48
49impl Debug for Route {
50    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51        f.debug_struct("Route")
52            .field("container", &self.container.len())
53            .field("middleware", &self.middleware.len())
54            .field("handlers", &self.handlers)
55            .finish()
56    }
57}
58
59
60impl Route {
61    pub fn new() -> Self {
62        Self {
63            container: SyncHashMap::new(),
64            middleware: SyncVec::new(),
65            handlers: SyncHashMap::new(),
66        }
67    }
68    /// handle a fn
69    /// for example:
70    /// ```rust
71    /// use mco_http::route::Route;
72    /// use mco_http::server::{Request, Response};
73    ///
74    /// let mut route = Route::new();
75    /// //Common way
76    /// route.handle_fn("/", |req: Request, res: Response| {
77    ///         res.send(b"Hello World!").unwrap();
78    ///     });
79    ///
80    /// //or you can use method. It can even nest calls to Handle
81    /// fn hello(req: Request, res: Response) {
82    ///     res.send(b"Hello World!").unwrap();
83    /// }
84    /// route.handle_fn("/",hello);
85    ///
86    ///
87    /// ```
88    pub fn handle_fn<H: Handler + 'static>(&self, url: &str, h: H) {
89        self.handlers.insert(url.to_string(), HandleBox {
90            url: url.to_string(),
91            inner: Box::new(h),
92        });
93    }
94
95    /// if you take Response. handle be done
96    /// for example:
97    /// ```rust
98    /// use mco_http::server::{Request, Response};
99    /// use mco_http::route::Route;
100    /// let mut route = Route::new();
101    /// route.add_middleware(|req: &mut Request, res: &mut Option<Response>|{
102    ///        //res.take() //take Response, next handle will be not run
103    ///     });
104    /// ```
105    pub fn add_middleware<M: MiddleWare + 'static>(&self, m: M) {
106        self.middleware.push(Box::new(m));
107    }
108
109    pub fn insert<T: Any>(&self, key: &str, data: T) {
110        self.container.insert(key.to_string(), Arc::new(Box::new(data)));
111    }
112
113    pub fn get<T: Any>(&self, key: &str) -> Option<&T> {
114        match self.container.get(key) {
115            None => {
116                None
117            }
118            Some(b) => {
119                let r: Option<&T> = b.downcast_ref();
120                r
121            }
122        }
123    }
124
125    /// index will get from container.if not exist will be panic!
126    pub fn index<T: Any>(&self, key: &str) -> &T {
127        self.get(key).expect(&format!("key:{} Does not exist in the container", key))
128    }
129}
130
131
132impl Handler for Route {
133    fn handle<'a, 'k>(&'a self, mut req: Request<'a, 'k>, mut res: Response<'a, Fresh>){
134        for  m in &self.middleware {
135            let mut r = Some(res);
136            //finish?.this is safety
137            m.handle(&mut req, &mut r);
138            if r.is_none() {
139                return;
140            } else {
141                res = r.unwrap();
142            }
143        }
144        match &req.uri {
145            AbsolutePath(p) => {
146                let path = &p[0..p.find("?").unwrap_or(p.len())];
147                match self.handlers.get(path) {
148                    None => {
149                        //404
150                        res.status = StatusCode::NotFound;
151                        return;
152                    }
153                    Some(h) => {
154                        let i = &h.inner;
155                        i.handle(req, res);
156                        return;
157                    }
158                }
159            }
160            RequestUri::AbsoluteUri(_) => {}
161            RequestUri::Authority(_) => {}
162            RequestUri::Star => {}
163        }
164    }
165}
166
167impl Handler for Arc<Route> {
168    fn handle<'a, 'k>(&'a self,  req: Request<'a, 'k>,  res: Response<'a, Fresh>) {
169        self.deref().handle(req,res)
170    }
171}