diff --git a/examples/json.rs b/examples/json.rs index c0495f6..9fabe09 100644 --- a/examples/json.rs +++ b/examples/json.rs @@ -30,6 +30,7 @@ fn main() { max_age: Some(42), send_wildcard: false, fairing_route_base: "/mycors".to_string(), + fairing_route_rank: 0, }; println!("Default settings"); diff --git a/src/fairing.rs b/src/fairing.rs index 2d46209..09343aa 100644 --- a/src/fairing.rs +++ b/src/fairing.rs @@ -53,8 +53,8 @@ pub(crate) fn fairing_error_route<'r>( } /// Create a new `Route` for Fairing handling -fn fairing_route() -> rocket::Route { - rocket::Route::new(http::Method::Get, "/", fairing_error_route) +fn fairing_route(rank: isize) -> rocket::Route { + rocket::Route::ranked(rank, http::Method::Get, "/", fairing_error_route) } /// Modifies a `Request` to route to Fairing error handler @@ -130,7 +130,10 @@ impl rocket::fairing::Fairing for Cors { fn on_attach(&self, rocket: rocket::Rocket) -> Result { match self.validate() { - Ok(()) => Ok(rocket.mount(&self.fairing_route_base, vec![fairing_route()])), + Ok(()) => Ok(rocket.mount( + &self.fairing_route_base, + vec![fairing_route(self.fairing_route_rank)], + )), Err(e) => { error_!("Error attaching CORS fairing: {}", e); Err(rocket) diff --git a/src/lib.rs b/src/lib.rs index ffefcea..814e75f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,24 @@ //! } //! //! ``` +//! #### Injected Route +//! +//! The fairing implementation will inject a route during attachment to Rocket. This route is used +//! to handle errors during CORS validation. +//! +//! This is due to the limitation in Rocket's Fairing +//! [lifecycle](https://rocket.rs/guide/fairings/). Ideally, we want to validate the CORS request +//! during `on_request`, and if the validation fails, we want to stop the route from even executing +//! to +//! +//! 1) prevent side effects +//! 1) prevent resource usage from unnecessary computation +//! +//! The only way to do this is to hijack the request and route it to our own injected route to +//! handle errors. Rocket does not allow Fairings to stop the processing of a route. +//! +//! You can configure the behaviour of the injected route through a couple of fields in the +//! [`Cors` struct](Cors). //! //! ### Request Guard //! @@ -916,7 +934,8 @@ impl AllowedHeaders { /// "expose_headers": [], /// "max_age": null, /// "send_wildcard": false, -/// "fairing_route_base": "/cors" +/// "fairing_route_base": "/cors", +/// "fairing_route_rank": 0 /// } /// ``` /// ### Defined @@ -1031,13 +1050,20 @@ pub struct Cors { /// Defaults to `false`. #[cfg_attr(feature = "serialization", serde(default))] pub send_wildcard: bool, - /// When used as Fairing, Cors will need to redirect failed CORS checks to a custom route to - /// be mounted by the fairing. Specify the base the route so that it doesn't clash with any + /// When used as Fairing, Cors will need to redirect failed CORS checks to a custom route + /// mounted by the fairing. Specify the base of the route so that it doesn't clash with any /// of your existing routes. /// /// Defaults to "/cors" #[cfg_attr(feature = "serialization", serde(default = "Cors::default_fairing_route_base"))] pub fairing_route_base: String, + /// When used as Fairing, Cors will need to redirect failed CORS checks to a custom route + /// mounted by the fairing. Specify the rank of the route so that it doesn't clash with any + /// of your existing routes. Remember that a higher ranked route has lower priority. + /// + /// Defaults to 0 + #[cfg_attr(feature = "serialization", serde(default = "Cors::default_fairing_route_rank"))] + pub fairing_route_rank: isize, } impl Default for Cors { @@ -1051,6 +1077,7 @@ impl Default for Cors { max_age: Default::default(), send_wildcard: Default::default(), fairing_route_base: Self::default_fairing_route_base(), + fairing_route_rank: Self::default_fairing_route_rank(), } } } @@ -1076,6 +1103,10 @@ impl Cors { "/cors".to_string() } + fn default_fairing_route_rank() -> isize { + 0 + } + /// Validates if any of the settings are disallowed or incorrect /// /// This is run during initial Fairing attachment