From d6e86be1b0cf8a2b33d980189e0edc16a9c753bc Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Tue, 18 Apr 2017 17:42:44 -0700 Subject: [PATCH] Make route collisions a hard error. This is a breaking change. Previously, route collisions were warnings. --- examples/errors/src/main.rs | 1 + lib/src/error.rs | 20 ++++++++++++++++++-- lib/src/rocket.rs | 4 ++-- lib/src/router/mod.rs | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/examples/errors/src/main.rs b/examples/errors/src/main.rs index edcb3981..8ce806cf 100644 --- a/examples/errors/src/main.rs +++ b/examples/errors/src/main.rs @@ -21,6 +21,7 @@ fn not_found(req: &rocket::Request) -> content::HTML { fn main() { let e = rocket::ignite() + // .mount("/", routes![hello, hello]) // uncoment this to get an error .mount("/", routes![hello]) .catch(errors![not_found]) .launch(); diff --git a/lib/src/error.rs b/lib/src/error.rs index ebbf14c5..65008a36 100644 --- a/lib/src/error.rs +++ b/lib/src/error.rs @@ -23,11 +23,14 @@ pub enum Error { /// The kind of launch error that occured. /// /// In almost every instance, a launch error occurs because of an I/O error; -/// this represented by the `Io` variant. The `Unknown` variant captures all -/// other kinds of launch errors. +/// this is represented by the `Io` variant. A launch error may also occur +/// because of ill-defined routes that lead to collisions; this is represented +/// by the `Collision` variant. The `Unknown` variant captures all other kinds +/// of launch errors. #[derive(Debug)] pub enum LaunchErrorKind { Io(io::Error), + Collision, Unknown(Box<::std::error::Error + Send + Sync>) } @@ -110,6 +113,13 @@ impl LaunchError { } } +impl From for LaunchError { + #[inline] + fn from(kind: LaunchErrorKind) -> LaunchError { + LaunchError::new(kind) + } +} + impl From for LaunchError { #[inline] fn from(error: hyper::Error) -> LaunchError { @@ -125,6 +135,7 @@ impl fmt::Display for LaunchErrorKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { LaunchErrorKind::Io(ref e) => write!(f, "I/O error: {}", e), + LaunchErrorKind::Collision => write!(f, "route collisions detected"), LaunchErrorKind::Unknown(ref e) => write!(f, "unknown error: {}", e) } } @@ -152,6 +163,7 @@ impl ::std::error::Error for LaunchError { self.mark_handled(); match *self.kind() { LaunchErrorKind::Io(_) => "an I/O error occured during launch", + LaunchErrorKind::Collision => "route collisions were detected", LaunchErrorKind::Unknown(_) => "an unknown error occured during launch" } } @@ -168,6 +180,10 @@ impl Drop for LaunchError { error!("Rocket failed to launch due to an I/O error."); panic!("{}", e); } + LaunchErrorKind::Collision => { + error!("Rocket failed to launch due to routing collisions."); + panic!("route collisions detected"); + } LaunchErrorKind::Unknown(ref e) => { error!("Rocket failed to launch due to an unknown error."); panic!("{}", e); diff --git a/lib/src/rocket.rs b/lib/src/rocket.rs index fefc5e79..0131db00 100644 --- a/lib/src/rocket.rs +++ b/lib/src/rocket.rs @@ -18,7 +18,7 @@ use response::{Body, Response}; use router::{Router, Route}; use catcher::{self, Catcher}; use outcome::Outcome; -use error::{Error, LaunchError}; +use error::{Error, LaunchError, LaunchErrorKind}; use http::{Method, Status, Header, Session}; use http::hyper::{self, header}; @@ -596,7 +596,7 @@ impl Rocket { /// ``` pub fn launch(self) -> LaunchError { if self.router.has_collisions() { - warn!("Route collisions detected!"); + return LaunchError::from(LaunchErrorKind::Collision); } let full_addr = format!("{}:{}", self.config.address, self.config.port); diff --git a/lib/src/router/mod.rs b/lib/src/router/mod.rs index 799e9298..cb8155b4 100644 --- a/lib/src/router/mod.rs +++ b/lib/src/router/mod.rs @@ -51,7 +51,7 @@ impl Router { for b_route in routes.iter().skip(i + 1) { if a_route.collides_with(b_route) { result = true; - warn!("{} and {} collide!", a_route, b_route); + error!("{} and {} collide!", a_route, b_route); } } }