From 0b69a5d8f7445ff19f34d9c0b8778646cabe0623 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Sun, 5 Feb 2017 01:43:53 -0800 Subject: [PATCH] Ensure routes with and without query params don't collide. --- lib/src/router/collider.rs | 25 ++++++++++ lib/tests/query-and-non-query-dont-collide.rs | 49 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 lib/tests/query-and-non-query-dont-collide.rs diff --git a/lib/src/router/collider.rs b/lib/src/router/collider.rs index a5c6fbf8..ec2a72db 100644 --- a/lib/src/router/collider.rs +++ b/lib/src/router/collider.rs @@ -52,6 +52,10 @@ impl<'a> Collider for &'a str { impl<'a, 'b> Collider> for URI<'a> { fn collides_with(&self, other: &URI<'b>) -> bool { + if self.query().is_some() != other.query().is_some() { + return false; + } + for (seg_a, seg_b) in self.segments().zip(other.segments()) { if seg_a.ends_with("..>") || seg_b.ends_with("..>") { return true; @@ -194,6 +198,17 @@ mod tests { assert!(unranked_collide("/", "///a///")); } + + #[test] + fn query_collisions() { + assert!(unranked_collide("/?", "/?")); + assert!(unranked_collide("/a/?", "/a/?")); + assert!(unranked_collide("/a?", "/a?")); + assert!(unranked_collide("/?", "/?")); + assert!(unranked_collide("/a/b/c?", "/a/b/c?")); + assert!(unranked_collide("//b/c?", "/a/b/?")); + } + #[test] fn non_collisions() { assert!(!unranked_collide("/a", "/b")); @@ -214,6 +229,16 @@ mod tests { assert!(!unranked_collide("/", "//////")); } + #[test] + fn query_non_collisions() { + assert!(!unranked_collide("/?", "/")); + assert!(!unranked_collide("/?", "/hi")); + assert!(!unranked_collide("/?", "/a")); + assert!(!unranked_collide("/a?", "/a")); + assert!(!unranked_collide("/a/b?", "/a/b")); + assert!(!unranked_collide("/a/b", "/a/b/?")); + } + #[test] fn method_dependent_non_collisions() { assert!(!m_collide((Get, "/"), (Post, "/"))); diff --git a/lib/tests/query-and-non-query-dont-collide.rs b/lib/tests/query-and-non-query-dont-collide.rs new file mode 100644 index 00000000..a7fff33f --- /dev/null +++ b/lib/tests/query-and-non-query-dont-collide.rs @@ -0,0 +1,49 @@ +#![feature(plugin, custom_derive)] +#![plugin(rocket_codegen)] + +extern crate rocket; + +#[derive(FromForm)] +struct Query { + field: String +} + +#[get("/?")] +fn first(query: Query) -> String { + query.field +} + +#[get("/")] +fn second() -> &'static str { + "no query" +} + +#[cfg(feature = "testing")] +mod tests { + use super::*; + + use rocket::Rocket; + use rocket::testing::MockRequest; + use rocket::http::Method::*; + + fn assert_no_collision(rocket: &Rocket) { + let mut req = MockRequest::new(Get, "/?field=query"); + let mut response = req.dispatch_with(&rocket); + let body_str = response.body().and_then(|b| b.into_string()); + assert_eq!(body_str, Some("query".to_string())); + + let mut req = MockRequest::new(Get, "/"); + let mut response = req.dispatch_with(&rocket); + let body_str = response.body().and_then(|b| b.into_string()); + assert_eq!(body_str, Some("no query".to_string())); + } + + #[test] + fn check_query_collisions() { + let rocket = rocket::ignite().mount("/", routes![first, second]); + assert_no_collision(&rocket); + + let rocket = rocket::ignite().mount("/", routes![second, first]); + assert_no_collision(&rocket); + } +}