hyper/service/
service.rs

1use std::future::Future;
2
3/// An asynchronous function from a `Request` to a `Response`.
4///
5/// The `Service` trait is a simplified interface making it easy to write
6/// network applications in a modular and reusable way, decoupled from the
7/// underlying protocol.
8///
9/// # Functional
10///
11/// A `Service` is a function of a `Request`. It immediately returns a
12/// `Future` representing the eventual completion of processing the
13/// request. The actual request processing may happen at any time in the
14/// future, on any thread or executor. The processing may depend on calling
15/// other services. At some point in the future, the processing will complete,
16/// and the `Future` will resolve to a response or error.
17///
18/// At a high level, the `Service::call` function represents an RPC request. The
19/// `Service` value can be a server or a client.
20pub trait Service<Request> {
21    /// Responses given by the service.
22    type Response;
23
24    /// Errors produced by the service.
25    ///
26    /// Note: Returning an `Error` to a hyper server, the behavior depends on the
27    /// protocol. In most cases, hyper will cause the connection to be abruptly aborted.
28    /// It will abort the request however the protocol allows, either with some sort of RST_STREAM,
29    /// or killing the connection if that doesn't exist.
30    type Error;
31
32    /// The future response value.
33    type Future: Future<Output = Result<Self::Response, Self::Error>>;
34
35    /// Process the request and return the response asynchronously.
36    /// `call` takes `&self` instead of `mut &self` because:
37    /// - It prepares the way for async fn,
38    ///   since then the future only borrows `&self`, and thus a Service can concurrently handle
39    ///   multiple outstanding requests at once.
40    /// - It's clearer that Services can likely be cloned
41    /// - To share state across clones, you generally need `Arc<Mutex<_>>`
42    ///   That means you're not really using the `&mut self` and could do with a `&self`.
43    ///   The discussion on this is here: <https://github.com/hyperium/hyper/issues/3040>
44    fn call(&self, req: Request) -> Self::Future;
45}
46
47impl<Request, S: Service<Request> + ?Sized> Service<Request> for &'_ S {
48    type Response = S::Response;
49    type Error = S::Error;
50    type Future = S::Future;
51
52    #[inline]
53    fn call(&self, req: Request) -> Self::Future {
54        (**self).call(req)
55    }
56}
57
58impl<Request, S: Service<Request> + ?Sized> Service<Request> for &'_ mut S {
59    type Response = S::Response;
60    type Error = S::Error;
61    type Future = S::Future;
62
63    #[inline]
64    fn call(&self, req: Request) -> Self::Future {
65        (**self).call(req)
66    }
67}
68
69impl<Request, S: Service<Request> + ?Sized> Service<Request> for Box<S> {
70    type Response = S::Response;
71    type Error = S::Error;
72    type Future = S::Future;
73
74    #[inline]
75    fn call(&self, req: Request) -> Self::Future {
76        (**self).call(req)
77    }
78}
79
80impl<Request, S: Service<Request> + ?Sized> Service<Request> for std::rc::Rc<S> {
81    type Response = S::Response;
82    type Error = S::Error;
83    type Future = S::Future;
84
85    #[inline]
86    fn call(&self, req: Request) -> Self::Future {
87        (**self).call(req)
88    }
89}
90
91impl<Request, S: Service<Request> + ?Sized> Service<Request> for std::sync::Arc<S> {
92    type Response = S::Response;
93    type Error = S::Error;
94    type Future = S::Future;
95
96    #[inline]
97    fn call(&self, req: Request) -> Self::Future {
98        (**self).call(req)
99    }
100}