• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::util::BoxService;
2 use std::{fmt, sync::Arc};
3 use tower_layer::{layer_fn, Layer};
4 use tower_service::Service;
5 
6 /// A boxed [`Layer`] trait object.
7 ///
8 /// [`BoxLayer`] turns a layer into a trait object, allowing both the [`Layer`] itself
9 /// and the output [`Service`] to be dynamic, while having consistent types.
10 ///
11 /// This [`Layer`] produces [`BoxService`] instances erasing the type of the
12 /// [`Service`] produced by the wrapped [`Layer`].
13 ///
14 /// # Example
15 ///
16 /// `BoxLayer` can, for example, be useful to create layers dynamically that otherwise wouldn't have
17 /// the same types. In this example, we include a [`Timeout`] layer
18 /// only if an environment variable is set. We can use `BoxLayer`
19 /// to return a consistent type regardless of runtime configuration:
20 ///
21 /// ```
22 /// use std::time::Duration;
23 /// use tower::{Service, ServiceBuilder, BoxError, util::BoxLayer};
24 ///
25 /// fn common_layer<S, T>() -> BoxLayer<S, T, S::Response, BoxError>
26 /// where
27 ///     S: Service<T> + Send + 'static,
28 ///     S::Future: Send + 'static,
29 ///     S::Error: Into<BoxError> + 'static,
30 /// {
31 ///     let builder = ServiceBuilder::new()
32 ///         .concurrency_limit(100);
33 ///
34 ///     if std::env::var("SET_TIMEOUT").is_ok() {
35 ///         let layer = builder
36 ///             .timeout(Duration::from_secs(30))
37 ///             .into_inner();
38 ///
39 ///         BoxLayer::new(layer)
40 ///     } else {
41 ///         let layer = builder
42 ///             .map_err(Into::into)
43 ///             .into_inner();
44 ///
45 ///         BoxLayer::new(layer)
46 ///     }
47 /// }
48 /// ```
49 ///
50 /// [`Layer`]: tower_layer::Layer
51 /// [`Service`]: tower_service::Service
52 /// [`BoxService`]: super::BoxService
53 /// [`Timeout`]: crate::timeout
54 pub struct BoxLayer<In, T, U, E> {
55     boxed: Arc<dyn Layer<In, Service = BoxService<T, U, E>> + Send + Sync + 'static>,
56 }
57 
58 impl<In, T, U, E> BoxLayer<In, T, U, E> {
59     /// Create a new [`BoxLayer`].
new<L>(inner_layer: L) -> Self where L: Layer<In> + Send + Sync + 'static, L::Service: Service<T, Response = U, Error = E> + Send + 'static, <L::Service as Service<T>>::Future: Send + 'static,60     pub fn new<L>(inner_layer: L) -> Self
61     where
62         L: Layer<In> + Send + Sync + 'static,
63         L::Service: Service<T, Response = U, Error = E> + Send + 'static,
64         <L::Service as Service<T>>::Future: Send + 'static,
65     {
66         let layer = layer_fn(move |inner: In| {
67             let out = inner_layer.layer(inner);
68             BoxService::new(out)
69         });
70 
71         Self {
72             boxed: Arc::new(layer),
73         }
74     }
75 }
76 
77 impl<In, T, U, E> Layer<In> for BoxLayer<In, T, U, E> {
78     type Service = BoxService<T, U, E>;
79 
layer(&self, inner: In) -> Self::Service80     fn layer(&self, inner: In) -> Self::Service {
81         self.boxed.layer(inner)
82     }
83 }
84 
85 impl<In, T, U, E> Clone for BoxLayer<In, T, U, E> {
clone(&self) -> Self86     fn clone(&self) -> Self {
87         Self {
88             boxed: Arc::clone(&self.boxed),
89         }
90     }
91 }
92 
93 impl<In, T, U, E> fmt::Debug for BoxLayer<In, T, U, E> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result94     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
95         fmt.debug_struct("BoxLayer").finish()
96     }
97 }
98