diff --git a/examples/middleware.rs b/examples/middleware.rs index 4e5c9b1e6..4eb139469 100644 --- a/examples/middleware.rs +++ b/examples/middleware.rs @@ -31,7 +31,7 @@ fn user_loader<'a>( if let Some(user) = request.state().find_user().await { tide::log::trace!("user loaded", {user: user.name}); request.set_ext(user); - next.run(request).await + Ok(next.run(request).await) // this middleware only needs to run before the endpoint, so // it just passes through the result of Next } else { @@ -71,7 +71,7 @@ impl Middleware for RequestCounterMiddlewar tide::log::trace!("request counter", { count: count }); req.set_ext(RequestCount(count)); - let mut res = next.run(req).await?; + let mut res = next.run(req).await; res.insert_header("request-number", count.to_string()); Ok(res) @@ -99,8 +99,7 @@ async fn main() -> Result<()> { tide::log::start(); let mut app = tide::with_state(UserDatabase::default()); - app.middleware(After(|result: Result| async move { - let response = result.unwrap_or_else(|e| Response::new(e.status())); + app.middleware(After(|response: Response| async move { match response.status() { StatusCode::NotFound => { let mut res = Response::new(404); diff --git a/src/cookies/middleware.rs b/src/cookies/middleware.rs index f713ae259..00b6eca17 100644 --- a/src/cookies/middleware.rs +++ b/src/cookies/middleware.rs @@ -49,7 +49,7 @@ impl Middleware for CookiesMiddleware { content }; - let mut res = next.run(ctx).await?; + let mut res = next.run(ctx).await; // Don't do anything if there are no cookies. if res.cookie_events.is_empty() { diff --git a/src/endpoint.rs b/src/endpoint.rs index b955362ed..c28dc09f8 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -44,16 +44,17 @@ use crate::{Middleware, Request, Response}; /// ``` /// /// Tide routes will also accept endpoints with `Fn` signatures of this form, but using the `async` keyword has better ergonomics. -pub trait Endpoint: Send + Sync + 'static { +pub trait Endpoint: Send + Sync + 'static { /// Invoke the endpoint within the given context fn call<'a>(&'a self, req: Request) -> BoxFuture<'a, crate::Result>; } pub(crate) type DynEndpoint = dyn Endpoint; -impl Endpoint for F +impl Endpoint for F where - F: Fn(Request) -> Fut, + State: Send + Sync + 'static, + F: Send + Sync + 'static + Fn(Request) -> Fut, Fut: Future> + Send + 'static, Res: Into, { @@ -92,6 +93,7 @@ impl std::fmt::Debug for MiddlewareEndpoint { impl MiddlewareEndpoint where + State: Send + Sync + 'static, E: Endpoint, { pub fn wrap_with_middleware(ep: E, middleware: &[Arc>]) -> Self { @@ -102,7 +104,7 @@ where } } -impl Endpoint for MiddlewareEndpoint +impl Endpoint for MiddlewareEndpoint where E: Endpoint, { @@ -111,6 +113,6 @@ where endpoint: &self.endpoint, next_middleware: &self.middleware, }; - next.run(req) + Box::pin(async move { Ok(next.run(req).await) }) } } diff --git a/src/fs/serve_dir.rs b/src/fs/serve_dir.rs index 5b213c618..6ba5a979f 100644 --- a/src/fs/serve_dir.rs +++ b/src/fs/serve_dir.rs @@ -17,7 +17,10 @@ impl ServeDir { } } -impl Endpoint for ServeDir { +impl Endpoint for ServeDir +where + State: Send + Sync + 'static, +{ fn call<'a>(&'a self, req: Request) -> BoxFuture<'a, Result> { let path = req.url().path(); let path = path.trim_start_matches(&self.prefix); diff --git a/src/log/middleware.rs b/src/log/middleware.rs index 0d0aabfd5..60cb5fa81 100644 --- a/src/log/middleware.rs +++ b/src/log/middleware.rs @@ -37,43 +37,31 @@ impl LogMiddleware { path: path, }); let start = std::time::Instant::now(); - match next.run(ctx).await { - Ok(res) => { - let status = res.status(); - if status.is_server_error() { - log::error!("--> Response sent", { - method: method, - path: path, - status: status as u16, - duration: format!("{:?}", start.elapsed()), - }); - } else if status.is_client_error() { - log::warn!("--> Response sent", { - method: method, - path: path, - status: status as u16, - duration: format!("{:?}", start.elapsed()), - }); - } else { - log::info!("--> Response sent", { - method: method, - path: path, - status: status as u16, - duration: format!("{:?}", start.elapsed()), - }); - } - Ok(res) - } - Err(err) => { - log::error!("{}", err.to_string(), { - method: method, - path: path, - status: err.status() as u16, - duration: format!("{:?}", start.elapsed()), - }); - Err(err) - } + let response = next.run(ctx).await; + let status = response.status(); + if status.is_server_error() { + log::error!("--> Response sent", { + method: method, + path: path, + status: status as u16, + duration: format!("{:?}", start.elapsed()), + }); + } else if status.is_client_error() { + log::warn!("--> Response sent", { + method: method, + path: path, + status: status as u16, + duration: format!("{:?}", start.elapsed()), + }); + } else { + log::info!("--> Response sent", { + method: method, + path: path, + status: status as u16, + duration: format!("{:?}", start.elapsed()), + }); } + Ok(response) } } diff --git a/src/middleware.rs b/src/middleware.rs index e6010c350..7e04a9dcc 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -75,8 +75,7 @@ where /// use tide::{After, Response, http}; /// /// let mut app = tide::new(); -/// app.middleware(After(|res: tide::Result| async move { -/// let res = res.unwrap_or_else(|e| Response::new(e.status())); +/// app.middleware(After(|res: Response| async move { /// match res.status() { /// http::StatusCode::NotFound => Ok("Page not found".into()), /// http::StatusCode::InternalServerError => Ok("Something went wrong".into()), @@ -98,8 +97,8 @@ where next: Next<'a, State>, ) -> BoxFuture<'a, crate::Result> { Box::pin(async move { - let result = next.run(request).await; - (self.0)(result).await + let response = next.run(request).await; + (self.0)(response).await }) } } @@ -127,10 +126,10 @@ pub struct Next<'a, State> { pub(crate) next_middleware: &'a [Arc>], } -impl<'a, State: 'static> Next<'a, State> { +impl<'a, State: 'static + Send + Sync> Next<'a, State> { /// Asynchronously execute the remaining middleware chain. #[must_use] - pub async fn run(mut self, req: Request) -> BoxFuture<'a, Response> { + pub fn run(mut self, req: Request) -> BoxFuture<'a, Response> { Box::pin(async move { if let Some((current, next)) = self.next_middleware.split_first() { self.next_middleware = next; @@ -138,6 +137,6 @@ impl<'a, State: 'static> Next<'a, State> { } else { self.endpoint.call(req).await.into() } - } + }) } } diff --git a/src/redirect.rs b/src/redirect.rs index 22120c84e..cc7e656b4 100644 --- a/src/redirect.rs +++ b/src/redirect.rs @@ -88,6 +88,7 @@ impl> Redirect { impl Endpoint for Redirect where + State: Send + Sync + 'static, T: AsRef + Send + Sync + 'static, { fn call<'a>(&'a self, _req: Request) -> BoxFuture<'a, crate::Result> { diff --git a/src/response.rs b/src/response.rs index 1c03cda1e..c5ba3c80d 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,7 +1,6 @@ use std::convert::TryInto; use std::fmt::Debug; use std::ops::Index; -use std::sync::Arc; use crate::http::cookies::Cookie; use crate::http::headers::{self, HeaderName, HeaderValues, ToHeaderValues}; @@ -36,16 +35,6 @@ impl Response { } } - /// Create a new instance from an `http_types::Error`. - #[must_use] - pub fn from_error(err: Error) -> Self { - let res = http::Response::from_error(err); - Self { - res, - cookie_events: vec![], - } - } - /// Returns the statuscode. #[must_use] pub fn status(&self) -> crate::StatusCode { @@ -220,7 +209,7 @@ impl Response { } /// Takes the `Error` from the response if one exists, replacing it with `None`. - pub fn take_error(&mut self) -> Option> { + pub fn take_error(&mut self) -> Option { self.res.take_error() } @@ -293,7 +282,8 @@ impl From for Response { impl From for Response { fn from(err: Error) -> Self { - Self::from_error(err) + let res: http::Response = err.into(); + res.into() } } diff --git a/src/route.rs b/src/route.rs index 4334bde80..8a0b662cf 100644 --- a/src/route.rs +++ b/src/route.rs @@ -29,7 +29,7 @@ pub struct Route<'a, State> { prefix: bool, } -impl<'a, State: 'static> Route<'a, State> { +impl<'a, State: 'static + Send + Sync> Route<'a, State> { pub(crate) fn new(router: &'a mut Router, path: String) -> Route<'a, State> { Route { router, @@ -274,7 +274,11 @@ impl Clone for StripPrefixEndpoint { } } -impl> Endpoint for StripPrefixEndpoint { +impl Endpoint for StripPrefixEndpoint +where + State: 'static + Send + Sync, + E: Endpoint, +{ fn call<'a>(&'a self, req: crate::Request) -> BoxFuture<'a, crate::Result> { let crate::Request { state, diff --git a/src/router.rs b/src/router.rs index e210c82aa..92b8a3f46 100644 --- a/src/router.rs +++ b/src/router.rs @@ -22,7 +22,7 @@ pub struct Selection<'a, State> { pub(crate) params: Params, } -impl Router { +impl Router { pub fn new() -> Self { Router { method_map: HashMap::default(), @@ -82,10 +82,14 @@ impl Router { } } -fn not_found_endpoint(_cx: Request) -> BoxFuture<'static, crate::Result> { +fn not_found_endpoint( + _cx: Request, +) -> BoxFuture<'static, crate::Result> { Box::pin(async move { Ok(Response::new(StatusCode::NotFound)) }) } -fn method_not_allowed(_cx: Request) -> BoxFuture<'static, crate::Result> { +fn method_not_allowed( + _cx: Request, +) -> BoxFuture<'static, crate::Result> { Box::pin(async move { Ok(Response::new(StatusCode::MethodNotAllowed)) }) } diff --git a/src/security/cors.rs b/src/security/cors.rs index f6fd16463..734fcb5ac 100644 --- a/src/security/cors.rs +++ b/src/security/cors.rs @@ -141,7 +141,7 @@ impl Middleware for CorsMiddleware { if origins.is_none() { // This is not a CORS request if there is no Origin header - return next.run(req).await; + return Ok(next.run(req).await); } let origins = origins.unwrap(); @@ -156,7 +156,7 @@ impl Middleware for CorsMiddleware { return Ok(self.build_preflight_response(&origins).into()); } - let mut response: http_types::Response = next.run(req).await?.into(); + let mut response: http_types::Response = next.run(req).await.into(); response.insert_header( headers::ACCESS_CONTROL_ALLOW_ORIGIN, diff --git a/src/server.rs b/src/server.rs index 1a2443c17..d6769ab6f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -454,8 +454,7 @@ impl Endpoint, ) -> BoxFuture<'a, tide::Result> { Box::pin(async move { - let mut res = next.run(req).await?; + let mut res = next.run(req).await; res.insert_header("X-Tide-Test", "1"); Ok(res) }) diff --git a/tests/route_middleware.rs b/tests/route_middleware.rs index 96f6ab568..e70471a75 100644 --- a/tests/route_middleware.rs +++ b/tests/route_middleware.rs @@ -23,7 +23,7 @@ impl Middleware for TestMiddleware { next: tide::Next<'a, State>, ) -> BoxFuture<'a, tide::Result> { Box::pin(async move { - let mut res = next.run(req).await?; + let mut res = next.run(req).await; res.insert_header(self.0.clone(), self.1); Ok(res) })