Skip to content

Commit a4ee7fe

Browse files
committed
Preserve per-route middleware on nested subroutes
1 parent 7fc2577 commit a4ee7fe

File tree

2 files changed

+43
-38
lines changed

2 files changed

+43
-38
lines changed

src/server/route.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ impl<'a, State: 'static> Route<'a, State> {
3535
}
3636

3737
/// Extend the route with the given `path`.
38-
///
39-
/// The returned route won't have any middleware applied.
4038
pub fn at<'b>(&'b mut self, path: &str) -> Route<'b, State> {
4139
let mut p = self.path.clone();
4240

@@ -51,7 +49,7 @@ impl<'a, State: 'static> Route<'a, State> {
5149
Route {
5250
router: &mut self.router,
5351
path: p,
54-
middleware: Vec::new(),
52+
middleware: self.middleware.clone(),
5553
prefix: false,
5654
}
5755
}

tests/route_middleware.rs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
use async_std::io::prelude::*;
2-
use futures::executor::block_on;
31
use futures::future::BoxFuture;
42
use http_service::Body;
53
use http_service_mock::make_server;
64
use tide::Middleware;
75

8-
struct TestMiddleware(&'static str);
6+
struct TestMiddleware(&'static str, &'static str);
7+
8+
impl TestMiddleware {
9+
fn with_header_name(name: &'static str, value: &'static str) -> Self {
10+
Self(name, value)
11+
}
12+
}
913

1014
impl<State: Send + Sync + 'static> Middleware<State> for TestMiddleware {
1115
fn handle<'a>(
@@ -15,7 +19,7 @@ impl<State: Send + Sync + 'static> Middleware<State> for TestMiddleware {
1519
) -> BoxFuture<'a, tide::Response> {
1620
Box::pin(async move {
1721
let res = next.run(req).await;
18-
res.set_header("X-Tide-Test", self.0)
22+
res.set_header(self.0, self.1)
1923
})
2024
}
2125
}
@@ -28,52 +32,55 @@ async fn echo_path<State>(req: tide::Request<State>) -> String {
2832
fn route_middleware() {
2933
let mut app = tide::new();
3034
let mut foo_route = app.at("/foo");
31-
foo_route.middleware(TestMiddleware("foo")).get(echo_path);
35+
foo_route // /foo
36+
.middleware(TestMiddleware::with_header_name("X-Foo", "foo"))
37+
.get(echo_path);
3238
foo_route
33-
.at("/bar")
34-
.middleware(TestMiddleware("bar"))
39+
.at("/bar") // nested, /foo/bar
40+
.middleware(TestMiddleware::with_header_name("X-Bar", "bar"))
3541
.get(echo_path);
36-
foo_route.post(echo_path).reset_middleware().put(echo_path);
42+
foo_route // /foo
43+
.post(echo_path)
44+
.reset_middleware()
45+
.put(echo_path);
3746
let mut server = make_server(app.into_http_service()).unwrap();
3847

39-
let mut buf = Vec::new();
4048
let req = http::Request::get("/foo").body(Body::empty()).unwrap();
4149
let res = server.simulate(req).unwrap();
42-
assert_eq!(
43-
res.headers().get("X-Tide-Test"),
44-
Some(&"foo".parse().unwrap())
45-
);
46-
assert_eq!(res.status(), 200);
47-
block_on(res.into_body().read_to_end(&mut buf)).unwrap();
48-
assert_eq!(&*buf, &*b"/foo");
50+
assert_eq!(res.headers().get("X-Foo"), Some(&"foo".parse().unwrap()));
4951

50-
buf.clear();
5152
let req = http::Request::post("/foo").body(Body::empty()).unwrap();
5253
let res = server.simulate(req).unwrap();
53-
assert_eq!(
54-
res.headers().get("X-Tide-Test"),
55-
Some(&"foo".parse().unwrap())
56-
);
57-
assert_eq!(res.status(), 200);
58-
block_on(res.into_body().read_to_end(&mut buf)).unwrap();
59-
assert_eq!(&*buf, &*b"/foo");
54+
assert_eq!(res.headers().get("X-Foo"), Some(&"foo".parse().unwrap()));
6055

61-
buf.clear();
6256
let req = http::Request::put("/foo").body(Body::empty()).unwrap();
6357
let res = server.simulate(req).unwrap();
64-
assert_eq!(res.headers().get("X-Tide-Test"), None);
65-
assert_eq!(res.status(), 200);
66-
block_on(res.into_body().read_to_end(&mut buf)).unwrap();
67-
assert_eq!(&*buf, &*b"/foo");
58+
assert_eq!(res.headers().get("X-Foo"), None);
6859

69-
buf.clear();
7060
let req = http::Request::get("/foo/bar").body(Body::empty()).unwrap();
7161
let res = server.simulate(req).unwrap();
62+
assert_eq!(res.headers().get("X-Foo"), Some(&"foo".parse().unwrap()));
63+
assert_eq!(res.headers().get("X-Bar"), Some(&"bar".parse().unwrap()));
64+
}
65+
66+
#[test]
67+
fn subroute_not_nested() {
68+
let mut app = tide::new();
69+
app.at("/parent") // /parent
70+
.middleware(TestMiddleware::with_header_name("X-Parent", "Parent"))
71+
.get(echo_path);
72+
app.at("/parent/child") // /parent/child, not nested
73+
.middleware(TestMiddleware::with_header_name("X-Child", "child"))
74+
.get(echo_path);
75+
let mut server = make_server(app.into_http_service()).unwrap();
76+
77+
let req = http::Request::get("/parent/child")
78+
.body(Body::empty())
79+
.unwrap();
80+
let res = server.simulate(req).unwrap();
81+
assert_eq!(res.headers().get("X-Parent"), None);
7282
assert_eq!(
73-
res.headers().get("X-Tide-Test"),
74-
Some(&"bar".parse().unwrap())
83+
res.headers().get("X-Child"),
84+
Some(&"child".parse().unwrap())
7585
);
76-
assert_eq!(res.status(), 200);
77-
block_on(res.into_body().read_to_end(&mut buf)).unwrap();
78-
assert_eq!(&*buf, &*b"/foo/bar");
7986
}

0 commit comments

Comments
 (0)