Skip to content

Commit 39f56dd

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents f7014fa + 4b866b4 commit 39f56dd

File tree

3 files changed

+35
-19
lines changed

3 files changed

+35
-19
lines changed
Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
22

3+
use crate::core::res_body::ResBody;
34
use crate::{Request, Response, Result, SilentError};
45
use async_trait::async_trait;
56
use http::{Method, StatusCode};
@@ -17,17 +18,29 @@ pub trait Handler: Send + Sync + 'static {
1718
#[async_trait]
1819
impl Handler for HashMap<Method, Arc<dyn Handler>> {
1920
async fn call(&self, req: Request) -> Result<Response> {
20-
match self.clone().get(req.method()) {
21-
None => Err(SilentError::business_error(
22-
StatusCode::METHOD_NOT_ALLOWED,
23-
"method not allowed".to_string(),
24-
)),
25-
Some(handler) => {
26-
let mut pre_res = Response::empty();
27-
pre_res.configs = req.configs();
28-
pre_res.copy_from_response(handler.call(req).await?);
29-
Ok(pre_res)
30-
}
21+
let method = req.method().clone();
22+
// 直接命中匹配的方法
23+
if let Some(handler) = self.clone().get(&method) {
24+
let mut pre_res = Response::empty();
25+
pre_res.configs = req.configs();
26+
pre_res.copy_from_response(handler.call(req).await?);
27+
return Ok(pre_res);
3128
}
29+
30+
// 特殊处理:HEAD 无显式处理器时回退到 GET,并清空响应体
31+
if method == http::Method::HEAD
32+
&& let Some(get_handler) = self.clone().get(&http::Method::GET)
33+
{
34+
let mut pre_res = Response::empty();
35+
pre_res.configs = req.configs();
36+
pre_res.copy_from_response(get_handler.call(req).await?);
37+
pre_res.set_body(ResBody::None);
38+
return Ok(pre_res);
39+
}
40+
41+
Err(SilentError::business_error(
42+
StatusCode::METHOD_NOT_ALLOWED,
43+
"method not allowed".to_string(),
44+
))
3245
}
3346
}

silent/src/route/route_tree.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ impl RouteTree {
112112
(true, last_path)
113113
}
114114
SpecialPath::FullPath(key) => {
115-
// ** 通配符:总是匹配,参数记录完整剩余路径
115+
// ** 通配符:记录完整剩余路径,且允许继续尝试子结点匹配。
116+
// 若后续子结点无法匹配,dfs_match 中会在有处理器时回退到当前结点。
116117
let p = path.strip_prefix('/').unwrap_or(path);
117118
req.set_path_params(key, PathParam::Path(p.to_string()));
118119
(true, last_path)
@@ -137,17 +138,19 @@ impl RouteTree {
137138
stack.push(self);
138139

139140
if last_path.is_empty() {
140-
// URL 已完全匹配:仅尝试 path 为空字符串的子结点
141+
// URL 已完全匹配:仍尝试所有子结点,让特殊路径(如 <path:**>)有机会匹配空余路径
141142
for child in &self.children {
142-
if !child.path.is_empty() {
143-
continue;
144-
}
145143
if child.dfs_match(req, last_path, stack) {
146144
return true;
147145
}
148146
}
149-
// 无子结点匹配,则当前为终点
150-
return true;
147+
// 无子结点匹配:仅当当前结点存在处理器时才认为匹配成功
148+
if self.has_handler {
149+
return true;
150+
} else {
151+
stack.pop();
152+
return false;
153+
}
151154
}
152155

153156
// 继续匹配子路由

xtask/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ publish = false
66

77
[dependencies]
88
clap = { version = "4", features = ["derive"] }
9-
which = "6"
9+
which = "8"
1010
serde_json = "1"
1111
chrono = { version = "0.4" }
1212

0 commit comments

Comments
 (0)