Skip to content

Commit ff5f57e

Browse files
committed
Update Next to use cursors with Arc references
- Removes for<'a> and <'_> &'a lifetimes on Next - Changes all references to endpoints and middleware to use Arc<T> - Updates selection routing to return Arc handlers instead of Boxed - Simplfy server respond to pass along endpoint and middleware
1 parent 49d7a6d commit ff5f57e

File tree

13 files changed

+64
-72
lines changed

13 files changed

+64
-72
lines changed

examples/middleware.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ impl UserDatabase {
2525
// This is an example of a function middleware that uses the
2626
// application state. Because it depends on a specific request state,
2727
// it would likely be closely tied to a specific application
28-
fn user_loader<'a>(
29-
mut request: Request,
30-
next: Next<'a>,
31-
) -> Pin<Box<dyn Future<Output = Result> + Send + 'a>> {
28+
fn user_loader(mut request: Request, next: Next) -> Pin<Box<dyn Future<Output = Result> + Send>> {
3229
Box::pin(async {
3330
if let Some(user) = request.state().find_user().await {
3431
tide::log::trace!("user loaded", {user: user.name});
@@ -62,7 +59,7 @@ struct RequestCount(usize);
6259

6360
#[tide::utils::async_trait]
6461
impl Middleware for RequestCounterMiddleware {
65-
async fn handle(&self, mut req: Request, next: Next<'_>) -> Result {
62+
async fn handle(&self, mut req: Request, next: Next) -> Result {
6663
let count = self.requests_counted.fetch_add(1, Ordering::Relaxed);
6764
tide::log::trace!("request counter", { count: count });
6865
req.set_ext(RequestCount(count));

src/cookies/middleware.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl CookiesMiddleware {
3535
}
3636

3737
#[async_trait]
38-
impl<State: Clone + Send + Sync + 'static> Middleware<State> for CookiesMiddleware {
39-
async fn handle(&self, mut ctx: Request, next: Next<'_, State>) -> crate::Result {
38+
impl Middleware for CookiesMiddleware {
39+
async fn handle(&self, mut ctx: Request, next: Next) -> crate::Result {
4040
let cookie_jar = if let Some(cookie_data) = ctx.ext::<CookieData>() {
4141
cookie_data.content.clone()
4242
} else {

src/endpoint.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ where
6767
}
6868

6969
pub(crate) struct MiddlewareEndpoint<E> {
70-
endpoint: E,
71-
middleware: Vec<Arc<dyn Middleware>>,
70+
endpoint: Arc<E>,
71+
middleware: Arc<Vec<Arc<dyn Middleware>>>,
7272
}
7373

7474
impl<E: Clone> Clone for MiddlewareEndpoint<E> {
@@ -96,14 +96,14 @@ where
9696
{
9797
pub(crate) fn wrap_with_middleware(
9898
ep: E,
99-
middleware: &[Arc<dyn Middleware>],
100-
) -> Box<dyn Endpoint + Send + Sync + 'static> {
99+
middleware: Vec<Arc<dyn Middleware>>,
100+
) -> Arc<dyn Endpoint + Send + Sync + 'static> {
101101
if middleware.is_empty() {
102-
Box::new(ep)
102+
Arc::new(ep)
103103
} else {
104-
Box::new(Self {
105-
endpoint: ep,
106-
middleware: middleware.to_vec(),
104+
Arc::new(Self {
105+
endpoint: Arc::new(ep),
106+
middleware: Arc::new(middleware),
107107
})
108108
}
109109
}
@@ -115,10 +115,7 @@ where
115115
E: Endpoint,
116116
{
117117
async fn call(&self, req: Request) -> crate::Result {
118-
let next = Next {
119-
endpoint: &self.endpoint,
120-
next_middleware: &self.middleware,
121-
};
118+
let next = Next::new(self.endpoint.clone(), self.middleware.clone());
122119
Ok(next.run(req).await)
123120
}
124121
}

src/log/middleware.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl LogMiddleware {
2626
}
2727

2828
/// Log a request and a response.
29-
async fn log<'a>(&'a self, mut req: Request, next: Next<'a>) -> crate::Result {
29+
async fn log(&self, mut req: Request, next: Next) -> crate::Result {
3030
if req.ext::<LogMiddlewareHasBeenRun>().is_some() {
3131
return Ok(next.run(req).await);
3232
}
@@ -91,7 +91,7 @@ impl LogMiddleware {
9191

9292
#[async_trait::async_trait]
9393
impl Middleware for LogMiddleware {
94-
async fn handle(&self, req: Request, next: Next<'_>) -> crate::Result {
94+
async fn handle(&self, req: Request, next: Next) -> crate::Result {
9595
self.log(req, next).await
9696
}
9797
}

src/middleware.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
33
use std::sync::Arc;
44

5-
use crate::endpoint::DynEndpoint;
6-
use crate::{Request, Response};
5+
use crate::{Endpoint, Request, Response};
76
use async_trait::async_trait;
87
use std::future::Future;
98
use std::pin::Pin;
@@ -12,7 +11,7 @@ use std::pin::Pin;
1211
#[async_trait]
1312
pub trait Middleware: Send + Sync + 'static {
1413
/// Asynchronously handle the request, and return a response.
15-
async fn handle(&self, request: Request, next: Next<'_>) -> crate::Result;
14+
async fn handle(&self, request: Request, next: Next) -> crate::Result;
1615

1716
/// Set the middleware's name. By default it uses the type signature.
1817
fn name(&self) -> &str {
@@ -26,32 +25,42 @@ where
2625
F: Send
2726
+ Sync
2827
+ 'static
29-
+ for<'a> Fn(Request, Next<'a>) -> Pin<Box<dyn Future<Output = crate::Result> + 'a + Send>>,
28+
+ Fn(Request, Next) -> Pin<Box<dyn Future<Output = crate::Result> + Send>>,
3029
{
31-
async fn handle(&self, req: Request, next: Next<'_>) -> crate::Result {
30+
async fn handle(&self, req: Request, next: Next) -> crate::Result {
3231
(self)(req, next).await
3332
}
3433
}
3534

3635
/// The remainder of a middleware chain, including the endpoint.
3736
#[allow(missing_debug_implementations)]
38-
pub struct Next<'a> {
39-
pub(crate) endpoint: &'a DynEndpoint,
40-
pub(crate) next_middleware: &'a [Arc<dyn Middleware>],
37+
pub struct Next {
38+
cursor: usize,
39+
endpoint: Arc<dyn Endpoint>,
40+
middleware: Arc<Vec<Arc<dyn Middleware>>>,
4141
}
4242

43-
impl Next<'_> {
43+
impl Next {
44+
/// Creates a new Next middleware with an arc to the endpoint and middleware
45+
pub fn new(endpoint: Arc<dyn Endpoint>, middleware: Arc<Vec<Arc<dyn Middleware>>>) -> Self {
46+
Self {
47+
cursor: 0,
48+
endpoint,
49+
middleware,
50+
}
51+
}
52+
4453
/// Asynchronously execute the remaining middleware chain.
4554
pub async fn run(mut self, req: Request) -> Response {
46-
if let Some((current, next)) = self.next_middleware.split_first() {
47-
self.next_middleware = next;
48-
match current.handle(req, self).await {
49-
Ok(request) => request,
55+
if let Some(mid) = self.middleware.get(self.cursor) {
56+
self.cursor += 1;
57+
match mid.to_owned().handle(req, self).await {
58+
Ok(response) => response,
5059
Err(err) => err.into(),
5160
}
5261
} else {
5362
match self.endpoint.call(req).await {
54-
Ok(request) => request,
63+
Ok(response) => response,
5564
Err(err) => err.into(),
5665
}
5766
}

src/route.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@ impl<'a> Route<'a> {
187187
wildcard.router.add(
188188
&wildcard.path,
189189
method,
190-
MiddlewareEndpoint::wrap_with_middleware(ep, &wildcard.middleware),
190+
MiddlewareEndpoint::wrap_with_middleware(ep, wildcard.middleware.clone()),
191191
);
192192
} else {
193193
self.router.add(
194194
&self.path,
195195
method,
196-
MiddlewareEndpoint::wrap_with_middleware(ep, &self.middleware),
196+
MiddlewareEndpoint::wrap_with_middleware(ep, self.middleware.clone()),
197197
);
198198
}
199199
self
@@ -208,12 +208,12 @@ impl<'a> Route<'a> {
208208
let wildcard = self.at("*");
209209
wildcard.router.add_all(
210210
&wildcard.path,
211-
MiddlewareEndpoint::wrap_with_middleware(ep, &wildcard.middleware),
211+
MiddlewareEndpoint::wrap_with_middleware(ep, wildcard.middleware.clone()),
212212
);
213213
} else {
214214
self.router.add_all(
215215
&self.path,
216-
MiddlewareEndpoint::wrap_with_middleware(ep, &self.middleware),
216+
MiddlewareEndpoint::wrap_with_middleware(ep, self.middleware.clone()),
217217
);
218218
}
219219
self

src/router.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use routefinder::{Captures, Router as MethodRouter};
22
use std::collections::HashMap;
3+
use std::sync::Arc;
34

45
use crate::endpoint::DynEndpoint;
56
use crate::{Request, Response, StatusCode};
@@ -10,8 +11,8 @@ use crate::{Request, Response, StatusCode};
1011
/// by the method first allows the table itself to be more efficient.
1112
#[allow(missing_debug_implementations)]
1213
pub(crate) struct Router {
13-
method_map: HashMap<http_types::Method, MethodRouter<Box<DynEndpoint>>>,
14-
all_method_router: MethodRouter<Box<DynEndpoint>>,
14+
method_map: HashMap<http_types::Method, MethodRouter<Arc<DynEndpoint>>>,
15+
all_method_router: MethodRouter<Arc<DynEndpoint>>,
1516
}
1617

1718
impl std::fmt::Debug for Router {
@@ -24,8 +25,8 @@ impl std::fmt::Debug for Router {
2425
}
2526

2627
/// The result of routing a URL
27-
pub(crate) struct Selection<'a> {
28-
pub(crate) endpoint: &'a DynEndpoint,
28+
pub(crate) struct Selection {
29+
pub(crate) endpoint: Arc<DynEndpoint>,
2930
pub(crate) params: Captures<'static, 'static>,
3031
}
3132

@@ -37,31 +38,31 @@ impl Router {
3738
}
3839
}
3940

40-
pub(crate) fn add(&mut self, path: &str, method: http_types::Method, ep: Box<DynEndpoint>) {
41+
pub(crate) fn add(&mut self, path: &str, method: http_types::Method, ep: Arc<DynEndpoint>) {
4142
self.method_map
4243
.entry(method)
4344
.or_insert_with(MethodRouter::new)
4445
.add(path, ep)
4546
.unwrap()
4647
}
4748

48-
pub(crate) fn add_all(&mut self, path: &str, ep: Box<DynEndpoint>) {
49+
pub(crate) fn add_all(&mut self, path: &str, ep: Arc<DynEndpoint>) {
4950
self.all_method_router.add(path, ep).unwrap()
5051
}
5152

52-
pub(crate) fn route(&self, path: &str, method: http_types::Method) -> Selection<'_> {
53+
pub(crate) fn route(&self, path: &str, method: http_types::Method) -> Selection {
5354
if let Some(m) = self
5455
.method_map
5556
.get(&method)
5657
.and_then(|r| r.best_match(path))
5758
{
5859
Selection {
59-
endpoint: m.handler(),
60+
endpoint: m.handler().to_owned(),
6061
params: m.captures().into_owned(),
6162
}
6263
} else if let Some(m) = self.all_method_router.best_match(path) {
6364
Selection {
64-
endpoint: m.handler(),
65+
endpoint: m.handler().to_owned(),
6566
params: m.captures().into_owned(),
6667
}
6768
} else if method == http_types::Method::Head {
@@ -78,12 +79,12 @@ impl Router {
7879
// If this `path` can be handled by a callback registered with a different HTTP method
7980
// should return 405 Method Not Allowed
8081
Selection {
81-
endpoint: &method_not_allowed,
82+
endpoint: Arc::new(method_not_allowed),
8283
params: Captures::default(),
8384
}
8485
} else {
8586
Selection {
86-
endpoint: &not_found_endpoint,
87+
endpoint: Arc::new(not_found_endpoint),
8788
params: Captures::default(),
8889
}
8990
}

src/security/cors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl CorsMiddleware {
137137

138138
#[async_trait::async_trait]
139139
impl Middleware for CorsMiddleware {
140-
async fn handle(&self, req: Request, next: Next<'_>) -> Result {
140+
async fn handle(&self, req: Request, next: Next) -> Result {
141141
// TODO: how should multiple origin values be handled?
142142
let origins = req.header(&headers::ORIGIN).cloned();
143143

src/server.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,7 @@ where
297297
let route_params = vec![params];
298298
let req = Request::with_state(state, req, route_params);
299299

300-
let next = Next {
301-
endpoint,
302-
next_middleware: &middleware,
303-
};
304-
300+
let next = Next::new(endpoint, middleware);
305301
let res = next.run(req).await;
306302
let res: http_types::Response = res.into();
307303
Ok(res.into())
@@ -357,11 +353,7 @@ impl<InnerState: Clone + Sync + Send + 'static> Endpoint for Server<InnerState>
357353
route_params.push(params);
358354
let req = Request::with_state(state, req, route_params);
359355

360-
let next = Next {
361-
endpoint,
362-
next_middleware: &middleware,
363-
};
364-
356+
let next = Next::new(endpoint, middleware);
365357
Ok(next.run(req).await)
366358
}
367359
}

src/sessions/middleware.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ where
7979
Store: SessionStore,
8080
State: Clone + Send + Sync + 'static,
8181
{
82-
async fn handle(&self, mut request: Request, next: Next<'_, State>) -> crate::Result {
82+
async fn handle(&self, mut request: Request, next: Next) -> crate::Result {
8383
let cookie = request.cookie(&self.cookie_name);
8484
let cookie_value = cookie
8585
.clone()

0 commit comments

Comments
 (0)