Skip to content

Commit e21b4ed

Browse files
committed
Refactor selection/routing to just use Next as an endpoint
1 parent dc75e00 commit e21b4ed

File tree

5 files changed

+65
-99
lines changed

5 files changed

+65
-99
lines changed

src/endpoint.rs

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use async_std::future::Future;
2-
use async_std::sync::Arc;
32
use async_trait::async_trait;
43
use http_types::Result;
54

6-
use crate::middleware::Next;
7-
use crate::{Middleware, Request, Response};
5+
use crate::{Request, Response};
86

97
/// An HTTP request handler.
108
///
@@ -50,8 +48,6 @@ pub trait Endpoint: Send + Sync + 'static {
5048
async fn call(&self, req: Request) -> crate::Result;
5149
}
5250

53-
pub(crate) type DynEndpoint = dyn Endpoint;
54-
5551
#[async_trait]
5652
impl<F, Fut, Res> Endpoint for F
5753
where
@@ -66,60 +62,6 @@ where
6662
}
6763
}
6864

69-
pub(crate) struct MiddlewareEndpoint<E> {
70-
endpoint: Arc<E>,
71-
middleware: Arc<Vec<Arc<dyn Middleware>>>,
72-
}
73-
74-
impl<E: Clone> Clone for MiddlewareEndpoint<E> {
75-
fn clone(&self) -> Self {
76-
Self {
77-
endpoint: self.endpoint.clone(),
78-
middleware: self.middleware.clone(),
79-
}
80-
}
81-
}
82-
83-
impl<E> std::fmt::Debug for MiddlewareEndpoint<E> {
84-
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85-
write!(
86-
fmt,
87-
"MiddlewareEndpoint (length: {})",
88-
self.middleware.len(),
89-
)
90-
}
91-
}
92-
93-
impl<E> MiddlewareEndpoint<E>
94-
where
95-
E: Endpoint,
96-
{
97-
pub(crate) fn wrap_with_middleware(
98-
ep: E,
99-
middleware: Vec<Arc<dyn Middleware>>,
100-
) -> Arc<dyn Endpoint + Send + Sync + 'static> {
101-
if middleware.is_empty() {
102-
Arc::new(ep)
103-
} else {
104-
Arc::new(Self {
105-
endpoint: Arc::new(ep),
106-
middleware: Arc::new(middleware),
107-
})
108-
}
109-
}
110-
}
111-
112-
#[async_trait]
113-
impl<E> Endpoint for MiddlewareEndpoint<E>
114-
where
115-
E: Endpoint,
116-
{
117-
async fn call(&self, req: Request) -> crate::Result {
118-
let next = Next::new(self.endpoint.clone(), self.middleware.clone());
119-
Ok(next.run(req).await)
120-
}
121-
}
122-
12365
#[async_trait]
12466
impl Endpoint for Box<dyn Endpoint> {
12567
async fn call(&self, request: Request) -> crate::Result {

src/middleware.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,28 @@ pub struct Next {
4242

4343
impl Next {
4444
/// 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 {
45+
pub fn new(endpoint: impl Endpoint, middleware: Vec<Arc<dyn Middleware>>) -> Self {
4646
Self {
4747
cursor: 0,
48-
endpoint,
48+
endpoint: Arc::new(endpoint),
49+
middleware: Arc::new(middleware),
50+
}
51+
}
52+
53+
/// Creates a new Next middleware from the given endpoint with empty middleware
54+
pub fn from_endpoint(endpoint: impl Endpoint) -> Self {
55+
Self {
56+
cursor: 0,
57+
endpoint: Arc::new(endpoint),
58+
middleware: Arc::default(),
59+
}
60+
}
61+
62+
/// Creates a new Next middleware from an existing next middleware (as an endpoint)
63+
pub fn from_next(endpoint: Next, middleware: Arc<Vec<Arc<dyn Middleware>>>) -> Self {
64+
Self {
65+
cursor: 0,
66+
endpoint: Arc::new(endpoint),
4967
middleware,
5068
}
5169
}
@@ -66,3 +84,22 @@ impl Next {
6684
}
6785
}
6886
}
87+
88+
#[async_trait]
89+
impl Endpoint for Next {
90+
async fn call(&self, req: Request) -> crate::Result {
91+
let next = self.clone();
92+
let response = next.run(req).await;
93+
Ok(response)
94+
}
95+
}
96+
97+
impl Clone for Next {
98+
fn clone(&self) -> Self {
99+
Next {
100+
cursor: 0,
101+
endpoint: self.endpoint.clone(),
102+
middleware: self.middleware.clone(),
103+
}
104+
}
105+
}

src/route.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ use std::io;
33
use std::path::Path;
44
use std::sync::Arc;
55

6-
use crate::endpoint::MiddlewareEndpoint;
76
use crate::fs::{ServeDir, ServeFile};
8-
use crate::log;
7+
use crate::{log, Next};
98
use crate::{router::Router, Endpoint, Middleware};
109

1110
/// A handle to a route.
@@ -178,17 +177,11 @@ impl<'a> Route<'a> {
178177
if self.prefix {
179178
let ep = StripPrefixEndpoint::new(ep);
180179
let wildcard = self.at("*");
181-
wildcard.router.add(
182-
&wildcard.path,
183-
method,
184-
MiddlewareEndpoint::wrap_with_middleware(ep, wildcard.middleware.clone()),
185-
);
180+
let next = Next::new(ep, wildcard.middleware.clone());
181+
wildcard.router.add(&wildcard.path, method, next);
186182
} else {
187-
self.router.add(
188-
&self.path,
189-
method,
190-
MiddlewareEndpoint::wrap_with_middleware(ep, self.middleware.clone()),
191-
);
183+
let next = Next::new(ep, self.middleware.clone());
184+
self.router.add(&self.path, method, next);
192185
}
193186
self
194187
}
@@ -200,15 +193,11 @@ impl<'a> Route<'a> {
200193
if self.prefix {
201194
let ep = StripPrefixEndpoint::new(ep);
202195
let wildcard = self.at("*");
203-
wildcard.router.add_all(
204-
&wildcard.path,
205-
MiddlewareEndpoint::wrap_with_middleware(ep, wildcard.middleware.clone()),
206-
);
196+
let next = Next::new(ep, wildcard.middleware.clone());
197+
wildcard.router.add_all(&wildcard.path, next);
207198
} else {
208-
self.router.add_all(
209-
&self.path,
210-
MiddlewareEndpoint::wrap_with_middleware(ep, self.middleware.clone()),
211-
);
199+
let next = Next::new(ep, self.middleware.clone());
200+
self.router.add_all(&self.path, next);
212201
}
213202
self
214203
}

src/router.rs

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

5-
use crate::endpoint::DynEndpoint;
6-
use crate::{Request, Response, StatusCode};
4+
use crate::{Next, Request, Response, StatusCode};
75

86
/// The routing table used by `Server`
97
///
108
/// Internally, we have a separate state machine per http method; indexing
119
/// by the method first allows the table itself to be more efficient.
1210
#[allow(missing_debug_implementations)]
1311
pub(crate) struct Router {
14-
method_map: HashMap<http_types::Method, MethodRouter<Arc<DynEndpoint>>>,
15-
all_method_router: MethodRouter<Arc<DynEndpoint>>,
12+
method_map: HashMap<http_types::Method, MethodRouter<Next>>,
13+
all_method_router: MethodRouter<Next>,
1614
}
1715

1816
impl std::fmt::Debug for Router {
@@ -26,7 +24,7 @@ impl std::fmt::Debug for Router {
2624

2725
/// The result of routing a URL
2826
pub(crate) struct Selection {
29-
pub(crate) endpoint: Arc<DynEndpoint>,
27+
pub(crate) next: Next,
3028
pub(crate) params: Captures<'static, 'static>,
3129
}
3230

@@ -38,15 +36,15 @@ impl Router {
3836
}
3937
}
4038

41-
pub(crate) fn add(&mut self, path: &str, method: http_types::Method, ep: Arc<DynEndpoint>) {
39+
pub(crate) fn add(&mut self, path: &str, method: http_types::Method, ep: Next) {
4240
self.method_map
4341
.entry(method)
4442
.or_insert_with(MethodRouter::new)
4543
.add(path, ep)
4644
.unwrap()
4745
}
4846

49-
pub(crate) fn add_all(&mut self, path: &str, ep: Arc<DynEndpoint>) {
47+
pub(crate) fn add_all(&mut self, path: &str, ep: Next) {
5048
self.all_method_router.add(path, ep).unwrap()
5149
}
5250

@@ -57,12 +55,12 @@ impl Router {
5755
.and_then(|r| r.best_match(path))
5856
{
5957
Selection {
60-
endpoint: m.handler().to_owned(),
58+
next: m.handler().clone(),
6159
params: m.captures().into_owned(),
6260
}
6361
} else if let Some(m) = self.all_method_router.best_match(path) {
6462
Selection {
65-
endpoint: m.handler().to_owned(),
63+
next: m.handler().clone(),
6664
params: m.captures().into_owned(),
6765
}
6866
} else if method == http_types::Method::Head {
@@ -79,12 +77,12 @@ impl Router {
7977
// If this `path` can be handled by a callback registered with a different HTTP method
8078
// should return 405 Method Not Allowed
8179
Selection {
82-
endpoint: Arc::new(method_not_allowed),
80+
next: Next::from_endpoint(method_not_allowed),
8381
params: Captures::default(),
8482
}
8583
} else {
8684
Selection {
87-
endpoint: Arc::new(not_found_endpoint),
85+
next: Next::from_endpoint(not_found_endpoint),
8886
params: Captures::default(),
8987
}
9088
}

src/server.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use async_std::sync::Arc;
66
#[cfg(feature = "cookies")]
77
use crate::cookies;
88
use crate::listener::{Listener, ToListener};
9-
use crate::log;
10-
use crate::middleware::{Middleware, Next};
9+
use crate::middleware::Middleware;
1110
use crate::router::{Router, Selection};
1211
use crate::state::StateMiddleware;
12+
use crate::{log, Next};
1313
use crate::{Endpoint, Request, Route};
1414

1515
/// An HTTP server.
@@ -271,10 +271,10 @@ impl Server {
271271
let req = req.into();
272272

273273
let method = req.method().to_owned();
274-
let Selection { endpoint, params } = self.router.route(req.url().path(), method);
274+
let Selection { next, params } = self.router.route(req.url().path(), method);
275275
let route_params = vec![params];
276276
let req = Request::new(req, route_params);
277-
let next = Next::new(endpoint, self.middleware.clone());
277+
let next = Next::from_next(next, self.middleware.clone());
278278
let res = next.run(req).await;
279279
let res: http_types::Response = res.into();
280280
Ok(res.into())
@@ -307,10 +307,10 @@ impl Endpoint for Server {
307307
let path = req.url().path().to_owned();
308308
let method = req.method().to_owned();
309309

310-
let Selection { endpoint, params } = self.router.route(&path, method);
310+
let Selection { next, params } = self.router.route(&path, method);
311311
route_params.push(params);
312312
let req = Request::new(req, route_params);
313-
let next = Next::new(endpoint, self.middleware.clone());
313+
let next = Next::from_next(next, self.middleware.clone());
314314
Ok(next.run(req).await)
315315
}
316316
}

0 commit comments

Comments
 (0)