Fix Router::merge for overlapping routes same different methods (#543)

Discovered while working on something else that we didn't properly
handle this:

```rust
let one = Router::new().route("/", get(|| async {}));
let two = Router::new().route("/", post(|| async {}));

let app = one.merge(two);
```
This commit is contained in:
David Pedersen 2021-11-19 21:15:41 +01:00 committed by GitHub
parent 1d94d75c57
commit 22931688f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 12 deletions

View file

@ -244,12 +244,15 @@ where
nested_at_root,
} = other;
if let Err(err) = self.node.merge(node) {
self.panic_on_matchit_error(err);
}
for (id, route) in routes {
assert!(self.routes.insert(id, route).is_none());
let path = node
.route_id_to_path
.get(&id)
.expect("no path for route id. This is a bug in axum. Please file an issue");
self = match route {
Endpoint::MethodRouter(route) => self.route(path, route),
Endpoint::Route(route) => self.route(path, route),
};
}
self.fallback = match (self.fallback, fallback) {
@ -603,13 +606,6 @@ impl Node {
Ok(())
}
fn merge(&mut self, other: Node) -> Result<(), matchit::InsertError> {
for (id, path) in other.route_id_to_path {
self.insert(&*path, id)?;
}
Ok(())
}
fn at<'n, 'p>(
&'n self,
path: &'p str,

View file

@ -584,3 +584,19 @@ async fn nesting_router_with_fallbacks_panics() {
let app = Router::new().nest("/", one);
TestClient::new(app);
}
#[tokio::test]
async fn merging_routers_with_same_paths_but_different_methods() {
let one = Router::new().route("/", get(|| async { "GET" }));
let two = Router::new().route("/", post(|| async { "POST" }));
let client = TestClient::new(one.merge(two));
let res = client.get("/").send().await;
let body = res.text().await;
assert_eq!(body, "GET");
let res = client.post("/").send().await;
let body = res.text().await;
assert_eq!(body, "POST");
}