Skip to content

Commit

Permalink
Implement tracing through the list of routes
Browse files Browse the repository at this point in the history
  • Loading branch information
the10thWiz committed Sep 10, 2023
1 parent 422945d commit 7b6ea9a
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 4 deletions.
63 changes: 60 additions & 3 deletions core/lib/src/local/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@ macro_rules! pub_response_impl {
self._into_msgpack() $(.$suffix)?
}

/// 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.
/// Checks if a response was generted by a specific route type. This only returns true if the route
/// actually generated the response, and a catcher was _not_ run. See [`was_attempted_by`] to
/// check if a route was attempted, but may not have generated the response
///
/// # Example
///
Expand All @@ -202,13 +203,69 @@ macro_rules! pub_response_impl {
/// return a static file can be checked against it. Libraries which provide custom Routes should
/// implement `RouteType`, see [`RouteType`](crate::route::RouteType) for more information.
pub fn was_routed_by<T: crate::route::RouteType>(&self) -> bool {
if let Some(route_type) = self._request().route().map(|r| r.route_type).flatten() {
// If this request was caught, the route in `.route()` did NOT generate this response.
if self._request().catcher().is_some() {
false
} else if let Some(route_type) = self._request().route().map(|r| r.route_type).flatten() {
route_type == std::any::TypeId::of::<T>()
} else {
false
}
}

/// Checks if a request was routed to a specific route type. This will return true for routes
/// that were attempted, _but not actually called_. This enables a test to verify that a route
/// was attempted, even if another route actually generated the response, e.g. an
/// authenticated route will typically defer to an error catcher if the request does not have
/// the proper authentication. This makes it possible to verify that a request was routed to
/// the authentication route, even if the response was eventaully generated by another route or
/// a catcher.
///
/// # Example
///
// WARNING: this doc-test is NOT run, because cargo test --doc does not run doc-tests for items
// only available during tests.
/// ```rust
/// # use rocket::{get, routes, async_trait, request::{Request, Outcome, FromRequest}};
/// # struct WillFail {}
/// # #[async_trait]
/// # impl<'r> FromRequest<'r> for WillFail {
/// # type Error = ();
/// # async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
/// # Outcome::Forward(())
/// # }
/// # }
/// #[get("/", rank = 2)]
/// fn index1(guard: WillFail) -> &'static str { "Hello World" }
/// #[get("/")]
/// fn index2() -> &'static str { "Hello World" }
#[doc = $doc_prelude]
/// # Client::_test_with(|r| r.mount("/", routes![index1, index2]), |_, _, response| {
/// let response: LocalResponse = response;
/// assert!(response.was_attempted_by::<index1>());
/// assert!(response.was_attempted_by::<index2>());
/// assert!(response.was_routed_by::<index2>());
/// # });
/// ```
///
/// # 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 custom Routes should
/// implement `RouteType`, see [`RouteType`](crate::route::RouteType) for more information.
///
/// # Note
///
/// This method is marked as `cfg(test)`, and is therefore only available in unit and
/// integration tests. This is because the list of routes attempted is only collected in these
/// testing environments, to minimize performance impacts during normal operation.
#[cfg(test)]
pub fn was_attempted_by<T: crate::route::RouteType>(&self) -> bool {
self._request().route_path(|path| path.iter().any(|r|
r.route_type == Some(std::any::TypeId::of::<T>())
))
}

/// Checks if a route was caught by a specific route type
///
/// # Example
Expand Down
25 changes: 24 additions & 1 deletion core/lib/src/request/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ use crate::http::uncased::UncasedStr;
use crate::http::private::Certificates;
use crate::http::uri::{fmt::Path, Origin, Segments, Host, Authority};

#[cfg(test)]
use parking_lot::Mutex;

/// The type of an incoming web request.
///
/// This should be used sparingly in Rocket applications. In particular, it
Expand Down Expand Up @@ -51,6 +54,8 @@ pub(crate) struct RequestState<'r> {
pub content_type: Storage<Option<ContentType>>,
pub cache: Arc<Container![Send + Sync]>,
pub host: Option<Host<'r>>,
#[cfg(test)]
pub route_path: Arc<Mutex<Vec<&'r Route>>>,
}

impl Request<'_> {
Expand All @@ -76,6 +81,8 @@ impl RequestState<'_> {
content_type: self.content_type.clone(),
cache: self.cache.clone(),
host: self.host.clone(),
#[cfg(test)]
route_path: self.route_path.clone(),
}
}
}
Expand Down Expand Up @@ -105,6 +112,8 @@ impl<'r> Request<'r> {
content_type: Storage::new(),
cache: Arc::new(<Container![Send + Sync]>::new()),
host: None,
#[cfg(test)]
route_path: Arc::new(Mutex::new(vec![])),
}
}
}
Expand Down Expand Up @@ -968,7 +977,21 @@ impl<'r> Request<'r> {
/// was `route`. Use during routing when attempting a given route.
#[inline(always)]
pub(crate) fn set_route(&self, route: Option<&'r Route>) {
self.state.route.store(route, Ordering::Release)
self.state.route.store(route, Ordering::Release);
#[cfg(test)]
if let Some(route) = route {
self.state.route_path.lock().push(route);
}
}

/// Compute a value using the route path of this request
///
/// This doesn't simply return a refernce, since the reference is held behind a Arc<Mutex>.
/// This method is only intended to be used internally, and is therefore NOT pub.
#[inline(always)]
#[cfg(test)]
pub(crate) fn route_path<R>(&self, operation: impl FnOnce(&[&'r Route]) -> R) -> R {
operation(self.state.route_path.lock().as_ref())
}

/// Set `self`'s parameters given that the route used to reach this request
Expand Down

0 comments on commit 7b6ea9a

Please sign in to comment.