diff --git a/src/service/service.rs b/src/service/service.rs index b5de9bec20..005406f982 100644 --- a/src/service/service.rs +++ b/src/service/service.rs @@ -28,5 +28,13 @@ pub trait Service { type Future: Future>; /// Process the request and return the response asynchronously. - fn call(&mut self, req: Request) -> Self::Future; + /// call takes a &self instead of a mut &self because: + /// - It prepares the way for async fn, + /// since then the future only borrows &self, and thus a Service can concurrently handle + /// multiple outstanding requests at once. + /// - It's clearer that Services can likely be cloned + /// - To share state across clones you generally need Arc> + /// that means you're not really using the &mut self and could do with a &self + /// To see the discussion on this see: https://github.com/hyperium/hyper/issues/3040 + fn call(&self, req: Request) -> Self::Future; } diff --git a/src/service/util.rs b/src/service/util.rs index 1d8587fe82..710ba53543 100644 --- a/src/service/util.rs +++ b/src/service/util.rs @@ -29,7 +29,7 @@ use crate::{Request, Response}; /// ``` pub fn service_fn(f: F) -> ServiceFn where - F: FnMut(Request) -> S, + F: Fn(Request) -> S, S: Future, { ServiceFn { @@ -46,7 +46,7 @@ pub struct ServiceFn { impl Service> for ServiceFn where - F: FnMut(Request) -> Ret, + F: Fn(Request) -> Ret, ReqBody: Body, Ret: Future, E>>, E: Into>, @@ -56,7 +56,7 @@ where type Error = E; type Future = Ret; - fn call(&mut self, req: Request) -> Self::Future { + fn call(&self, req: Request) -> Self::Future { (self.f)(req) } }