| 1 | #![warn ( |
| 2 | missing_debug_implementations, |
| 3 | missing_docs, |
| 4 | rust_2018_idioms, |
| 5 | unreachable_pub |
| 6 | )] |
| 7 | #![forbid (unsafe_code)] |
| 8 | // `rustdoc::broken_intra_doc_links` is checked on CI |
| 9 | |
| 10 | //! Layer traits and extensions. |
| 11 | //! |
| 12 | //! A layer decorates an service and provides additional functionality. It |
| 13 | //! allows other services to be composed with the service that implements layer. |
| 14 | //! |
| 15 | //! A middleware implements the [`Layer`] and [`Service`] trait. |
| 16 | //! |
| 17 | //! [`Service`]: https://docs.rs/tower/*/tower/trait.Service.html |
| 18 | |
| 19 | mod identity; |
| 20 | mod layer_fn; |
| 21 | mod stack; |
| 22 | mod tuple; |
| 23 | |
| 24 | pub use self::{ |
| 25 | identity::Identity, |
| 26 | layer_fn::{layer_fn, LayerFn}, |
| 27 | stack::Stack, |
| 28 | }; |
| 29 | |
| 30 | /// Decorates a [`Service`], transforming either the request or the response. |
| 31 | /// |
| 32 | /// Often, many of the pieces needed for writing network applications can be |
| 33 | /// reused across multiple services. The `Layer` trait can be used to write |
| 34 | /// reusable components that can be applied to very different kinds of services; |
| 35 | /// for example, it can be applied to services operating on different protocols, |
| 36 | /// and to both the client and server side of a network transaction. |
| 37 | /// |
| 38 | /// # Log |
| 39 | /// |
| 40 | /// Take request logging as an example: |
| 41 | /// |
| 42 | /// ```rust |
| 43 | /// # use tower_service::Service; |
| 44 | /// # use std::task::{Poll, Context}; |
| 45 | /// # use tower_layer::Layer; |
| 46 | /// # use std::fmt; |
| 47 | /// |
| 48 | /// pub struct LogLayer { |
| 49 | /// target: &'static str, |
| 50 | /// } |
| 51 | /// |
| 52 | /// impl<S> Layer<S> for LogLayer { |
| 53 | /// type Service = LogService<S>; |
| 54 | /// |
| 55 | /// fn layer(&self, service: S) -> Self::Service { |
| 56 | /// LogService { |
| 57 | /// target: self.target, |
| 58 | /// service |
| 59 | /// } |
| 60 | /// } |
| 61 | /// } |
| 62 | /// |
| 63 | /// // This service implements the Log behavior |
| 64 | /// pub struct LogService<S> { |
| 65 | /// target: &'static str, |
| 66 | /// service: S, |
| 67 | /// } |
| 68 | /// |
| 69 | /// impl<S, Request> Service<Request> for LogService<S> |
| 70 | /// where |
| 71 | /// S: Service<Request>, |
| 72 | /// Request: fmt::Debug, |
| 73 | /// { |
| 74 | /// type Response = S::Response; |
| 75 | /// type Error = S::Error; |
| 76 | /// type Future = S::Future; |
| 77 | /// |
| 78 | /// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
| 79 | /// self.service.poll_ready(cx) |
| 80 | /// } |
| 81 | /// |
| 82 | /// fn call(&mut self, request: Request) -> Self::Future { |
| 83 | /// // Insert log statement here or other functionality |
| 84 | /// println!("request = {:?}, target = {:?}" , request, self.target); |
| 85 | /// self.service.call(request) |
| 86 | /// } |
| 87 | /// } |
| 88 | /// ``` |
| 89 | /// |
| 90 | /// The above log implementation is decoupled from the underlying protocol and |
| 91 | /// is also decoupled from client or server concerns. In other words, the same |
| 92 | /// log middleware could be used in either a client or a server. |
| 93 | /// |
| 94 | /// [`Service`]: https://docs.rs/tower/*/tower/trait.Service.html |
| 95 | pub trait Layer<S> { |
| 96 | /// The wrapped service |
| 97 | type Service; |
| 98 | /// Wrap the given service with the middleware, returning a new service |
| 99 | /// that has been decorated with the middleware. |
| 100 | fn layer(&self, inner: S) -> Self::Service; |
| 101 | } |
| 102 | |
| 103 | impl<'a, T, S> Layer<S> for &'a T |
| 104 | where |
| 105 | T: ?Sized + Layer<S>, |
| 106 | { |
| 107 | type Service = T::Service; |
| 108 | |
| 109 | fn layer(&self, inner: S) -> Self::Service { |
| 110 | (**self).layer(inner) |
| 111 | } |
| 112 | } |
| 113 | |