#router #path #url #match #tree

pavex_matchit

matchit 的分支,以获取 Pavex 的一些未发布修复

2 个不稳定版本

0.7.4 2024 年 1 月 22 日
0.1.0 2024 年 1 月 22 日

#357网络编程

Download history 51/week @ 2024-03-14 238/week @ 2024-03-21 303/week @ 2024-03-28 302/week @ 2024-04-04 424/week @ 2024-04-11 610/week @ 2024-04-18 507/week @ 2024-04-25 189/week @ 2024-05-02 173/week @ 2024-05-09 347/week @ 2024-05-16 291/week @ 2024-05-23 205/week @ 2024-05-30 200/week @ 2024-06-06 365/week @ 2024-06-13 213/week @ 2024-06-20 163/week @ 2024-06-27

每月下载量 979
用于 8 个包(2 个直接使用)

MIT AND BSD-3-Clause

52KB
863

matchit

Documentation Version License

一个高性能、零拷贝 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

无运行时依赖项