Skip to main content

nargo_ssr/
router.rs

1use std::{collections::HashMap, sync::Arc};
2
3/// 路由参数类型
4type RouteParams = HashMap<String, String>;
5
6/// 路由匹配结果
7#[derive(Clone)]
8pub struct RouteMatch {
9    /// 匹配的路由路径
10    pub path: String,
11    /// 路由参数
12    pub params: RouteParams,
13    /// 路由查询参数
14    pub query: HashMap<String, String>,
15}
16
17/// 路由处理器 trait
18pub trait RouteHandler: Send + Sync {
19    /// 处理路由请求
20    ///
21    /// # Arguments
22    /// * `params` - 路由参数
23    /// * `query` - 查询参数
24    ///
25    /// # Returns
26    /// * `Result<String, String>` - 渲染结果或错误信息
27    fn handle(&self, params: &RouteParams, query: &HashMap<String, String>) -> Result<String, String>;
28}
29
30/// 路由表
31pub struct Router {
32    /// 路由规则映射
33    routes: HashMap<String, Arc<dyn RouteHandler>>,
34    /// 缓存的路由匹配结果
35    route_cache: HashMap<String, RouteMatch>,
36}
37
38impl Router {
39    /// 创建新的路由表
40    pub fn new() -> Self {
41        Self { routes: HashMap::new(), route_cache: HashMap::new() }
42    }
43
44    /// 添加路由
45    ///
46    /// # Arguments
47    /// * `path` - 路由路径
48    /// * `handler` - 路由处理器
49    pub fn add_route<H: RouteHandler + 'static>(&mut self, path: &str, handler: H) {
50        self.routes.insert(path.to_string(), Arc::new(handler));
51    }
52
53    /// 匹配路由
54    ///
55    /// # Arguments
56    /// * `path` - 请求路径
57    ///
58    /// # Returns
59    /// * `Option<(Arc<dyn RouteHandler>, RouteMatch)>` - 匹配的处理器和路由匹配结果
60    pub fn match_route(&mut self, path: &str) -> Option<(Arc<dyn RouteHandler>, RouteMatch)> {
61        // 检查缓存
62        if let Some(match_result) = self.route_cache.get(path) {
63            // 查找对应的处理器
64            if let Some(handler) = self.routes.get(&match_result.path) {
65                return Some((handler.clone(), match_result.clone()));
66            }
67        }
68
69        // 解析路径和查询参数
70        let (path_part, query_part) = path.split_once('?').unwrap_or((path, ""));
71        let query = self.parse_query(query_part);
72
73        // 匹配路由
74        for (route_path, handler) in &self.routes {
75            if let Some(params) = self.match_path(route_path, path_part) {
76                let match_result = RouteMatch { path: route_path.clone(), params, query };
77                // 缓存匹配结果
78                self.route_cache.insert(path.to_string(), match_result.clone());
79                return Some((handler.clone(), match_result));
80            }
81        }
82
83        None
84    }
85
86    /// 解析查询参数
87    ///
88    /// # Arguments
89    /// * `query_str` - 查询参数字符串
90    ///
91    /// # Returns
92    /// * `HashMap<String, String>` - 解析后的查询参数
93    fn parse_query(&self, query_str: &str) -> HashMap<String, String> {
94        let mut query = HashMap::new();
95        for pair in query_str.split('&') {
96            if let Some((key, value)) = pair.split_once('=') {
97                query.insert(key.to_string(), value.to_string());
98            }
99        }
100        query
101    }
102
103    /// 匹配路径
104    ///
105    /// # Arguments
106    /// * `route_path` - 路由路径模板
107    /// * `request_path` - 请求路径
108    ///
109    /// # Returns
110    /// * `Option<RouteParams>` - 匹配的路由参数
111    fn match_path(&self, route_path: &str, request_path: &str) -> Option<RouteParams> {
112        let route_parts: Vec<&str> = route_path.split('/').filter(|p| !p.is_empty()).collect();
113        let request_parts: Vec<&str> = request_path.split('/').filter(|p| !p.is_empty()).collect();
114
115        if route_parts.len() != request_parts.len() {
116            return None;
117        }
118
119        let mut params = RouteParams::new();
120        for (route_part, request_part) in route_parts.iter().zip(request_parts.iter()) {
121            if route_part.starts_with(':') {
122                // 动态参数
123                let param_name = route_part.trim_start_matches(':');
124                params.insert(param_name.to_string(), request_part.to_string());
125            }
126            else if route_part != request_part {
127                // 路径不匹配
128                return None;
129            }
130        }
131
132        Some(params)
133    }
134
135    /// 清除路由缓存
136    pub fn clear_cache(&mut self) {
137        self.route_cache.clear();
138    }
139}