1 | use super::ServiceExt; |
2 | use futures_util::future::BoxFuture; |
3 | use std::{ |
4 | fmt, |
5 | task::{Context, Poll}, |
6 | }; |
7 | use tower_layer::{layer_fn, LayerFn}; |
8 | use tower_service::Service; |
9 | |
10 | /// A [`Clone`] + [`Send`] boxed [`Service`]. |
11 | /// |
12 | /// [`BoxCloneService`] turns a service into a trait object, allowing the |
13 | /// response future type to be dynamic, and allowing the service to be cloned. |
14 | /// |
15 | /// This is similar to [`BoxService`](super::BoxService) except the resulting |
16 | /// service implements [`Clone`]. |
17 | /// |
18 | /// # Example |
19 | /// |
20 | /// ``` |
21 | /// use tower::{Service, ServiceBuilder, BoxError, util::BoxCloneService}; |
22 | /// use std::time::Duration; |
23 | /// # |
24 | /// # struct Request; |
25 | /// # struct Response; |
26 | /// # impl Response { |
27 | /// # fn new() -> Self { Self } |
28 | /// # } |
29 | /// |
30 | /// // This service has a complex type that is hard to name |
31 | /// let service = ServiceBuilder::new() |
32 | /// .map_request(|req| { |
33 | /// println!("received request" ); |
34 | /// req |
35 | /// }) |
36 | /// .map_response(|res| { |
37 | /// println!("response produced" ); |
38 | /// res |
39 | /// }) |
40 | /// .load_shed() |
41 | /// .concurrency_limit(64) |
42 | /// .timeout(Duration::from_secs(10)) |
43 | /// .service_fn(|req: Request| async { |
44 | /// Ok::<_, BoxError>(Response::new()) |
45 | /// }); |
46 | /// # let service = assert_service(service); |
47 | /// |
48 | /// // `BoxCloneService` will erase the type so it's nameable |
49 | /// let service: BoxCloneService<Request, Response, BoxError> = BoxCloneService::new(service); |
50 | /// # let service = assert_service(service); |
51 | /// |
52 | /// // And we can still clone the service |
53 | /// let cloned_service = service.clone(); |
54 | /// # |
55 | /// # fn assert_service<S, R>(svc: S) -> S |
56 | /// # where S: Service<R> { svc } |
57 | /// ``` |
58 | pub struct BoxCloneService<T, U, E>( |
59 | Box< |
60 | dyn CloneService<T, Response = U, Error = E, Future = BoxFuture<'static, Result<U, E>>> |
61 | + Send, |
62 | >, |
63 | ); |
64 | |
65 | impl<T, U, E> BoxCloneService<T, U, E> { |
66 | /// Create a new `BoxCloneService`. |
67 | pub fn new<S>(inner: S) -> Self |
68 | where |
69 | S: Service<T, Response = U, Error = E> + Clone + Send + 'static, |
70 | S::Future: Send + 'static, |
71 | { |
72 | let inner: MapFuture …> = inner.map_future(|f: impl Send + 'static| Box::pin(f) as _); |
73 | BoxCloneService(Box::new(inner)) |
74 | } |
75 | |
76 | /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxCloneService`] |
77 | /// middleware. |
78 | /// |
79 | /// [`Layer`]: crate::Layer |
80 | pub fn layer<S>() -> LayerFn<fn(S) -> Self> |
81 | where |
82 | S: Service<T, Response = U, Error = E> + Clone + Send + 'static, |
83 | S::Future: Send + 'static, |
84 | { |
85 | layer_fn(Self::new) |
86 | } |
87 | } |
88 | |
89 | impl<T, U, E> Service<T> for BoxCloneService<T, U, E> { |
90 | type Response = U; |
91 | type Error = E; |
92 | type Future = BoxFuture<'static, Result<U, E>>; |
93 | |
94 | #[inline ] |
95 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { |
96 | self.0.poll_ready(cx) |
97 | } |
98 | |
99 | #[inline ] |
100 | fn call(&mut self, request: T) -> Self::Future { |
101 | self.0.call(req:request) |
102 | } |
103 | } |
104 | |
105 | impl<T, U, E> Clone for BoxCloneService<T, U, E> { |
106 | fn clone(&self) -> Self { |
107 | Self(self.0.clone_box()) |
108 | } |
109 | } |
110 | |
111 | trait CloneService<R>: Service<R> { |
112 | fn clone_box( |
113 | &self, |
114 | ) -> Box< |
115 | dyn CloneService<R, Response = Self::Response, Error = Self::Error, Future = Self::Future> |
116 | + Send, |
117 | >; |
118 | } |
119 | |
120 | impl<R, T> CloneService<R> for T |
121 | where |
122 | T: Service<R> + Send + Clone + 'static, |
123 | { |
124 | fn clone_box( |
125 | &self, |
126 | ) -> Box<dyn CloneService<R, Response = T::Response, Error = T::Error, Future = T::Future> + Send> |
127 | { |
128 | Box::new(self.clone()) |
129 | } |
130 | } |
131 | |
132 | impl<T, U, E> fmt::Debug for BoxCloneService<T, U, E> { |
133 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
134 | fmt.debug_struct(name:"BoxCloneService" ).finish() |
135 | } |
136 | } |
137 | |