diff --git a/core/lib/src/catcher/catcher.rs b/core/lib/src/catcher/catcher.rs index 1407bd0f..4a60f791 100644 --- a/core/lib/src/catcher/catcher.rs +++ b/core/lib/src/catcher/catcher.rs @@ -11,12 +11,10 @@ use crate::catcher::{Handler, BoxFuture}; use yansi::Paint; -// We could also choose to require a Debug impl? -/// A generic trait for route types. This should be automatically implemented on the structs -/// generated by the codegen for each route. +/// A generic trait for catcher types. This should be automatically implemented on the structs +/// generated by the codegen for each catcher, and manually implemented on custom cater types. /// -/// It may also be desirable to add an option for other routes to define a RouteType. This -/// would likely just be a case of adding an alternate constructor to the Route type. +/// Use the `Catcher::with_type::()` method to set the catcher type. pub trait CatcherType: Any + Send + Sync + 'static { } /// An error catching route. @@ -183,6 +181,8 @@ impl Catcher { /// /// Panics if `code` is not in the HTTP status code error range `[400, /// 600)`. + /// + /// If applicable, `with_type` should also be called to set the route type for testing #[inline(always)] pub fn new(code: S, handler: H) -> Catcher where S: Into>, H: Handler @@ -274,6 +274,13 @@ impl Catcher { self } + /// Marks this catcher with the specified type. For a custom catcher type, i.e. something that can + /// be passed to `.register()`, it should be that type to make identification easier. + pub fn with_type(mut self) -> Self { + self.catcher_type = Some(TypeId::of::()); + self + } + /// Maps the `base` of this catcher using `mapper`, returning a new /// `Catcher` with the returned base. /// diff --git a/core/lib/src/local/response.rs b/core/lib/src/local/response.rs index 38d972a9..f0accbe8 100644 --- a/core/lib/src/local/response.rs +++ b/core/lib/src/local/response.rs @@ -180,7 +180,8 @@ macro_rules! pub_response_impl { self._into_msgpack() $(.$suffix)? } - /// Checks if a route was routed by a specific route type + /// Checks if a route was routed by a specific route type. This only returns true if the route + /// actually generated a response, and a catcher was not run. /// /// # Example /// @@ -194,6 +195,12 @@ macro_rules! pub_response_impl { /// assert!(response.routed_by::()) /// # }); /// ``` + /// + /// # Other Route types + /// + /// [`FileServer`](crate::fs::FileServer) implementes `RouteType`, so a route that should + /// return a static file can be checked against it. Libraries which provide a Route type should + /// implement `RouteType`, see [`RouteType`](crate::route::RouteType) for more information. pub fn routed_by(&self) -> bool { if let Some(route_type) = self._request().route().map(|r| r.route_type).flatten() { route_type == std::any::TypeId::of::() @@ -208,14 +215,18 @@ macro_rules! pub_response_impl { /// /// ```rust /// # use rocket::get; - /// #[get("/")] - /// fn index() -> &'static str { "Hello World" } + /// #[catch(404)] + /// fn default_404() -> &'static str { "Hello World" } #[doc = $doc_prelude] /// # Client::_test(|_, _, response| { /// let response: LocalResponse = response; - /// assert!(response.routed_by::()) + /// assert!(response.caught_by::()) /// # }); /// ``` + /// + /// # Rocket's default catcher + /// + /// The default catcher has a `CatcherType` of [`DefaultCatcher`](crate::catcher::DefaultCatcher) pub fn caught_by(&self) -> bool { if let Some(catcher_type) = self._request().catcher().map(|r| r.catcher_type).flatten() { catcher_type == std::any::TypeId::of::() @@ -224,6 +235,22 @@ macro_rules! pub_response_impl { } } + /// Checks if a route was caught by a catcher + /// + /// # Example + /// + /// ```rust + /// # use rocket::get; + #[doc = $doc_prelude] + /// # Client::_test(|_, _, response| { + /// let response: LocalResponse = response; + /// assert!(response.was_caught()) + /// # }); + /// ``` + pub fn was_caught(&self) -> bool { + self._request().catcher().is_some() + } + #[cfg(test)] #[allow(dead_code)] fn _ensure_impls_exist() { diff --git a/core/lib/src/route/route.rs b/core/lib/src/route/route.rs index f51e4dc9..fc2b3557 100644 --- a/core/lib/src/route/route.rs +++ b/core/lib/src/route/route.rs @@ -9,12 +9,10 @@ use crate::http::{uri, MediaType, Method}; use crate::route::{BoxFuture, Handler, RouteUri}; use crate::sentinel::Sentry; -// We could also choose to require a Debug impl? /// A generic trait for route types. This should be automatically implemented on the structs -/// generated by the codegen for each route. +/// generated by the codegen for each route, and manually implemented on custom route types. /// -/// It may also be desirable to add an option for other routes to define a RouteType. This -/// would likely just be a case of adding an alternate constructor to the Route type. +/// Use the `Route::with_type::()` method to set the route type. pub trait RouteType: Any + Send + Sync + 'static { } /// A request handling route. @@ -219,6 +217,8 @@ impl Route { /// assert_eq!(index.method, Method::Get); /// assert_eq!(index.uri, "/"); /// ``` + /// + /// If applicable, `with_type` should also be called to set the route type for testing #[track_caller] pub fn new(method: Method, uri: &str, handler: H) -> Route { Route::ranked(None, method, uri, handler) @@ -254,6 +254,8 @@ impl Route { /// assert_eq!(foo.method, Method::Post); /// assert_eq!(foo.uri, "/foo?bar"); /// ``` + /// + /// If applicable, `with_type` should also be called to set the route type for testing #[track_caller] pub fn ranked(rank: R, method: Method, uri: &str, handler: H) -> Route where @@ -315,7 +317,8 @@ impl Route { self } - /// Marks this route with the specified type + /// Marks this route with the specified type. For a custom route type, i.e. something that can + /// be passed to `.mount()`, it should be that type to make identification easier. pub fn with_type(mut self) -> Self { self.route_type = Some(TypeId::of::()); self