Skip to content

Commit 09528e0

Browse files
committed
split apart router and subrouter
1 parent 774af3d commit 09528e0

File tree

4 files changed

+68
-34
lines changed

4 files changed

+68
-34
lines changed

examples/simple_nested_router.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use tide::{
66
head::{Named, NamedComponent},
7-
Router,
7+
Router, SubRouter,
88
};
99

1010
struct Number(i32);
@@ -26,12 +26,17 @@ async fn add_two(Named(number): Named<Number>) -> String {
2626
format!("{} plus two is {}", num, num + 2)
2727
}
2828

29-
fn build_add_two<Data: Clone + Send + Sync + 'static>(router: &mut Router<Data>) {
29+
fn build_add_two<Data: Clone + Send + Sync + 'static>(router: &mut SubRouter<Data>) {
3030
router.at("{num}").get(add_two);
3131
}
3232

3333
fn main() {
3434
let mut app = tide::App::new(());
35+
app.at("/speech").nest(|router| {
36+
router.at("hello").get(async || "hello world");
37+
router.at("nice").get(async || "nice!");
38+
});
39+
3540
app.at("add_two").nest(build_add_two);
3641
app.serve("127.0.0.1:8000");
3742
}

src/app.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
endpoint::Endpoint,
1515
extract::Extract,
1616
middleware::{logger::RootLogger, RequestContext},
17-
router::{Resource, RouteResult, Router},
17+
router::{BaseRouter, Resource, RouteResult, Router},
1818
Middleware, Request, Response, RouteMatch,
1919
};
2020

@@ -25,7 +25,7 @@ use crate::{
2525
/// They also hold a top-level router.
2626
pub struct App<Data> {
2727
data: Data,
28-
router: Router<Data>,
28+
router: BaseRouter<Data>,
2929
}
3030

3131
impl<Data: Clone + Send + Sync + 'static> App<Data> {
@@ -34,7 +34,7 @@ impl<Data: Clone + Send + Sync + 'static> App<Data> {
3434
let logger = RootLogger::new();
3535
let mut app = App {
3636
data,
37-
router: Router::new(),
37+
router: BaseRouter::new(),
3838
};
3939

4040
// Add RootLogger as a default middleware
@@ -43,7 +43,7 @@ impl<Data: Clone + Send + Sync + 'static> App<Data> {
4343
}
4444

4545
/// Get the top-level router.
46-
pub fn router(&mut self) -> &mut Router<Data> {
46+
pub fn router(&mut self) -> &mut BaseRouter<Data> {
4747
&mut self.router
4848
}
4949

@@ -99,7 +99,7 @@ impl<Data: Clone + Send + Sync + 'static> App<Data> {
9999
#[derive(Clone)]
100100
struct Server<Data> {
101101
data: Data,
102-
router: Arc<Router<Data>>,
102+
router: Arc<BaseRouter<Data>>,
103103
}
104104

105105
impl<Data: Clone + Send + Sync + 'static> Service for Server<Data> {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ pub use crate::{
2929
middleware::Middleware,
3030
request::Request,
3131
response::{IntoResponse, Response},
32-
router::{Resource, Router},
32+
router::{BaseRouter, Resource, Router, SubRouter},
3333
};
3434
pub use path_table::RouteMatch;

src/router.rs

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ use path_table::{PathTable, RouteMatch};
1010
/// A core type for routing.
1111
///
1212
/// The `Router` type can be used to set up routes and resources, and to apply middleware.
13-
pub struct Router<Data> {
13+
pub struct BaseRouter<Data> {
1414
table: PathTable<ResourceData<Data>>,
1515
middleware_base: Vec<Arc<dyn Middleware<Data> + Send + Sync>>,
1616
default_handler: Arc<BoxedEndpoint<Data>>,
1717
}
1818

19+
pub struct SubRouter<Data> {
20+
table: PathTable<ResourceData<Data>>,
21+
middleware_base: Vec<Arc<dyn Middleware<Data> + Send + Sync>>,
22+
}
23+
1924
pub(crate) struct RouteResult<'a, Data> {
2025
pub(crate) endpoint: &'a BoxedEndpoint<Data>,
2126
pub(crate) params: Option<RouteMatch<'a>>,
2227
pub(crate) middleware: &'a [Arc<dyn Middleware<Data> + Send + Sync>],
2328
}
2429

