fast_web/
router.rs

1use hyper::header::{self, HeaderName, HeaderValue};
2use hyper::server::conn::AddrStream;
3use hyper::service::{make_service_fn, service_fn};
4use hyper::{Body, Request, Response, Server, StatusCode};
5use log::{debug, error, info, trace, warn};
6use regex::Regex;
7use std::cell::{RefCell, RefMut};
8use std::collections::HashMap;
9use std::fmt::{Debug, Display};
10use std::str::FromStr;
11use std::sync::Arc;
12use std::{convert::Infallible, net::SocketAddr};
13use url::form_urlencoded;
14use urlencoding::decode;
15
16/// 自定义处理函数的参数类型
17pub type Ctx<'a> = RefMut<'a, Context>;
18
19/// json类型的值
20pub type Json = serde_json::Value;
21
22/// 用于把json字符串转json对象值
23pub use serde_json::json;
24
25/// 用于序列化
26pub use serde::Deserialize;
27
28/// 用于反序列化
29pub use serde::Serialize;
30
31/// 请求处理函数
32type Handler = dyn Fn(&mut Ctx) + 'static + Send + Sync;
33
34/// Http 请求类型
35#[derive(Debug, PartialEq, Eq)]
36pub enum Method {
37    TRACE,
38    HEAD,
39    GET,
40    POST,
41    PUT,
42    PATCH,
43    DELETE,
44    OPTIONS,
45    ANY,
46}
47
48impl From<Method> for String {
49    fn from(v: Method) -> Self {
50        format!("{:?}", v)
51    }
52}
53
54impl From<&str> for Method {
55    fn from(s: &str) -> Self {
56        match s.to_uppercase().as_str() {
57            "TRACE" => Self::TRACE,
58            "HEAD" => Self::HEAD,
59            "GET" => Self::GET,
60            "POST" => Self::POST,
61            "PUT" => Self::PUT,
62            "PATCH" => Self::PATCH,
63            "DELETE" => Self::DELETE,
64            "OPTIONS" => Self::OPTIONS,
65            "ANY" => Self::ANY,
66            v => panic!("不存在这个类型:{}", v),
67        }
68    }
69}
70
71/// 包含了每次请求的所有信息以及用户自定义信息
72#[derive(Default)]
73pub struct Context {
74    headers: HashMap<String, String>,
75    params: HashMap<String, String>,
76    queries: HashMap<String, String>,
77
78    // form表单提交的数据
79    forms: HashMap<String, String>,
80
81    // 保存自定义信息
82    datas: HashMap<String, String>,
83
84    response: Response<Body>,
85
86    // 记录是否处理完毕,根据这个值判断是否还继续往后调用处理函数
87    // 最终也根据这个值决定是否返回404,如果为false则返回404
88    // 在 context.string() 等函数中 需要把这个值设置为 ture
89    is_finished: bool,
90
91    // 用于决定是否跳过剩下的前置过滤器
92    is_skip_before_filters: bool,
93
94    // 用于决定是否跳过剩下的后置过滤器
95    is_skip_after_filters: bool,
96
97    // 客户端ip和端口
98    ip: String,
99}
100
101impl Context {
102    /// 获取路由规则中的命名参数值
103    pub fn param<T>(&self, name: &str) -> Option<T>
104    where
105        T: FromStr,
106        <T as FromStr>::Err: Debug,
107    {
108        self.params
109            .get(name.into())
110            .map(|v| v.as_str().parse().unwrap())
111    }
112
113    /// 获取query参数值
114    pub fn query<T>(&self, name: &str) -> Option<T>
115    where
116        T: FromStr,
117        <T as FromStr>::Err: Debug,
118    {
119        self.queries
120            .get(name.into())
121            .map(|v| v.as_str().parse().unwrap())
122    }
123
124    /// 获取请求头中的参数值
125    pub fn header(&self, name: &str) -> Option<String> {
126        self.headers
127            .get(name.to_lowercase().as_str())
128            .map(|v| v.as_str().parse().unwrap())
129    }
130
131    /// 获取 form 表单提交值
132    pub fn form<T>(&self, name: &str) -> Option<T>
133    where
134        T: FromStr,
135        <T as FromStr>::Err: Debug,
136    {
137        self.forms
138            .get(name.into())
139            .map(|v| v.as_str().parse().unwrap())
140    }
141
142    /// 获取自定义数据,前面的处理器可以传给后面的处理器
143    /// 通过 set_data 设置
144    pub fn data<T>(&self, name: &str) -> Option<T>
145    where
146        T: FromStr,
147        <T as FromStr>::Err: Debug,
148    {
149        self.datas
150            .get(name.into())
151            .map(|v| v.as_str().parse().unwrap())
152    }
153
154    /// 获取 header 中的参数值
155    pub fn set_data<T>(&mut self, name: &str, data: T)
156    where
157        T: FromStr + Display,
158        <T as FromStr>::Err: Debug,
159    {
160        if self.datas.contains_key(name) {
161            self.datas.remove(name);
162        }
163        self.datas.insert(name.to_string(), data.to_string());
164    }
165
166    /// 返回客户端的ip+端口
167    pub fn ip(&self) -> String {
168        self.ip.clone()
169    }
170}
171
172impl Context {
173    /// 在前置过滤器中调用才有效,调用后会跳过后面的所有前置过滤器
174    pub fn skip_before_filters(&mut self) {
175        self.is_skip_before_filters = true;
176    }
177
178    /// 判断是否要跳过剩下的前置过滤器
179    pub fn is_skip_before_filters(&self) -> bool {
180        self.is_skip_before_filters
181    }
182
183    /// 调用后会跳过后面的所有后置过滤器,在请求处理函数和后置过滤器中调用才有效
184    pub fn skip_after_filters(&mut self) {
185        self.is_skip_after_filters = true;
186    }
187
188    /// 判断是否要跳过剩下的后置过滤器
189    pub fn is_skip_after_filters(&self) -> bool {
190        self.is_skip_after_filters
191    }
192
193    /// 是否处理完毕
194    pub fn is_finished(&self) -> bool {
195        self.is_finished
196    }
197}
198
199impl Context {
200    /// 设置响应头信息
201    pub fn set_header(&mut self, name: &str, value: &str) {
202        let headers = self.response.headers_mut();
203        headers.insert(
204            HeaderName::from_str(name).unwrap(),
205            HeaderValue::from_str(value).unwrap(),
206        );
207    }
208
209    /// 返回html格式字符串
210    pub fn string(&mut self, data: &str) {
211        self.string_raw(data, "text/html; charset=utf-8");
212    }
213
214    /// 返回纯文本格式字符串,不会解析html标签
215    pub fn text(&mut self, data: &str) {
216        self.string_raw(data, "text/plain; charset=utf-8");
217    }
218
219    // 所有输出字符串函数都调用这个函数
220    // 这样就不会忘记设置 is_finished 属性了
221    #[inline]
222    fn string_raw(&mut self, data: &str, content_type: &str) {
223        // 注意:必须设置,表示已经设置了返回内容,处理完毕
224        self.is_finished = true;
225        self.set_header(header::CONTENT_TYPE.as_str(), content_type);
226        *self.response.body_mut() = Body::from(data.to_string());
227    }
228
229    /// 返回json格式数据
230    /// 调用格式
231    ///```
232    /// c.json(json!({"name":"admin","age":18}));
233    /// ```
234    /// 如果实现了 `Serialize` Trait 的话可以用下面的方式调用
235    ///
236    /// ```
237    /// let p = Person{name:"admin", age:18};
238    /// c.json(&p);
239    /// ```
240    ///
241    pub fn json<T>(&mut self, json: T)
242    where
243        T: Serialize,
244    {
245        let data = serde_json::to_string(&json).unwrap();
246        self.string_raw(data.as_str(), "application/json; charset=utf-8");
247    }
248}
249
250/// 路由
251#[derive(Default, Debug)]
252pub struct Router {
253    // 请求处理之前的过滤器
254    before_fileters: Vec<Route>,
255
256    // 处理请求的函数
257    routes: Vec<Route>,
258
259    // 处理之后的过滤器
260    after_fileters: Vec<Route>,
261
262    // 是否忽略路径后面的斜线,默认忽略
263    has_slash: bool,
264}
265
266impl Router {
267    async fn shutdown_signal() {
268        tokio::signal::ctrl_c()
269            .await
270            .expect("安装 CTRL+C 处理器失败");
271    }
272
273    /// 静态资源目录
274    pub fn static_dir(path: &str, dir: &str) {}
275
276    /// 静态文件
277    pub fn static_file(uri: &str, filepath: &str) {}
278
279    async fn handle(
280        router: Arc<Router>,
281        addr: SocketAddr,
282        req: Request<Body>,
283    ) -> Result<Response<Body>, Infallible> {
284        let routes = router.match_route(req.method().as_str().into(), req.uri().path());
285
286        // 没找到,返回 404
287        if routes.is_none() {
288            let response = Response::builder()
289                .status(StatusCode::NOT_FOUND)
290                .header(header::CONTENT_TYPE, "text/html; charset=utf-8")
291                .body(Body::from("没匹配到路由"))
292                .unwrap();
293            return Ok(response);
294        }
295
296        trace!("匹配到的路由:{:?}", routes);
297
298        // 如果匹配成功,从路由中提取参数的值,保存到context中
299        let r = routes.unwrap();
300
301        // 每次请求到来就生成一个context,
302        // 他包含着请求信息,传递给每个处理函数处理之后
303        // 把结果保存在Context中,最后返回给客户端
304        let mut context = Context::default();
305
306        // 保存客户端ip和端口
307        context.ip = format!("{}:{}", addr.ip(), addr.port());
308
309        // 地址中匹配到的命名参数数据
310        let mut tm = HashMap::new();
311        for (k, v) in r.params.as_ref().unwrap() {
312            tm.insert(k.to_string(), v.to_string());
313        }
314        context.params = tm;
315
316        // query参数,分割解码保存到context的queries里面
317        let qs = req.uri().query();
318
319        if let Some(qs) = qs {
320            let queries = form_urlencoded::parse(qs.as_ref())
321                .into_owned()
322                .collect::<HashMap<String, String>>();
323
324            context.queries = queries;
325        }
326
327        // 保存请求头信息
328        for (k, v) in req.headers() {
329            context.headers.insert(
330                k.to_string().to_lowercase(),
331                v.to_str().unwrap_or_default().to_string(),
332            );
333        }
334
335        // 优先处理 form-data 类型数据
336
337        // 处理body中的内容
338        if let Ok(body) = hyper::body::to_bytes(req).await {
339            let form = form_urlencoded::parse(body.as_ref())
340                .into_owned()
341                .collect::<HashMap<String, String>>();
342
343            context.forms = form;
344        }
345
346        // 根据请求类型,把数据放到对应的地方
347        let context = RefCell::new(context);
348
349        // 前置过滤器
350        for r in r.before {
351            // 获取Context的可变引用,用于修改Context中的内容
352            let mut context1 = context.borrow_mut();
353
354            // 如果跳过前置过滤器,就不执行后面的过滤器了
355            if context1.is_skip_before_filters || context1.is_finished() {
356                break;
357            }
358
359            // 调用过滤器函数
360            (r.handler)(&mut context1);
361        }
362
363        // 控制器函数
364        if let Some(r) = r.route {
365            // trace!("匹配成功:{}", req.uri().path());
366            trace!("路由规则:{:?}", r);
367
368            let mut context1 = context.borrow_mut();
369
370            // 前置处理器没有直接返回,才调用这个处理器
371            if !context1.is_finished() {
372                (r.handler)(&mut context1);
373            }
374        }
375
376        // 后置过滤器
377        for r in r.after {
378            let mut context1 = context.borrow_mut();
379
380            // 如果跳过后置过滤器,就不执行后面的过滤器了
381            if context1.is_finished() || context1.is_skip_after_filters {
382                break;
383            }
384
385            // 调用过滤器函数
386            (r.handler)(&mut context1);
387        }
388
389        // let context1 = context.borrow_mut();
390
391        if context.borrow_mut().is_finished() {
392            Ok(Response::from(context.take().response))
393        } else {
394            let response = Response::builder()
395                .status(StatusCode::NOT_FOUND)
396                .header(header::CONTENT_TYPE, "text/html; charset=utf-8")
397                .body(Body::from("没匹配到处理函数"))
398                .unwrap();
399            Ok(response)
400        }
401    }
402
403    /// 启动服务器
404    /// ```rust
405    /// use fast_router::router::Router;
406    ///
407    /// fn main(){
408    ///     let mut r = Router::new();
409    ///     r.get("",|c|c.string("hello world"));
410    ///     r.run("127.0.0.1:80");
411    /// }
412    /// ```
413    pub fn run(self, host: &str) {
414        let rt = tokio::runtime::Runtime::new().unwrap();
415        rt.block_on(async {
416            let addr = match SocketAddr::from_str(host) {
417                Ok(v) => v,
418                Err(_) => {
419                    error!("解析地址失败,请确认格式为(ip:port),你的地址是:{}", host);
420                    return;
421                }
422            };
423
424            // 路由表信息
425            let router: Arc<Router> = Arc::new(self);
426
427            debug!("路由表:{:#?}", router.clone());
428
429            // 创建service处理每个请求
430            let make_service = make_service_fn(move |conn: &AddrStream| {
431                // 客户端地址信息
432                let addr = conn.remote_addr();
433
434                // 每个请求都克隆一个路由信息,传入给处理函数
435                let router = router.clone();
436                let service = service_fn(move |req| Self::handle(router.clone(), addr, req));
437                async move { Ok::<_, Infallible>(service) }
438            });
439            let server = Server::bind(&addr).serve(make_service);
440
441            let graceful = server.with_graceful_shutdown(Self::shutdown_signal());
442
443            info!("启动成功: {}", host);
444
445            if let Err(e) = graceful.await {
446                eprintln!("server error: {}", e);
447            }
448        });
449    }
450
451    /// 启动tls服务器
452    pub fn run_tls(host: &str, pem: &str, key: &str) {}
453}
454
455impl Router {
456    /// 创建一个默认的Router
457    pub fn new() -> Self {
458        Self::default()
459    }
460
461    /// 路由分组
462    pub fn group(&mut self, path: &str) -> RouterGroup {
463        RouterGroup::new(path, self)
464    }
465
466    /// 区分路径最后的斜线,默认不区分
467    pub fn has_slash(&mut self) {
468        self.has_slash = true;
469    }
470
471    /// 根据用户请求地址,匹配路由
472    /// 并从请求地址中提取命名路由对应的数据
473    fn match_route(&self, method: Method, path: &str) -> Option<MatchedRoute> {
474        // 如果忽略地址最后的斜线,并且长度不是0,就去掉后面的斜线
475        let path = if !self.has_slash && path.len() > 0 && &path[path.len() - 1..] == "/" {
476            &path[..path.len() - 1]
477        } else {
478            path
479        };
480
481        // 保存从请求路径中提交的键值对
482        // 比如:
483        //      路由:      /user/:name
484        //      请求地址:  /user/admin
485        // 则保存的是 name=>admin 这样的键值对
486        let mut params: HashMap<String, String> = HashMap::new();
487
488        trace!("查找路由:{}", path);
489        // 寻找匹配的路由
490        let mut matched_route = None;
491        for route in &self.routes {
492            if (method == route.method || route.method == Method::ANY) && route.re.is_match(path) {
493                // 找到匹配的路由
494                matched_route = Some(route);
495
496                // 提取参数
497                let cps = route.re.captures(path).unwrap();
498                trace!("参数列表:{:?}", route.param_names);
499                for name in &route.param_names {
500                    // urldecode解码
501                    match decode(cps.name(name.as_str()).unwrap().as_str()) {
502                        Ok(value) => {
503                            params.insert(name.to_string(), value.to_string());
504                        }
505                        Err(e) => {
506                            warn!("路由参数值urldecode解码出错:{:?}", e)
507                        }
508                    }
509                }
510
511                break;
512            }
513        }
514
515        // 寻找前置过滤器
516        let mut before_filters = vec![];
517        for route in &self.before_fileters {
518            if (method == route.method || route.method == Method::ANY) && route.re.is_match(path) {
519                // 找到匹配的过滤器,可能会有多个
520                before_filters.push(route);
521
522                // 提取参数
523                let cps = route.re.captures(path).unwrap();
524                trace!("参数列表:{:?}", route.param_names);
525                for name in &route.param_names {
526                    match decode(cps.name(name.as_str()).unwrap().as_str()) {
527                        Ok(value) => {
528                            params.insert(name.to_string(), value.to_string());
529                        }
530                        Err(e) => {
531                            warn!("路由参数值urldecode解码出错:{:?}", e)
532                        }
533                    }
534                }
535            }
536        }
537
538        // 输出所有参数值
539        trace!("路径中的参数值:{:?}", params);
540
541        // 寻找后置过滤器
542        let mut after_filters = vec![];
543        for route in &self.after_fileters {
544            if (method == route.method || route.method == Method::ANY) && route.re.is_match(path) {
545                // 找到匹配的过滤器,可能会有多个
546                after_filters.push(route);
547            }
548        }
549
550        // 如果都没找到
551        if matched_route.is_none() && before_filters.len() == 0 && after_filters.len() == 0 {
552            return None;
553        }
554
555        Some(MatchedRoute {
556            before: before_filters,
557            route: matched_route,
558            after: after_filters,
559            params: Some(params),
560        })
561    }
562}
563
564impl Router {
565    fn add<F>(&mut self, method: Method, path: &str, handler: F)
566    where
567        F: Fn(&mut Ctx) + 'static + Send + Sync,
568    {
569        // assert!(path.len() > 0);
570
571        let route = Route::new(
572            method,
573            path.to_owned(),
574            Box::new(handler),
575            None,
576            self.has_slash,
577        );
578
579        self.routes.push(route);
580    }
581
582    /// 添加前置中间件
583    pub fn before<F>(&mut self, method: Method, path: &str, handler: F)
584    where
585        F: Fn(&mut Ctx) + 'static + Send + Sync,
586    {
587        let route = Route::new_filter(
588            method,
589            path.to_owned(),
590            Box::new(handler),
591            None,
592            self.has_slash,
593        );
594
595        self.before_fileters.push(route);
596    }
597
598    /// 添加后置中间件
599    pub fn after<F>(&mut self, method: Method, path: &str, handler: F)
600    where
601        F: Fn(&mut Ctx) + 'static + Send + Sync,
602    {
603        let route = Route::new_filter(
604            method,
605            path.to_owned(),
606            Box::new(handler),
607            None,
608            self.has_slash,
609        );
610
611        self.after_fileters.push(route);
612    }
613
614    /// 封装各类请求
615    pub fn get<F>(&mut self, path: &str, handler: F)
616    where
617        F: Fn(&mut Ctx) + 'static + Send + Sync,
618    {
619        self.add(Method::GET, path, handler);
620    }
621
622    pub fn post<F>(&mut self, path: &str, handler: F)
623    where
624        F: Fn(&mut Ctx) + 'static + Send + Sync,
625    {
626        self.add(Method::POST, path, handler);
627    }
628
629    pub fn trace<F>(&mut self, path: &str, handler: F)
630    where
631        F: Fn(&mut Ctx) + 'static + Send + Sync,
632    {
633        self.add(Method::TRACE, path, handler);
634    }
635
636    pub fn head<F>(&mut self, path: &str, handler: F)
637    where
638        F: Fn(&mut Ctx) + 'static + Send + Sync,
639    {
640        self.add(Method::HEAD, path, handler);
641    }
642
643    pub fn put<F>(&mut self, path: &str, handler: F)
644    where
645        F: Fn(&mut Ctx) + 'static + Send + Sync,
646    {
647        self.add(Method::PUT, path, handler);
648    }
649
650    pub fn patch<F>(&mut self, path: &str, handler: F)
651    where
652        F: Fn(&mut Ctx) + 'static + Send + Sync,
653    {
654        self.add(Method::PATCH, path, handler);
655    }
656
657    pub fn delete<F>(&mut self, path: &str, handler: F)
658    where
659        F: Fn(&mut Ctx) + 'static + Send + Sync,
660    {
661        self.add(Method::DELETE, path, handler);
662    }
663
664    pub fn options<F>(&mut self, path: &str, handler: F)
665    where
666        F: Fn(&mut Ctx) + 'static + Send + Sync,
667    {
668        self.add(Method::OPTIONS, path, handler);
669    }
670
671    pub fn any<F>(&mut self, path: &str, handler: F)
672    where
673        F: Fn(&mut Ctx) + 'static + Send + Sync,
674    {
675        self.add(Method::ANY, path, handler);
676    }
677}
678
679/// 根据地址匹配到的路由
680#[derive(Debug)]
681struct MatchedRoute<'a> {
682    before: Vec<&'a Route>,
683    route: Option<&'a Route>,
684    after: Vec<&'a Route>,
685    // 地址参数
686    params: Option<HashMap<String, String>>,
687}
688
689/// 路由组,拥有和`Router`类似的方法
690pub struct RouterGroup<'a> {
691    path: String,
692    router: &'a mut Router,
693}
694
695impl<'a> RouterGroup<'a> {
696    fn new(path: &str, router: &'a mut Router) -> Self {
697        Self {
698            path: path.to_string(),
699            router: router,
700        }
701    }
702
703    /// 处理两个地址相加,防止地址相加出现两个斜线或没有斜线
704    fn concat_path(path1: &str, path2: &str) -> String {
705        // 两个路径除去斜杠之后的长度
706        let l1 = path1.replace("/", "").len();
707        let l2 = path2.replace("/", "").len();
708
709        if l1 == 0 && l2 > 0 {
710            // 如果前面的地址为空,返回第二个地址
711            return path2.to_string();
712        } else if l2 == 0 && l1 > 0 {
713            // 如果后面的地址为空,返回第一个
714            return path1.to_string();
715        } else if l1 == 0 && l2 == 0 {
716            return "".to_string();
717        }
718
719        match (&path1[path1.len() - 1..], &path2[0..1]) {
720            // 两个斜线就去掉一个
721            ("/", "/") => path1.to_string() + &path2[1..],
722
723            // 没有斜线就添加一个
724            (p1, p2) if p1 != "/" && p2 != "/" => path1.to_string() + "/" + path2,
725
726            // 一个斜线就直接连起来
727            _ => path1.to_string() + path2,
728        }
729    }
730
731    fn add<F>(&mut self, method: Method, path: &str, handler: F)
732    where
733        F: Fn(&mut Ctx) + 'static + Send + Sync,
734    {
735        let path = Self::concat_path(self.path.as_str(), path);
736
737        self.router.add(method, path.as_str(), Box::new(handler));
738    }
739
740    /// 生成一个分组
741    pub fn group(&mut self, path: &str) -> RouterGroup {
742        let path = Self::concat_path(self.path.as_str(), path);
743        RouterGroup::new(path.as_str(), self.router)
744    }
745
746    /// 添加前置处理器
747    pub fn before<F>(&mut self, method: Method, path: &str, handler: F)
748    where
749        F: Fn(&mut Ctx) + 'static + Send + Sync,
750    {
751        let path = Self::concat_path(self.path.as_str(), path);
752
753        self.router.before(method, path.as_str(), handler);
754    }
755
756    /// 添加后置处理器
757    pub fn after<F>(&mut self, method: Method, path: &str, handler: F)
758    where
759        F: Fn(&mut Ctx) + 'static + Send + Sync,
760    {
761        let path = Self::concat_path(self.path.as_str(), path);
762
763        self.router.after(method, path.as_str(), handler);
764    }
765
766    /// 封装各类请求
767    pub fn get<F>(&mut self, path: &str, handler: F)
768    where
769        F: Fn(&mut Ctx) + 'static + Send + Sync,
770    {
771        self.add(Method::GET, path, handler);
772    }
773
774    pub fn post<F>(&mut self, path: &str, handler: F)
775    where
776        F: Fn(&mut Ctx) + 'static + Send + Sync,
777    {
778        self.add(Method::POST, path, handler);
779    }
780
781    pub fn trace<F>(&mut self, path: &str, handler: F)
782    where
783        F: Fn(&mut Ctx) + 'static + Send + Sync,
784    {
785        self.add(Method::TRACE, path, handler);
786    }
787
788    pub fn head<F>(&mut self, path: &str, handler: F)
789    where
790        F: Fn(&mut Ctx) + 'static + Send + Sync,
791    {
792        self.add(Method::HEAD, path, handler);
793    }
794
795    pub fn put<F>(&mut self, path: &str, handler: F)
796    where
797        F: Fn(&mut Ctx) + 'static + Send + Sync,
798    {
799        self.add(Method::PUT, path, handler);
800    }
801
802    pub fn patch<F>(&mut self, path: &str, handler: F)
803    where
804        F: Fn(&mut Ctx) + 'static + Send + Sync,
805    {
806        self.add(Method::PATCH, path, handler);
807    }
808
809    pub fn delete<F>(&mut self, path: &str, handler: F)
810    where
811        F: Fn(&mut Ctx) + 'static + Send + Sync,
812    {
813        self.add(Method::DELETE, path, handler);
814    }
815
816    pub fn options<F>(&mut self, path: &str, handler: F)
817    where
818        F: Fn(&mut Ctx) + 'static + Send + Sync,
819    {
820        self.add(Method::OPTIONS, path, handler);
821    }
822
823    pub fn any<F>(&mut self, path: &str, handler: F)
824    where
825        F: Fn(&mut Ctx) + 'static + Send + Sync,
826    {
827        self.add(Method::ANY, path, handler);
828    }
829}
830
831/// 路径的一个路由信息
832struct Route {
833    // 请求方式,不区分大小写
834    method: Method,
835
836    // 路由名字,用于生成url
837    name: Option<String>,
838
839    // 路由规则
840    path: String,
841
842    // 路径编译之后的正则表达式对象
843    re: Regex,
844
845    // 处理函数
846    handler: Box<Handler>,
847
848    // 是否保留路径最后的斜线
849    has_slash: bool,
850
851    // 路径中的分组命名
852    param_names: Vec<String>,
853}
854
855impl Debug for Route {
856    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
857        f.debug_struct("Route")
858            .field("method", &self.method)
859            .field("name", &self.name)
860            .field("path", &self.path)
861            .field("re", &self.re)
862            .field("has_slash", &self.has_slash)
863            .field("param_names", &self.param_names)
864            .finish()
865    }
866}
867
868impl Route {
869    /// 创建路由
870    fn new(
871        method: Method,
872        path: String,
873        handler: Box<Handler>,
874        name: Option<String>,
875        has_slash: bool,
876    ) -> Self {
877        Self::build(method, path, handler, name, has_slash, false)
878    }
879
880    /// 创建过滤器
881    fn new_filter(
882        method: Method,
883        path: String,
884        handler: Box<Handler>,
885        name: Option<String>,
886        has_slash: bool,
887    ) -> Self {
888        Self::build(method, path, handler, name, has_slash, true)
889    }
890    fn build(
891        method: Method,
892        path: String,
893        handler: Box<Handler>,
894        name: Option<String>,
895        has_slash: bool,
896
897        // 是否是过滤器,如果是过滤器,正则结尾不需要$,这样只要匹配一部分路径即可
898        is_filter: bool,
899    ) -> Self {
900        // 如果忽不保留路径最后的斜线,就去掉,否则就不变
901        let path = if !has_slash && !path.is_empty() && &path[path.len() - 1..] == "/" {
902            path[..path.len() - 1].to_string()
903        } else {
904            path
905        };
906
907        // 把自定义类型的路由转换成 正则路由
908        let path = Self::path_param_type_to_regex(path.as_str());
909
910        // 把正则路由转换成 在组名的正则路由
911        let path_and_names = Self::path2regex(path.as_str());
912
913        trace!("路由参数列表:{:?}", path_and_names.1);
914
915        let mut re_str = format!("^{}", path_and_names.0);
916
917        // 如果不是过滤器,需要匹配整个地址
918        if !is_filter {
919            re_str += "$";
920        }
921
922        let re = Regex::new(re_str.as_str()).unwrap();
923        Self {
924            method,
925            path: path.clone(),
926            name,
927            re,
928            handler,
929            has_slash,
930            param_names: path_and_names.1,
931        }
932    }
933
934    /// 返回对应类型的正则
935    #[inline]
936    fn type_to_regex(type_name: &str) -> String {
937        // i8|u8|i32|u32|i64|u64|i128|u128|bool
938        match type_name {
939            "i8" => r"[\-]{0,1}\d{1,3}",
940            "i16" => r"[\-]{0,1}\d{1,5}",
941            "i32" => r"[\-]{0,1}\d{1,10}",
942            "i64" => r"[\-]{0,1}\d{1,19}",
943            "i128" => r"[\-]{0,1}\d{1,39}",
944            "u8" => r"\d{1,3}",
945            "u16" => r"\d{1,5}",
946            "u32" => r"\d{1,10}",
947            "u64" => r"\d{1,20}",
948            "u128" => r"\d{1,39}",
949            "bool" => r"true|false",
950            v => {
951                panic!("路由不支持该参数类型:{}", v);
952            }
953        }
954        .to_string()
955    }
956
957    /// 把路由规则转换成正则表达式格式
958    ///
959    /// 例如:  /user/:id:usize/:page:usize
960    /// 转换成:/user/:id:(\d+)/:page:(\d+)
961    ///
962    /// 返回值说明:
963    /// 返回的第一个值是转换后的正则路由,第二个参数是正则路由中的命名参数名字
964    /// 比如:/:user/:id  第二个参数就返回["user","id"]
965    ///
966    #[inline]
967    fn path_param_type_to_regex(path: &str) -> String {
968        let mut p = String::new();
969
970        let re = Regex::new(r#"^:(?P<name>[a-zA-a_]{1}[a-zA-Z_0-9]*?):(?P<type>i32|u32|i8|u8|i64|u64|i128|u128|bool)$"#).unwrap();
971
972        for node in path.split("/") {
973            if node.is_empty() {
974                continue;
975            }
976
977            if re.is_match(node) {
978                let cms = re.captures(node).unwrap();
979                let name = cms.name("name").unwrap().as_str();
980                let tp = cms.name("type").unwrap().as_str();
981
982                let type_reg = Self::type_to_regex(tp);
983                p += format!("/:{}:({})", name, type_reg).as_str();
984            } else if &node[0..1] == ":" && &node[node.len() - 1..] != ")" {
985                // 如果不匹配,以 : 开头,表示没写类型,默认匹配任意字符串
986                // 也就是这种情况 /:name/
987                p = p + "/" + node + r#":([\w\-%_\.~:;'"@=+,]+)"#;
988            } else {
989                // 自定义正则就不改变
990                p = p + "/" + node;
991            }
992        }
993        // 最后如果有 / 也要加上
994        if path.len() > 0 && &path[path.len() - 1..] == "/" {
995            p += "/";
996        }
997
998        p
999    }
1000
1001    /// 把正则路由转换成,命名组正则表达式,如果是自定义类型的,需要先调用 path_param_type_to_regex 函数来处理成正则路由
1002    ///
1003    /// 例如把 /admin/:name:([^/]+)/:id:(\d+)
1004    /// 转换成 /admin/(?P<name>[^/]+)/(?P<id>\d+)
1005    ///
1006    #[inline]
1007    fn path2regex(path: &str) -> (String, Vec<String>) {
1008        let mut p = String::new();
1009
1010        let re = Regex::new(r#"^:(?P<name>[a-zA-a_]{1}[a-zA-Z_0-9]*?):\((?P<reg>.*)\)$"#).unwrap();
1011
1012        let mut names = vec![];
1013
1014        for node in path.split("/") {
1015            if node.is_empty() {
1016                continue;
1017            }
1018
1019            if re.is_match(node) {
1020                let cms = re.captures(node).unwrap();
1021                let name = cms.name("name").unwrap().as_str();
1022                names.push(name.to_string());
1023
1024                p += re
1025                    .replace(node, "/(?P<${name}>${reg})")
1026                    .to_string()
1027                    .as_str();
1028            } else {
1029                p += "/";
1030                p += node;
1031            }
1032        }
1033        // 最后如果有 / 也要加上
1034        if path.len() > 0 && &path[path.len() - 1..] == "/" {
1035            p += "/";
1036        }
1037
1038        (p, names)
1039    }
1040}
1041
1042#[cfg(test)]
1043mod tests {
1044
1045    use std::cell::RefCell;
1046    use std::cell::RefMut;
1047    use std::str::FromStr;
1048
1049    use regex::Regex;
1050
1051    use crate::router::Route;
1052
1053    use super::Method;
1054    use super::Router;
1055    use super::RouterGroup;
1056
1057    #[test]
1058    fn test_concat() {
1059        assert_eq!("a/b".to_string(), RouterGroup::concat_path("a/", "/b"));
1060        assert_eq!("a/b".to_string(), RouterGroup::concat_path("a", "/b"));
1061        assert_eq!("a/b".to_string(), RouterGroup::concat_path("a/", "b"));
1062        assert_eq!("a/b".to_string(), RouterGroup::concat_path("a", "b"));
1063        assert_eq!("a".to_string(), RouterGroup::concat_path("a", ""));
1064        assert_eq!("".to_string(), RouterGroup::concat_path("", ""));
1065        assert_eq!("b".to_string(), RouterGroup::concat_path("", "b"));
1066    }
1067
1068    #[test]
1069    fn test_router() {
1070        // let mut r = Router::default();
1071        // r.has_slash();
1072
1073        // r.post("/:user/:id", |c| {});
1074
1075        // let mut g = r.group("/:v1");
1076        // {
1077        //     g.get("admin/:name:i32", |mut c| {});
1078        //     g.post("/admin/u32/", |c| {});
1079
1080        //     let mut g1 = g.group("/test1");
1081        //     {
1082        //         g1.put("admin/login/", |c| {});
1083        //         g1.delete("/admin/login1/", |c| {});
1084        //     }
1085        // }
1086
1087        // let mut g = r.group("/a1/");
1088        // {
1089        //     g.add(Method::GET, "/admin/login", |c| {});
1090        //     g.add(Method::DELETE, "/admin/login1", |c| {});
1091
1092        //     let mut g1 = g.group("/test1/");
1093        //     {
1094        //         g1.add(Method::OPTIONS, "/admin/login", |c| {});
1095        //         g1.add(Method::ANY, "/admin/login1", |c| {});
1096        //     }
1097        // }
1098
1099        // for v in r.routes {
1100        //     println!("{:?}", v);
1101        // }
1102    }
1103
1104    #[test]
1105    fn test_router1() {
1106        let mut r = Router::default();
1107
1108        let mut g = r.group("/a1/");
1109        {
1110            let s = "aa".to_string();
1111            g.add(Method::GET, "/admin/login", move |c| {
1112                let t = &s;
1113            });
1114            g.add(Method::DELETE, "/admin/login1", |c| {});
1115
1116            let mut g1 = g.group("/test1/");
1117            {
1118                g1.add(Method::OPTIONS, "/admin/login", |c| {});
1119                g1.add(Method::ANY, "/admin/login1", |c| {});
1120            }
1121        }
1122
1123        for v in r.routes {
1124            println!("{:?}", v);
1125        }
1126    }
1127    #[test]
1128    fn test_regex() {
1129        let re = Regex::new(r"^/user/(?P<name>\w+)/(?P<id>\d{1,10})$").unwrap();
1130
1131        let v = re.captures("/user/zhangsan/123").unwrap();
1132        let r = v.name("name").unwrap();
1133        println!("{:?}", r.as_str());
1134        let r = v.name("id").unwrap();
1135        println!("{:?}", r.as_str());
1136    }
1137
1138    #[test]
1139    fn test_path2regex() {
1140        /*
1141        把     /admin/:name:([^/]+)/:id:(\d+)
1142            转换成 /admin/(?P<name>[^/]+)/(?P<id>\d+)
1143        */
1144
1145        let s = r#"/admin/:name:(.*+?)/info/:id:(\d+?)/name/"#;
1146        let p = Route::path2regex(s);
1147
1148        assert_eq!(
1149            r"/admin/(?P<name>.*+?)/info/(?P<id>\d+?)/name/",
1150            p.0.as_str()
1151        );
1152    }
1153
1154    #[test]
1155    fn test_path_param_to_regex() {
1156        let path = "/user/:id:(.*)/:page:u32";
1157        let p = Route::path_param_type_to_regex(path);
1158        assert_eq!(r"/user/:id:(.*)/:page:(\d{1,10})", p.as_str());
1159    }
1160
1161    #[test]
1162    fn test_router_match() {
1163        // let mut r = Router::default();
1164
1165        // let mut g = r.group("/v1");
1166        // {
1167        //     g.before(Method::ANY, "admin/:name", |c| {});
1168        //     g.after(Method::ANY, "admin/:name", |c| {});
1169
1170        //     g.any("admin/:name:i32", |c| {});
1171        //     g.any("admin/:name", |c| {});
1172        //     g.any("admin/:name/:id:u32", |c| {});
1173        //     g.post("/admin/login1/", |c| {});
1174        // }
1175
1176        // let route = r.match_route(Method::GET, "/v1/admin/zhang山/23423");
1177
1178        // // (route.as_ref().unwrap().route.unwrap().handler)("xxx".to_string());
1179    }
1180
1181    #[test]
1182    fn test_filters() {}
1183
1184    #[test]
1185    fn test_fnonce() {
1186        struct Context {
1187            data: String,
1188        }
1189
1190        type Ctx<'a> = RefMut<'a, Context>;
1191        type Hander = dyn Fn(Ctx) + 'static;
1192
1193        struct Route {
1194            handler: Box<Hander>,
1195        }
1196
1197        fn get<F>(f: F)
1198        where
1199            F: Fn(Ctx) + 'static,
1200        {
1201            let r = &Route {
1202                handler: Box::new(f),
1203            };
1204
1205            let c = RefCell::new(Context {
1206                data: "".to_string(),
1207            });
1208            let v = c.borrow_mut();
1209            (r.handler)(v);
1210            let v = c.borrow_mut();
1211            (r.handler)(v);
1212        }
1213
1214        let s = String::new();
1215        // let ctx = Context{data:"sss".to_string()};
1216        get(move |mut c| {
1217            let v = &s;
1218            c.data = "xxx".to_string();
1219        });
1220    }
1221}