1 | use 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. |
20 | pub 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 | |
47 | impl<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 | |
58 | impl<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 | |
69 | impl<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 | |
80 | impl<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 | |
91 | impl<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 | } |
101 | |