25-
pub async fn base_default_handler() -> http::status::StatusCode {
30+
async fn base_default_handler() -> http::status::StatusCode {
2631
http::status::StatusCode::NOT_FOUND
2732
}
2833

@@ -59,23 +64,19 @@ fn route_match_failure<'a, Data>(
5964
}
6065
}
6166

62-
impl<Data: Clone + Send + Sync + 'static> Router<Data> {
63-
/// Create a new top-level router.
64-
pub(crate) fn new() -> Router<Data> {
65-
Router {
66-
table: PathTable::new(),
67-
middleware_base: Vec::new(),
68-
default_handler: Arc::new(BoxedEndpoint::new(base_default_handler)),
69-
}
70-
}
67+
pub trait Router<Data: Clone + Send + Sync + 'static> {
68+
fn at<'a>(&'a mut self, path: &'a str) -> Resource<'a, Data>;
69+
70+
fn middleware(&mut self, middleware: impl Middleware<Data> + 'static) -> &mut Self;
71+
}
7172

73+
impl<Data: Clone + Send + Sync + 'static> Router<Data> for BaseRouter<Data> {
7274
/// Add a new resource at `path`, relative to this router.
73-
pub fn at<'a>(&'a mut self, path: &'a str) -> Resource<'a, Data> {
75+
fn at<'a>(&'a mut self, path: &'a str) -> Resource<'a, Data> {
7476
let table = self.table.setup_table(path);
7577
Resource {
7678
table,
7779
middleware_base: &self.middleware_base,
78-
default_handler: &self.default_handler,
7980
}
8081
}
8182

@@ -107,14 +108,44 @@ impl<Data: Clone + Send + Sync + 'static> Router<Data> {
107108
/// router.at("").get(async || "B then A");
108109
/// });
109110
/// ```
110-
pub fn middleware(&mut self, middleware: impl Middleware<Data> + 'static) -> &mut Self {
111+
fn middleware(&mut self, middleware: impl Middleware<Data> + 'static) -> &mut Self {
112+
let middleware = Arc::new(middleware);
113+
for resource in self.table.iter_mut() {
114+
resource.middleware.push(middleware.clone());
115+
}
116+
self.middleware_base.push(middleware);
117+
self
118+
}
119+
}
120+
121+
impl<Data: Clone + Send + Sync + 'static> Router<Data> for SubRouter<Data> {
122+
fn at<'a>(&'a mut self, path: &'a str) -> Resource<'a, Data> {
123+
let table = self.table.setup_table(path);
124+
Resource {
125+
table,
126+
middleware_base: &self.middleware_base,
127+
}
128+
}
129+
130+
fn middleware(&mut self, middleware: impl Middleware<Data> + 'static) -> &mut Self {
111131
let middleware = Arc::new(middleware);
112132
for resource in self.table.iter_mut() {
113133
resource.middleware.push(middleware.clone());
114134
}
115135
self.middleware_base.push(middleware);
116136
self
117137
}
138+
}
139+
140+
impl<Data: Clone + Send + Sync + 'static> BaseRouter<Data> {
141+
/// Create a new top-level router.
142+
pub(crate) fn new() -> BaseRouter<Data> {
143+
BaseRouter {
144+
table: PathTable::new(),
145+
middleware_base: Vec::new(),
146+
default_handler: Arc::new(BoxedEndpoint::new(base_default_handler)),
147+
}
148+
}
118149

119150
pub fn set_default_handler<T: Endpoint<Data, U>, U>(&mut self, ep: T) -> &mut Self {
120151
self.default_handler = Arc::new(BoxedEndpoint::new(ep));
@@ -148,7 +179,6 @@ impl<Data: Clone + Send + Sync + 'static> Router<Data> {
148179
pub struct Resource<'a, Data> {
149180
table: &'a mut PathTable<ResourceData<Data>>,
150181
middleware_base: &'a Vec<Arc<dyn Middleware<Data> + Send + Sync>>,
151-
default_handler: &'a Arc<BoxedEndpoint<Data>>,
152182
}
153183

