2 个不稳定版本
0.7.4 | 2024 年 1 月 22 日 |
---|---|
0.1.0 | 2024 年 1 月 22 日 |
#357 在 网络编程
每月下载量 979
用于 8 个包(2 个直接使用)
52KB
863 行
matchit
一个高性能、零拷贝 URL 路由器。
use matchit::Router;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut router = Router::new();
router.insert("/home", "Welcome!")?;
router.insert("/users/:id", "A User")?;
let matched = router.at("/users/978")?;
assert_eq!(matched.params.get("id"), Some("978"));
assert_eq!(*matched.value, "A User");
Ok(())
}
参数
除了静态路由之外,该路由器还支持动态路由段。这些段可以是命名参数或通配符参数
命名参数
像 /:id
这样的命名参数匹配从下一个 /
或路径末尾之前的任何内容
let mut m = Router::new();
m.insert("/users/:id", true)?;
assert_eq!(m.at("/users/1")?.params.get("id"), Some("1"));
assert_eq!(m.at("/users/23")?.params.get("id"), Some("23"));
assert!(m.at("/users").is_err());
通配符参数
通配符参数以 *
开头,匹配直到路径末尾的任何内容。它们必须始终位于路由的 末尾
let mut m = Router::new();
m.insert("/*p", true)?;
assert_eq!(m.at("/foo.js")?.params.get("p"), Some("foo.js"));
assert_eq!(m.at("/c/bar.css")?.params.get("p"), Some("c/bar.css"));
// note that this would not match:
assert_eq!(m.at("/").is_err());
路由优先级
静态和动态路由段可以重叠。如果它们重叠,则静态段将具有更高的优先级
let mut m = Router::new();
m.insert("/", "Welcome!").unwrap(); // priority: 1
m.insert("/about", "About Me").unwrap(); // priority: 1
m.insert("/*filepath", "...").unwrap(); // priority: 2
它是如何工作的?
该路由器利用了 URL 路由通常遵循分层结构的事实。它将路由存储在一个基数 trie 中,该 trie 重用了大量公共前缀
Priority Path Value
9 \ 1
3 ├s None
2 |├earch\ 2
1 |└upport\ 3
2 ├blog\ 4
1 | └:post None
1 | └\ 5
2 ├about-us\ 6
1 | └team\ 7
1 └contact\ 8
这使我们能够将路由搜索减少到少数几个分支。同一级别的树上的子节点也根据注册值数进行优先排序,增加了第一次尝试选择正确分支的机会。
基准测试
事实证明,这种路由方法非常快。在一个基准测试中,将 4 个路径与 130 个已注册路由匹配,matchit
在不到 200 纳秒内找到正确的路由,比大多数其他路由器快一个数量级。您可以在此处查看基准测试代码 here。
Compare Routers/matchit
time: [197.57 ns 198.74 ns 199.83 ns]
Compare Routers/actix
time: [26.805 us 26.811 us 26.816 us]
Compare Routers/path-tree
time: [468.95 ns 470.34 ns 471.65 ns]
Compare Routers/regex
time: [22.539 us 22.584 us 22.639 us]
Compare Routers/route-recognizer
time: [3.7552 us 3.7732 us 3.8027 us]
Compare Routers/routefinder
time: [5.7313 us 5.7405 us 5.7514 us]
致谢
本包中的大量代码基于 Julien Schmidt 的 httprouter
。