Skip to content

Commit aa5af79

Browse files
committed
Make Endpoint::call generic over lifetime
1 parent b429110 commit aa5af79

File tree

6 files changed

+28
-43
lines changed

6 files changed

+28
-43
lines changed

src/endpoint.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,19 @@ use crate::{response::IntoResponse, Request, Response};
4646
///
4747
/// Tide routes will also accept endpoints with `Fn` signatures of this form, but using the `async` keyword has better ergonomics.
4848
pub trait Endpoint<State>: Send + Sync + 'static {
49-
/// The async result of `call`.
50-
type Fut: Future<Output = Response> + Send + 'static;
51-
5249
/// Invoke the endpoint within the given context
53-
fn call(&self, req: Request<State>) -> Self::Fut;
50+
fn call<'a>(&'a self, req: Request<State>) -> BoxFuture<'a, Response>;
5451
}
5552

56-
pub(crate) type DynEndpoint<State> =
57-
dyn (Fn(Request<State>) -> BoxFuture<'static, Response>) + 'static + Send + Sync;
53+
pub(crate) type DynEndpoint<State> = dyn Endpoint<State>;
5854

5955
impl<State, F: Send + Sync + 'static, Fut> Endpoint<State> for F
6056
where
6157
F: Fn(Request<State>) -> Fut,
6258
Fut: Future + Send + 'static,
6359
Fut::Output: IntoResponse,
6460
{
65-
type Fut = BoxFuture<'static, Response>;
66-
fn call(&self, req: Request<State>) -> Self::Fut {
61+
fn call<'a>(&'a self, req: Request<State>) -> BoxFuture<'a, Response> {
6762
let fut = (self)(req);
6863
Box::pin(async move { fut.await.into_response() })
6964
}

src/middleware/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'a, State: 'static> Next<'a, State> {
5252
self.next_middleware = next;
5353
current.handle(req, self)
5454
} else {
55-
(self.endpoint)(req)
55+
self.endpoint.call(req)
5656
}
5757
}
5858
}

src/redirect.rs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use async_std::future;
2-
use async_std::task::{Context, Poll};
3-
4-
use std::pin::Pin;
5-
1+
use crate::utils::BoxFuture;
62
use crate::{Endpoint, Request, Response};
73

84
/// Redirect a route to another route.
@@ -21,7 +17,7 @@ use crate::{Endpoint, Request, Response};
2117
/// app.listen("127.0.0.1:8080").await?;
2218
/// #
2319
/// # Ok(()) }) }
24-
/// ````
20+
/// ```
2521
pub fn redirect<State>(location: impl AsRef<str>) -> impl Endpoint<State> {
2622
let location = location.as_ref().to_owned();
2723
Redirect { location }
@@ -33,22 +29,8 @@ pub struct Redirect {
3329
}
3430

3531
impl<State> Endpoint<State> for Redirect {
36-
type Fut = Future;
37-
38-
fn call(&self, _req: Request<State>) -> Self::Fut {
32+
fn call<'a>(&'a self, _req: Request<State>) -> BoxFuture<'a, Response> {
3933
let res = Response::new(307).set_header("Location", &self.location);
40-
Future { res: Some(res) }
41-
}
42-
}
43-
44-
/// Future returned from `redirect`.
45-
pub struct Future {
46-
res: Option<Response>,
47-
}
48-
49-
impl future::Future for Future {
50-
type Output = Response;
51-
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
52-
Poll::Ready(self.res.take().unwrap())
34+
Box::pin(async move { res })
5335
}
5436
}

src/router.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ impl<State: 'static> Router<State> {
3333
self.method_map
3434
.entry(method)
3535
.or_insert_with(MethodRouter::new)
36-
.add(path, Box::new(move |cx| Box::pin(ep.call(cx))))
36+
.add(path, Box::new(ep))
3737
}
3838

3939
pub(crate) fn add_all(&mut self, path: &str, ep: impl Endpoint<State>) {
4040
self.all_method_router
41-
.add(path, Box::new(move |cx| Box::pin(ep.call(cx))))
41+
.add(path, Box::new(ep))
4242
}
4343

4444
pub(crate) fn route(&self, path: &str, method: http::Method) -> Selection<'_, State> {

src/server/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,23 @@ impl<State: Send + Sync + 'static> Server<State> {
321321
///
322322
/// This type is useful only in conjunction with the [`HttpService`] trait,
323323
/// i.e. for hosting a Tide app within some custom HTTP server.
324-
#[derive(Clone)]
325324
#[allow(missing_debug_implementations)]
326325
pub struct Service<State> {
327326
router: Arc<Router<State>>,
328327
state: Arc<State>,
329328
middleware: Arc<Vec<Arc<dyn Middleware<State>>>>,
330329
}
331330

331+
impl<State> Clone for Service<State> {
332+
fn clone(&self) -> Self {
333+
Self {
334+
router: self.router.clone(),
335+
state: self.state.clone(),
336+
middleware: self.middleware.clone(),
337+
}
338+
}
339+
}
340+
332341
#[derive(Debug)]
333342
pub struct ReadyFuture;
334343

@@ -351,17 +360,17 @@ impl<State: Sync + Send + 'static> HttpService for Service<State> {
351360

352361
fn respond(&self, _conn: &mut (), req: http_service::Request) -> Self::ResponseFuture {
353362
let req = Request::new(self.state.clone(), req, Vec::new());
354-
let fut = self.call(req);
355-
Box::pin(async move { Ok(fut.await.into()) })
363+
let service = self.clone();
364+
Box::pin(async move {
365+
Ok(service.call(req).await.into())
366+
})
356367
}
357368
}
358369

359370
impl<State: Sync + Send + 'static, InnerState: Sync + Send + 'static> Endpoint<State>
360371
for Service<InnerState>
361372
{
362-
type Fut = BoxFuture<'static, Response>;
363-
364-
fn call(&self, req: Request<State>) -> Self::Fut {
373+
fn call<'a>(&'a self, req: Request<State>) -> BoxFuture<'a, Response> {
365374
let Request {
366375
request: req,
367376
mut route_params,

src/server/route.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::{router::Router, Endpoint};
1+
use crate::utils::BoxFuture;
2+
use crate::{router::Router, Endpoint, Response};
23

34
/// A handle to a route.
45
///
@@ -172,9 +173,7 @@ impl<E> Clone for StripPrefixEndpoint<E> {
172173
}
173174

174175
impl<State, E: Endpoint<State>> Endpoint<State> for StripPrefixEndpoint<E> {
175-
type Fut = E::Fut;
176-
177-
fn call(&self, mut req: crate::Request<State>) -> Self::Fut {
176+
fn call<'a>(&'a self, mut req: crate::Request<State>) -> BoxFuture<'a, Response> {
178177
let rest = req.rest().unwrap_or("");
179178
let mut path_and_query = format!("/{}", rest);
180179
let uri = req.uri();

0 commit comments

Comments
 (0)