154184
struct ResourceData<Data> {
@@ -164,11 +194,10 @@ impl<'a, Data> Resource<'a, Data> {
164194
/// the builder will be local to the subrouter and its descendents.
165195
///
166196
/// If resources are already present, they will be discarded.
167-
pub fn nest(self, builder: impl FnOnce(&mut Router<Data>)) {
168-
let mut subrouter = Router {
197+
pub fn nest(self, builder: impl FnOnce(&mut SubRouter<Data>)) {
198+
let mut subrouter = SubRouter {
169199
table: PathTable::new(),
170200
middleware_base: self.middleware_base.clone(),
171-
default_handler: self.default_handler.clone(),
172201
};
173202
builder(&mut subrouter);
174203
*self.table = subrouter.table;
@@ -253,7 +282,7 @@ mod tests {
253282
}
254283

255284
async fn simulate_request<'a, Data: Default + Clone + Send + Sync + 'static>(
256-
router: &'a Router<Data>,
285+
router: &'a BaseRouter<Data>,
257286
path: &'a str,
258287
method: &'a http::Method,
259288
) -> Option<Response> {
@@ -281,7 +310,7 @@ mod tests {
281310
}
282311

283312
fn route_middleware_count<Data: Clone + Send + Sync + 'static>(
284-
router: &Router<Data>,
313+
router: &BaseRouter<Data>,
285314
path: &str,
286315
method: &http::Method,
287316
) -> Option<usize> {
@@ -291,7 +320,7 @@ mod tests {
291320

292321
#[test]
293322
fn simple_static() {
294-
let mut router: Router<()> = Router::new();
323+
let mut router: BaseRouter<()> = BaseRouter::new();
295324
router.at("/").get(async || "/");
296325
router.at("/foo").get(async || "/foo");
297326
router.at("/foo/bar").get(async || "/foo/bar");
@@ -311,7 +340,7 @@ mod tests {
311340

312341
#[test]
313342
fn nested_static() {
314-
let mut router: Router<()> = Router::new();
343+
let mut router: BaseRouter<()> = BaseRouter::new();
315344
router.at("/a").get(async || "/a");
316345
router.at("/b").nest(|router| {
317346
router.at("/").get(async || "/b");
@@ -357,7 +386,7 @@ mod tests {
357386

358387
#[test]
359388
fn multiple_methods() {
360-
let mut router: Router<()> = Router::new();
389+
let mut router: BaseRouter<()> = BaseRouter::new();
361390
router
362391
.at("/a")
363392
.nest(|router| router.at("/b").get(async || "/a/b GET"));
@@ -378,7 +407,7 @@ mod tests {
378407
#[test]
379408
#[should_panic]
380409
fn duplicate_endpoint_fails() {
381-
let mut router: Router<()> = Router::new();
410+
let mut router: BaseRouter<()> = BaseRouter::new();
382411
router
383412
.at("/a")
384413
.nest(|router| router.at("/b").get(async || "")); // flattened into /a/b
@@ -387,7 +416,7 @@ mod tests {
387416

388417
#[test]
389418
fn simple_middleware() {
390-
let mut router: Router<()> = Router::new();
419+
let mut router: BaseRouter<()> = BaseRouter::new();
391420
router.middleware(passthrough_middleware);
392421
router.at("/").get(async || "/");
393422
router.at("/b").nest(|router| {
@@ -423,7 +452,7 @@ mod tests {
423452

424453
// The order of endpoint and middleware does not matter
425454
// The order of subrouter and middleware DOES matter
426-
let mut router: Router<Data> = Router::new();
455+
let mut router: BaseRouter<Data> = BaseRouter::new();
427456
router.middleware(Pusher(0));
428457
router.at("/").get(async move |data: AppData<Data>| {
429458
if (data.0).0 == [0, 2] {

0 commit comments

Comments
 (0)