Skip to content

Commit f7758ff

Browse files
committed
Expose the matched route as an extension on the request
Signed-off-by: Johannes Löthberg <[email protected]>
1 parent e79e4f6 commit f7758ff

File tree

4 files changed

+50
-5
lines changed

4 files changed

+50
-5
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub use redirect::Redirect;
9494
pub use request::Request;
9595
pub use response::Response;
9696
pub use response_builder::ResponseBuilder;
97-
pub use route::Route;
97+
pub use route::{MatchedRoute, Route};
9898
pub use server::Server;
9999

100100
pub use http_types::{self as http, Body, Error, Status, StatusCode};

src/route.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,29 @@ use crate::{router::Router, Endpoint, Middleware};
99

1010
use kv_log_macro::trace;
1111

12+
/// Extension struct for exposing the matched route.
13+
///
14+
/// # Examples
15+
///
16+
/// ```
17+
/// # use tide::{MatchedRoute, Request};
18+
/// let mut app = tide::Server::new();
19+
/// app.at("/route").get(|req: Request<()>| async move {
20+
/// let route: &str = req.ext::<MatchedRoute>().unwrap();
21+
/// Ok(route.to_string())
22+
/// });
23+
/// ```
24+
#[derive(Debug)]
25+
pub struct MatchedRoute(pub String);
26+
27+
impl std::ops::Deref for MatchedRoute {
28+
type Target = str;
29+
30+
fn deref(&self) -> &Self::Target {
31+
&self.0
32+
}
33+
}
34+
1235
/// A handle to a route.
1336
///
1437
/// All HTTP requests are made against resources. After using [`Server::at`] (or

src/router.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ impl<State> std::fmt::Debug for Router<State> {
2727
pub(crate) struct Selection<'a, State> {
2828
pub(crate) endpoint: &'a DynEndpoint<State>,
2929
pub(crate) params: Captures<'static, 'static>,
30+
pub(crate) matched_route: Option<String>,
3031
}
3132

3233
impl<State: Clone + Send + Sync + 'static> Router<State> {
@@ -63,11 +64,13 @@ impl<State: Clone + Send + Sync + 'static> Router<State> {
6364
Selection {
6465
endpoint: m.handler(),
6566
params: m.captures().into_owned(),
67+
matched_route: Some(m.route().to_string()),
6668
}
6769
} else if let Some(m) = self.all_method_router.best_match(path) {
6870
Selection {
6971
endpoint: m.handler(),
7072
params: m.captures().into_owned(),
73+
matched_route: Some(m.route().to_string()),
7174
}
7275
} else if method == http_types::Method::Head {
7376
// If it is a HTTP HEAD request then check if there is a callback in the endpoints map
@@ -85,11 +88,13 @@ impl<State: Clone + Send + Sync + 'static> Router<State> {
8588
Selection {
8689
endpoint: &method_not_allowed,
8790
params: Captures::default(),
91+
matched_route: None,
8892
}
8993
} else {
9094
Selection {
9195
endpoint: &not_found_endpoint,
9296
params: Captures::default(),
97+
matched_route: None,
9398
}
9499
}
95100
}

src/server.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use kv_log_macro::{info, trace};
88
use crate::cookies;
99
use crate::listener::{Listener, ToListener};
1010
use crate::middleware::{Middleware, Next};
11+
use crate::route::MatchedRoute;
1112
use crate::router::{Router, Selection};
1213
use crate::{Endpoint, Request, Route};
1314

@@ -287,9 +288,17 @@ where
287288
} = self.clone();
288289

289290
let method = req.method().to_owned();
290-
let Selection { endpoint, params } = router.route(req.url().path(), method);
291+
let Selection {
292+
endpoint,
293+
params,
294+
matched_route,
295+
} = router.route(req.url().path(), method);
291296
let route_params = vec![params];
292-
let req = Request::new(state, req, route_params);
297+
let mut req = Request::new(state, req, route_params);
298+
299+
if let Some(route) = matched_route {
300+
req.set_ext(MatchedRoute(route));
301+
}
293302

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

352-
let Selection { endpoint, params } = router.route(&path, method);
361+
let Selection {
362+
endpoint,
363+
params,
364+
matched_route,
365+
} = router.route(&path, method);
353366
route_params.push(params);
354-
let req = Request::new(state, req, route_params);
367+
let mut req = Request::new(state, req, route_params);
368+
369+
if let Some(route) = matched_route {
370+
req.set_ext(MatchedRoute(route));
371+
}
355372

356373
let next = Next {
357374
endpoint,

0 commit comments

Comments
 (0)