#radix #tree #path #router

path-tree

path-tree is a lightweight high performance HTTP request router for Rust

22 releases

0.2.2 Oct 24, 2021
0.1.12 Sep 29, 2020
0.1.11 Jun 21, 2020
0.1.9 Nov 5, 2019
0.1.4 Mar 17, 2019

#38 in HTTP server

Download history 1303/week @ 2021-10-06 989/week @ 2021-10-13 842/week @ 2021-10-20 1178/week @ 2021-10-27 1398/week @ 2021-11-03 1472/week @ 2021-11-10 505/week @ 2021-11-17 1150/week @ 2021-11-24 568/week @ 2021-12-01 1060/week @ 2021-12-08 1434/week @ 2021-12-15 902/week @ 2021-12-22 368/week @ 2021-12-29 894/week @ 2022-01-05 704/week @ 2022-01-12 460/week @ 2022-01-19

2,645 downloads per month
Used in 12 crates (10 directly)

MIT/Apache

19KB
288 lines

path-tree

A lightweight high performance HTTP request router for Rust

Features

  • Fast: See benchmark

  • Micro: The src/lib.rs file is ~396 lines of code (Includes comments)

  • Flexible:

    • Static segment. e.g. /users.

    • Named parameters. e.g. :name.

    • Catch-All parameters. e.g. *any, it must always be at the end of the pattern.

    • Supports multiple naming for the same path segment. e.g. /users/:id and /users/:user_id/repos.

    • Don't care about routes orders, recursive lookup, Static -> Named -> Catch-All.

Examples

use path_tree::PathTree;

let mut tree = PathTree::<usize>::new();

tree.insert("/", 0);
tree.insert("/users", 1);
tree.insert("/users/:id", 2);
tree.insert("/users/:id/:org", 3);
tree.insert("/users/:user_id/repos", 4);
tree.insert("/users/:user_id/repos/:id", 5);
tree.insert("/users/:user_id/repos/:id/*any", 6);
tree.insert("/:username", 7);
tree.insert("/*any", 8);
tree.insert("/about", 9);
tree.insert("/about/", 10);
tree.insert("/about/us", 11);
tree.insert("/users/repos/*any", 12);

// Matched "/"
let node = tree.find("/");
assert_eq!(node.is_some(), true);
let res = node.unwrap();
assert_eq!(*res.0, 0);
assert_eq!(res.1, []); // Params

// Matched "/:username"
let node = tree.find("/username");
assert_eq!(node.is_some(), true);
let res = node.unwrap();
assert_eq!(*res.0, 7);
assert_eq!(res.1, [("username", "username")]); // Params


// Matched "/*any"
let node = tree.find("/user/s");
let res = node.unwrap();
assert_eq!(*res.0, 8);
assert_eq!(res.1, [("any", "user/s")]);

// Matched "/users/:id"
let node = tree.find("/users/fundon");
let res = node.unwrap();
assert_eq!(*res.0, 2);
assert_eq!(res.1, [("id", "fundon")]); // Params

// Matched "/users/:user_id/repos/:id"
let node = tree.find("/users/fundon/repos/viz-rs");
let res = node.unwrap();
assert_eq!(*res.0, 5);
assert_eq!(res.1, [("user_id", "fundon"), ("id", "viz-rs")]); // Params

// Matched "/users/:user_id/repos/:id/*any"
let node = tree.find("/users/fundon/repos/viz-rs/noder/issues");
let res = node.unwrap();
assert_eq!(*res.0, 6);
assert_eq!(
    res.1,
    [
        ("user_id", "fundon"),
        ("id", "viz-rs"),
        ("any", "noder/issues"),
    ]
); // Params


// Matched "/users/repos/*any"
let node = tree.find("/users/repos/");
let res = node.unwrap();
assert_eq!(*res.0, 12);
assert_eq!(res.1, []);

Benchmark

$ cargo bench

Acknowledgements

It is inspired by the:

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

No runtime deps