cogo_http/route/
mod.rs

1use std::any::Any;
2use std::collections::{BTreeMap, HashMap};
3use std::error::Error;
4use std::fmt::{Debug, Formatter};
5use crate::net::Fresh;
6use crate::server::{Handler, Request, Response};
7use crate::status::StatusCode;
8use crate::uri::RequestUri::AbsolutePath;
9use std::io::copy;
10use std::ops::Deref;
11use std::sync::Arc;
12use crate::runtime::{SyncHashMap};
13use crate::uri::RequestUri;
14
15pub struct HandleBox {
16    pub url: String,
17    pub inner: Box<dyn Handler>,
18}
19
20impl Debug for HandleBox {
21    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22        f.debug_struct("HandleBox")
23            .field("url", &self.url)
24            .field("inner", &"*")
25            .finish()
26    }
27}
28
29pub trait MiddleWare: Send + Sync + Debug {
30    //return is finish. if finish will be return
31    fn handle(&self, req: &mut Request, res: &mut Response) -> bool;
32}
33
34#[derive(Debug)]
35pub struct Route {
36    pub container: SyncHashMap<String, Arc<Box<dyn Any>>>,
37    pub middleware: Vec<Box<dyn MiddleWare>>,
38    pub handlers: SyncHashMap<String, HandleBox>,
39}
40
41
42impl Route {
43    pub fn new() -> Self {
44        Self {
45            container: SyncHashMap::new(),
46            middleware: vec![],
47            handlers: SyncHashMap::new(),
48        }
49    }
50    pub fn handle_fn<H: Handler + 'static>(&self, url: &str, h: H) {
51        self.handlers.insert(url.to_string(), HandleBox {
52            url: url.to_string(),
53            inner: Box::new(h),
54        });
55    }
56
57    pub fn add_middleware<M: MiddleWare + 'static>(&mut self, m: M) {
58        self.middleware.push(Box::new(m));
59    }
60
61    pub fn insert<T: Any>(&self, key: &str, data: T) {
62        self.container.insert(key.to_string(), Arc::new(Box::new(data)));
63    }
64
65    pub fn get<T: Any>(&self, key: &str) -> Option<&T> {
66        match self.container.get(key) {
67            None => {
68                None
69            }
70            Some(b) => {
71                let r: Option<&T> = b.downcast_ref();
72                r
73            }
74        }
75    }
76
77    /// index will get from container.if not exist will be panic!
78    pub fn index<T: Any>(&self, key: &str) -> &T {
79        self.get(key).expect(&format!("key:{} Does not exist in the container",key))
80    }
81}
82
83
84impl Handler for Route {
85    fn handle(&self, mut req: Request, mut res: Response<'_, Fresh>) {
86        for x in &self.middleware {
87            //finish?.this is safety
88            if x.handle(&mut req, &mut res) {
89                return;
90            }
91        }
92        match &req.uri {
93            AbsolutePath(p) => {
94                let path = &p[0..p.find("?").unwrap_or(p.len())];
95                match self.handlers.get(path) {
96                    None => {
97                        //404
98                        res.status = StatusCode::NotFound;
99                        return;
100                    }
101                    Some(h) => {
102                        let i = &h.inner;
103                        i.handle(req, res);
104                        return;
105                    }
106                }
107            }
108            RequestUri::AbsoluteUri(_) => {}
109            RequestUri::Authority(_) => {}
110            RequestUri::Star => {}
111        }
112    }
113}
114
115impl Handler for Arc<Route> {
116    fn handle(&self, mut req: Request, mut res: Response<'_, Fresh>) {
117        Route::handle(self, req, res)
118    }
119}