"matchit" based router (#363)

* "matchit" based router

* Update changelog

* Remove dependency on `regex`

* Docs

* Fix typos

* Also mention route order in root module docs

* Update CHANGELOG.md

Co-authored-by: Jonas Platte <[email protected]>

* Document that `/:key` and `/foo` overlaps

* Provide good error message for wildcards in routes

* minor clean ups

* Make `Router` cheaper to clone

* Ensure middleware still only applies to routes above

* Remove call to issues from changelog

We're aware of the short coming :)

* Fix tests on 1.51

Co-authored-by: Jonas Platte <[email protected]>
This commit is contained in:
David Pedersen
2021-10-24 15:22:49 +02:00
committed by GitHub
co-authored by Jonas Platte
parent 9fcc884374
commit 1a78a3f224
11 changed files with 553 additions and 413 deletions
+78
View File
@@ -1,5 +1,6 @@
use super::*;
use crate::body::box_body;
use crate::routing::EmptyRouter;
use std::collections::HashMap;
#[tokio::test]
@@ -13,6 +14,7 @@ async fn nesting_apps() {
"/users/:id",
get(
|params: extract::Path<HashMap<String, String>>| async move {
dbg!(&params);
format!(
"{}: users#show ({})",
params.get("version").unwrap(),
@@ -179,3 +181,79 @@ async fn nest_static_file_server() {
let res = client.get("/static/README.md").send().await;
assert_eq!(res.status(), StatusCode::OK);
}
#[tokio::test]
async fn nested_multiple_routes() {
let app = Router::new()
.nest(
"/api",
Router::new()
.route("/users", get(|| async { "users" }))
.route("/teams", get(|| async { "teams" })),
)
.route("/", get(|| async { "root" }));
let client = TestClient::new(app);
assert_eq!(client.get("/").send().await.text().await, "root");
assert_eq!(client.get("/api/users").send().await.text().await, "users");
assert_eq!(client.get("/api/teams").send().await.text().await, "teams");
}
#[tokio::test]
async fn nested_with_other_route_also_matching_with_route_first() {
let app = Router::new().route("/api", get(|| async { "api" })).nest(
"/api",
Router::new()
.route("/users", get(|| async { "users" }))
.route("/teams", get(|| async { "teams" })),
);
let client = TestClient::new(app);
assert_eq!(client.get("/api").send().await.text().await, "api");
assert_eq!(client.get("/api/users").send().await.text().await, "users");
assert_eq!(client.get("/api/teams").send().await.text().await, "teams");
}
#[tokio::test]
async fn nested_with_other_route_also_matching_with_route_last() {
let app = Router::new()
.nest(
"/api",
Router::new()
.route("/users", get(|| async { "users" }))
.route("/teams", get(|| async { "teams" })),
)
.route("/api", get(|| async { "api" }));
let client = TestClient::new(app);
assert_eq!(client.get("/api").send().await.text().await, "api");
assert_eq!(client.get("/api/users").send().await.text().await, "users");
assert_eq!(client.get("/api/teams").send().await.text().await, "teams");
}
#[tokio::test]
async fn multiple_top_level_nests() {
let app = Router::new()
.nest(
"/one",
Router::new().route("/route", get(|| async { "one" })),
)
.nest(
"/two",
Router::new().route("/route", get(|| async { "two" })),
);
let client = TestClient::new(app);
assert_eq!(client.get("/one/route").send().await.text().await, "one");
assert_eq!(client.get("/two/route").send().await.text().await, "two");
}
#[tokio::test]
#[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")]
async fn nest_cannot_contain_wildcards() {
Router::<EmptyRouter>::new().nest("/one/*rest", Router::<EmptyRouter>::new());
}