1 | use super::Layer; |
2 | use std::fmt; |
3 | |
4 | /// Returns a new [`LayerFn`] that implements [`Layer`] by calling the |
5 | /// given function. |
6 | /// |
7 | /// The [`Layer::layer`] method takes a type implementing [`Service`] and |
8 | /// returns a different type implementing [`Service`]. In many cases, this can |
9 | /// be implemented by a function or a closure. The [`LayerFn`] helper allows |
10 | /// writing simple [`Layer`] implementations without needing the boilerplate of |
11 | /// a new struct implementing [`Layer`]. |
12 | /// |
13 | /// # Example |
14 | /// ```rust |
15 | /// # use tower::Service; |
16 | /// # use std::task::{Poll, Context}; |
17 | /// # use tower_layer::{Layer, layer_fn}; |
18 | /// # use std::fmt; |
19 | /// # use std::convert::Infallible; |
20 | /// # |
21 | /// // A middleware that logs requests before forwarding them to another service |
22 | /// pub struct LogService<S> { |
23 | /// target: &'static str, |
24 | /// service: S, |
25 | /// } |
26 | /// |
27 | /// impl<S, Request> Service<Request> for LogService<S> |
28 | /// where |
29 | /// S: Service<Request>, |
30 | /// Request: fmt::Debug, |
31 | /// { |
32 | /// type Response = S::Response; |
33 | /// type Error = S::Error; |
34 | /// type Future = S::Future; |
35 | /// |
36 | /// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
37 | /// self.service.poll_ready(cx) |
38 | /// } |
39 | /// |
40 | /// fn call(&mut self, request: Request) -> Self::Future { |
41 | /// // Log the request |
42 | /// println!("request = {:?}, target = {:?}" , request, self.target); |
43 | /// |
44 | /// self.service.call(request) |
45 | /// } |
46 | /// } |
47 | /// |
48 | /// // A `Layer` that wraps services in `LogService` |
49 | /// let log_layer = layer_fn(|service| { |
50 | /// LogService { |
51 | /// service, |
52 | /// target: "tower-docs" , |
53 | /// } |
54 | /// }); |
55 | /// |
56 | /// // An example service. This one uppercases strings |
57 | /// let uppercase_service = tower::service_fn(|request: String| async move { |
58 | /// Ok::<_, Infallible>(request.to_uppercase()) |
59 | /// }); |
60 | /// |
61 | /// // Wrap our service in a `LogService` so requests are logged. |
62 | /// let wrapped_service = log_layer.layer(uppercase_service); |
63 | /// ``` |
64 | /// |
65 | /// [`Service`]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html |
66 | /// [`Layer::layer`]: crate::Layer::layer |
67 | pub fn layer_fn<T>(f: T) -> LayerFn<T> { |
68 | LayerFn { f } |
69 | } |
70 | |
71 | /// A `Layer` implemented by a closure. See the docs for [`layer_fn`] for more details. |
72 | #[derive (Clone, Copy)] |
73 | pub struct LayerFn<F> { |
74 | f: F, |
75 | } |
76 | |
77 | impl<F, S, Out> Layer<S> for LayerFn<F> |
78 | where |
79 | F: Fn(S) -> Out, |
80 | { |
81 | type Service = Out; |
82 | |
83 | fn layer(&self, inner: S) -> Self::Service { |
84 | (self.f)(inner) |
85 | } |
86 | } |
87 | |
88 | impl<F> fmt::Debug for LayerFn<F> { |
89 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
90 | f&mut DebugStruct<'_, '_>.debug_struct("LayerFn" ) |
91 | .field(name:"f" , &format_args!(" {}" , std::any::type_name::<F>())) |
92 | .finish() |
93 | } |
94 | } |
95 | |
96 | #[cfg (test)] |
97 | mod tests { |
98 | use super::*; |
99 | |
100 | #[allow (dead_code)] |
101 | #[test ] |
102 | fn layer_fn_has_useful_debug_impl() { |
103 | struct WrappedService<S> { |
104 | inner: S, |
105 | } |
106 | let layer = layer_fn(|svc| WrappedService { inner: svc }); |
107 | let _svc = layer.layer("foo" ); |
108 | |
109 | assert_eq!( |
110 | "LayerFn { f: tower_layer::layer_fn::tests::layer_fn_has_useful_debug_impl::{{closure}} }" .to_string(), |
111 | format!("{:?}" , layer), |
112 | ); |
113 | } |
114 | } |
115 | |