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