Skip to content

Commit

Permalink
Expose the matched route as an extension on the request
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Löthberg <[email protected]>
  • Loading branch information
kyrias committed Sep 5, 2022
1 parent e79e4f6 commit f7758ff
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub use redirect::Redirect;
pub use request::Request;
pub use response::Response;
pub use response_builder::ResponseBuilder;
pub use route::Route;
pub use route::{MatchedRoute, Route};
pub use server::Server;

pub use http_types::{self as http, Body, Error, Status, StatusCode};
Expand Down
23 changes: 23 additions & 0 deletions src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@ use crate::{router::Router, Endpoint, Middleware};

use kv_log_macro::trace;

/// Extension struct for exposing the matched route.
///
/// # Examples
///
/// ```
/// # use tide::{MatchedRoute, Request};
/// let mut app = tide::Server::new();
/// app.at("/route").get(|req: Request<()>| async move {
/// let route: &str = req.ext::<MatchedRoute>().unwrap();
/// Ok(route.to_string())
/// });
/// ```
#[derive(Debug)]
pub struct MatchedRoute(pub String);

impl std::ops::Deref for MatchedRoute {
type Target = str;

fn deref(&self) -> &Self::Target {
&self.0
}
}

/// A handle to a route.
///
/// All HTTP requests are made against resources. After using [`Server::at`] (or
Expand Down
5 changes: 5 additions & 0 deletions src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ impl<State> std::fmt::Debug for Router<State> {
pub(crate) struct Selection<'a, State> {
pub(crate) endpoint: &'a DynEndpoint<State>,
pub(crate) params: Captures<'static, 'static>,
pub(crate) matched_route: Option<String>,
}

impl<State: Clone + Send + Sync + 'static> Router<State> {
Expand Down Expand Up @@ -63,11 +64,13 @@ impl<State: Clone + Send + Sync + 'static> Router<State> {
Selection {
endpoint: m.handler(),
params: m.captures().into_owned(),
matched_route: Some(m.route().to_string()),
}
} else if let Some(m) = self.all_method_router.best_match(path) {
Selection {
endpoint: m.handler(),
params: m.captures().into_owned(),
matched_route: Some(m.route().to_string()),
}
} else if method == http_types::Method::Head {
// If it is a HTTP HEAD request then check if there is a callback in the endpoints map
Expand All @@ -85,11 +88,13 @@ impl<State: Clone + Send + Sync + 'static> Router<State> {
Selection {
endpoint: &method_not_allowed,
params: Captures::default(),
matched_route: None,
}
} else {
Selection {
endpoint: &not_found_endpoint,
params: Captures::default(),
matched_route: None,
}
}
}
Expand Down
25 changes: 21 additions & 4 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use kv_log_macro::{info, trace};
use crate::cookies;
use crate::listener::{Listener, ToListener};
use crate::middleware::{Middleware, Next};
use crate::route::MatchedRoute;
use crate::router::{Router, Selection};
use crate::{Endpoint, Request, Route};

Expand Down Expand Up @@ -287,9 +288,17 @@ where
} = self.clone();

let method = req.method().to_owned();
let Selection { endpoint, params } = router.route(req.url().path(), method);
let Selection {
endpoint,
params,
matched_route,
} = router.route(req.url().path(), method);
let route_params = vec![params];
let req = Request::new(state, req, route_params);
let mut req = Request::new(state, req, route_params);

if let Some(route) = matched_route {
req.set_ext(MatchedRoute(route));
}

let next = Next {
endpoint,
Expand Down Expand Up @@ -349,9 +358,17 @@ impl<State: Clone + Sync + Send + 'static, InnerState: Clone + Sync + Send + 'st
let middleware = self.middleware.clone();
let state = self.state.clone();

let Selection { endpoint, params } = router.route(&path, method);
let Selection {
endpoint,
params,
matched_route,
} = router.route(&path, method);
route_params.push(params);
let req = Request::new(state, req, route_params);
let mut req = Request::new(state, req, route_params);

if let Some(route) = matched_route {
req.set_ext(MatchedRoute(route));
}

let next = Next {
endpoint,
Expand Down

0 comments on commit f7758ff

Please sign in to comment.