Ensure routes with and without query params don't collide.

This commit is contained in:
Sergio Benitez 2017-02-05 01:43:53 -08:00
parent e966925455
commit 0b69a5d8f7
2 changed files with 74 additions and 0 deletions

View File

@ -52,6 +52,10 @@ impl<'a> Collider<str> for &'a str {
impl<'a, 'b> Collider<URI<'b>> for URI<'a> { impl<'a, 'b> Collider<URI<'b>> for URI<'a> {
fn collides_with(&self, other: &URI<'b>) -> bool { 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()) { for (seg_a, seg_b) in self.segments().zip(other.segments()) {
if seg_a.ends_with("..>") || seg_b.ends_with("..>") { if seg_a.ends_with("..>") || seg_b.ends_with("..>") {
return true; return true;
@ -194,6 +198,17 @@ mod tests {
assert!(unranked_collide("/<a..>", "///a///")); assert!(unranked_collide("/<a..>", "///a///"));
} }
#[test]
fn query_collisions() {
assert!(unranked_collide("/?<a>", "/?<a>"));
assert!(unranked_collide("/a/?<a>", "/a/?<a>"));
assert!(unranked_collide("/a?<a>", "/a?<a>"));
assert!(unranked_collide("/<r>?<a>", "/<r>?<a>"));
assert!(unranked_collide("/a/b/c?<a>", "/a/b/c?<a>"));
assert!(unranked_collide("/<a>/b/c?<d>", "/a/b/<c>?<d>"));
}
#[test] #[test]
fn non_collisions() { fn non_collisions() {
assert!(!unranked_collide("/a", "/b")); assert!(!unranked_collide("/a", "/b"));
@ -214,6 +229,16 @@ mod tests {
assert!(!unranked_collide("/<a..>", "//////")); assert!(!unranked_collide("/<a..>", "//////"));
} }
#[test]
fn query_non_collisions() {
assert!(!unranked_collide("/?<a>", "/"));
assert!(!unranked_collide("/?<a>", "/hi"));
assert!(!unranked_collide("/?<a>", "/a"));
assert!(!unranked_collide("/a?<a>", "/a"));
assert!(!unranked_collide("/a/b?<a>", "/a/b"));
assert!(!unranked_collide("/a/b", "/a/b/?<c>"));
}
#[test] #[test]
fn method_dependent_non_collisions() { fn method_dependent_non_collisions() {
assert!(!m_collide((Get, "/"), (Post, "/"))); assert!(!m_collide((Get, "/"), (Post, "/")));

View File

@ -0,0 +1,49 @@
#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[derive(FromForm)]
struct Query {
field: String
}
#[get("/?<query>")]
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);
}
}