tower_async/builder/
mod.rs

1//! Builder types to compose layers and services
2
3use tower_async_layer::{Identity, Layer, Stack};
4use tower_async_service::Service;
5
6use std::fmt;
7
8/// Declaratively construct [`Service`] values.
9///
10/// [`ServiceBuilder`] provides a [builder-like interface][builder] for composing
11/// layers to be applied to a [`Service`].
12///
13/// # Service
14///
15/// A [`Service`] is a trait representing an asynchronous function of a request
16/// to a response. It is similar to `async fn(Request) -> Result<Response, Error>`.
17///
18/// A [`Service`] is typically bound to a single transport, such as a TCP
19/// connection.  It defines how _all_ inbound or outbound requests are handled
20/// by that connection.
21///
22/// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
23///
24/// # Order
25///
26/// The order in which layers are added impacts how requests are handled. Layers
27/// that are added first will be called with the request first. The argument to
28/// `service` will be last to see the request.
29///
30/// [`Service`]: crate::Service
31#[derive(Clone)]
32pub struct ServiceBuilder<L> {
33    layer: L,
34}
35
36impl Default for ServiceBuilder<Identity> {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl ServiceBuilder<Identity> {
43    /// Create a new [`ServiceBuilder`].
44    pub fn new() -> Self {
45        ServiceBuilder {
46            layer: Identity::new(),
47        }
48    }
49}
50
51impl<L> ServiceBuilder<L> {
52    /// Add a new layer `T` into the [`ServiceBuilder`].
53    ///
54    /// This wraps the inner service with the service provided by a user-defined
55    /// [`Layer`]. The provided layer must implement the [`Layer`] trait.
56    ///
57    /// [`Layer`]: crate::Layer
58    pub fn layer<T>(self, layer: T) -> ServiceBuilder<Stack<T, L>> {
59        ServiceBuilder {
60            layer: Stack::new(layer, self.layer),
61        }
62    }
63
64    /// Optionally add a new layer `T` into the [`ServiceBuilder`].
65    ///
66    /// ```
67    /// # use std::time::Duration;
68    /// # use tower_async::Service;
69    /// # use tower_async::builder::ServiceBuilder;
70    /// # use tower_async::timeout::TimeoutLayer;
71    /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send {
72    /// # let timeout = Some(Duration::new(10, 0));
73    /// // Apply a timeout if configured
74    /// ServiceBuilder::new()
75    ///     .option_layer(timeout.map(TimeoutLayer::new))
76    ///     .service(svc)
77    /// # ;
78    /// # }
79    /// ```
80    #[cfg(feature = "util")]
81    pub fn option_layer<T>(
82        self,
83        layer: Option<T>,
84    ) -> ServiceBuilder<Stack<crate::util::Either<T, Identity>, L>> {
85        self.layer(crate::util::option_layer(layer))
86    }
87
88    /// Add a [`Layer`] built from a function that accepts a service and returns another service.
89    ///
90    /// See the documentation for [`layer_fn`] for more details.
91    ///
92    /// [`layer_fn`]: crate::layer::layer_fn
93    pub fn layer_fn<F>(self, f: F) -> ServiceBuilder<Stack<crate::layer::LayerFn<F>, L>> {
94        self.layer(crate::layer::layer_fn(f))
95    }
96
97    /// Retry failed requests according to the given [retry policy][policy].
98    ///
99    /// `policy` determines which failed requests will be retried. It must
100    /// implement the [`retry::Policy`][policy] trait.
101    ///
102    /// This wraps the inner service with an instance of the [`Retry`]
103    /// middleware.
104    ///
105    /// [`Retry`]: crate::retry
106    /// [policy]: crate::retry::Policy
107    #[cfg(feature = "retry")]
108    pub fn retry<P>(self, policy: P) -> ServiceBuilder<Stack<crate::retry::RetryLayer<P>, L>> {
109        self.layer(crate::retry::RetryLayer::new(policy))
110    }
111
112    /// Fail requests that take longer than `timeout`.
113    ///
114    /// If the next layer takes more than `timeout` to respond to a request,
115    /// processing is terminated and an error is returned.
116    ///
117    /// This wraps the inner service with an instance of the [`timeout`]
118    /// middleware.
119    ///
120    /// [`timeout`]: crate::timeout
121    #[cfg(feature = "timeout")]
122    pub fn timeout(
123        self,
124        timeout: std::time::Duration,
125    ) -> ServiceBuilder<Stack<crate::timeout::TimeoutLayer, L>> {
126        self.layer(crate::timeout::TimeoutLayer::new(timeout))
127    }
128
129    /// Conditionally reject requests based on `predicate`.
130    ///
131    /// `predicate` must implement the [`Predicate`] trait.
132    ///
133    /// This wraps the inner service with an instance of the [`Filter`]
134    /// middleware.
135    ///
136    /// [`Filter`]: crate::filter
137    /// [`Predicate`]: crate::filter::Predicate
138    #[cfg(feature = "filter")]
139    pub fn filter<P>(
140        self,
141        predicate: P,
142    ) -> ServiceBuilder<Stack<crate::filter::FilterLayer<P>, L>> {
143        self.layer(crate::filter::FilterLayer::new(predicate))
144    }
145
146    /// Conditionally reject requests based on an asynchronous `predicate`.
147    ///
148    /// `predicate` must implement the [`AsyncPredicate`] trait.
149    ///
150    /// This wraps the inner service with an instance of the [`AsyncFilter`]
151    /// middleware.
152    ///
153    /// [`AsyncFilter`]: crate::filter::AsyncFilter
154    /// [`AsyncPredicate`]: crate::filter::AsyncPredicate
155    #[cfg(feature = "filter")]
156    pub fn filter_async<P>(
157        self,
158        predicate: P,
159    ) -> ServiceBuilder<Stack<crate::filter::AsyncFilterLayer<P>, L>> {
160        self.layer(crate::filter::AsyncFilterLayer::new(predicate))
161    }
162
163    /// Limit the number of in-flight requests.
164    ///
165    /// This wraps the inner service with an instance of the [`Limit`]
166    /// middleware. The `policy` determines how to handle requests sent
167    /// to the inner service when the limit has been reached.
168    ///
169    /// [`Limit`]: crate::limit::Limit
170    #[cfg(feature = "limit")]
171    pub fn limit<P>(self, policy: P) -> ServiceBuilder<Stack<crate::limit::LimitLayer<P>, L>> {
172        self.layer(crate::limit::LimitLayer::new(policy))
173    }
174
175    /// Map one request type to another.
176    ///
177    /// This wraps the inner service with an instance of the [`MapRequest`]
178    /// middleware.
179    ///
180    /// # Examples
181    ///
182    /// Changing the type of a request:
183    ///
184    /// ```rust
185    /// use tower_async::ServiceBuilder;
186    /// use tower_async::ServiceExt;
187    ///
188    /// # #[tokio::main]
189    /// # async fn main() -> Result<(), ()> {
190    /// // Suppose we have some `Service` whose request type is `String`:
191    /// let string_svc = tower_async::service_fn(|request: String| async move {
192    ///     println!("request: {}", request);
193    ///     Ok(())
194    /// });
195    ///
196    /// // ...but we want to call that service with a `usize`. What do we do?
197    ///
198    /// let usize_svc = ServiceBuilder::new()
199    ///      // Add a middleware that converts the request type to a `String`:
200    ///     .map_request(|request: usize| format!("{}", request))
201    ///     // ...and wrap the string service with that middleware:
202    ///     .service(string_svc);
203    ///
204    /// // Now, we can call that service with a `usize`:
205    /// usize_svc.oneshot(42).await?;
206    /// # Ok(())
207    /// # }
208    /// ```
209    ///
210    /// Modifying the request value:
211    ///
212    /// ```rust
213    /// use tower_async::ServiceBuilder;
214    /// use tower_async::ServiceExt;
215    ///
216    /// # #[tokio::main]
217    /// # async fn main() -> Result<(), ()> {
218    /// // A service that takes a number and returns it:
219    /// let svc = tower_async::service_fn(|request: usize| async move {
220    ///    Ok(request)
221    /// });
222    ///
223    /// let svc = ServiceBuilder::new()
224    ///      // Add a middleware that adds 1 to each request
225    ///     .map_request(|request: usize| request + 1)
226    ///     .service(svc);
227    ///
228    /// let response = svc.oneshot(1).await?;
229    /// assert_eq!(response, 2);
230    /// # Ok(())
231    /// # }
232    /// ```
233    ///
234    /// [`MapRequest`]: crate::util::MapRequest
235    #[cfg(feature = "util")]
236    pub fn map_request<F, R1, R2>(
237        self,
238        f: F,
239    ) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>>
240    where
241        F: Fn(R1) -> R2 + Clone,
242    {
243        self.layer(crate::util::MapRequestLayer::new(f))
244    }
245
246    /// Map one response type to another.
247    ///
248    /// This wraps the inner service with an instance of the [`MapResponse`]
249    /// middleware.
250    ///
251    /// See the documentation for the [`map_response` combinator] for details.
252    ///
253    /// [`MapResponse`]: crate::util::MapResponse
254    /// [`map_response` combinator]: crate::util::ServiceExt::map_response
255    #[cfg(feature = "util")]
256    pub fn map_response<F>(
257        self,
258        f: F,
259    ) -> ServiceBuilder<Stack<crate::util::MapResponseLayer<F>, L>> {
260        self.layer(crate::util::MapResponseLayer::new(f))
261    }
262
263    /// Map one error type to another.
264    ///
265    /// This wraps the inner service with an instance of the [`MapErr`]
266    /// middleware.
267    ///
268    /// See the documentation for the [`map_err` combinator] for details.
269    ///
270    /// [`MapErr`]: crate::util::MapErr
271    /// [`map_err` combinator]: crate::util::ServiceExt::map_err
272    #[cfg(feature = "util")]
273    pub fn map_err<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>> {
274        self.layer(crate::util::MapErrLayer::new(f))
275    }
276
277    /// Apply an asynchronous function after the service, regardless of whether the future
278    /// succeeds or fails.
279    ///
280    /// This wraps the inner service with an instance of the [`Then`]
281    /// middleware.
282    ///
283    /// This is similar to the [`map_response`] and [`map_err`] functions,
284    /// except that the *same* function is invoked when the service's future
285    /// completes, whether it completes successfully or fails. This function
286    /// takes the [`Result`] returned by the service's future, and returns a
287    /// [`Result`].
288    ///
289    /// See the documentation for the [`then` combinator] for details.
290    ///
291    /// [`Then`]: crate::util::Then
292    /// [`then` combinator]: crate::util::ServiceExt::then
293    /// [`map_response`]: ServiceBuilder::map_response
294    /// [`map_err`]: ServiceBuilder::map_err
295    #[cfg(feature = "util")]
296    pub fn then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::ThenLayer<F>, L>> {
297        self.layer(crate::util::ThenLayer::new(f))
298    }
299
300    /// Executes a new future after this service's future resolves.
301    ///
302    /// This method can be used to change the [`Response`] type of the service
303    /// into a different type. You can use this method to chain along a computation once the
304    /// service's response has been resolved.
305    ///
306    /// This wraps the inner service with an instance of the [`AndThen`]
307    /// middleware.
308    ///
309    /// See the documentation for the [`and_then` combinator] for details.
310    ///
311    /// [`Response`]: crate::Service::Response
312    /// [`and_then` combinator]: crate::util::ServiceExt::and_then
313    /// [`AndThen`]: crate::util::AndThen
314    #[cfg(feature = "util")]
315    pub fn and_then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::AndThenLayer<F>, L>> {
316        self.layer(crate::util::AndThenLayer::new(f))
317    }
318
319    /// Maps this service's result type (`Result<Self::Response, Self::Error>`)
320    /// to a different value, regardless of whether the future succeeds or
321    /// fails.
322    ///
323    /// This wraps the inner service with an instance of the [`MapResult`]
324    /// middleware.
325    ///
326    /// See the documentation for the [`map_result` combinator] for details.
327    ///
328    /// [`map_result` combinator]: crate::util::ServiceExt::map_result
329    /// [`MapResult`]: crate::util::MapResult
330    #[cfg(feature = "util")]
331    pub fn map_result<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapResultLayer<F>, L>> {
332        self.layer(crate::util::MapResultLayer::new(f))
333    }
334
335    /// Returns the underlying `Layer` implementation.
336    pub fn into_inner(self) -> L {
337        self.layer
338    }
339
340    /// Wrap the service `S` with the middleware provided by this
341    /// [`ServiceBuilder`]'s [`Layer`]'s, returning a new [`Service`].
342    ///
343    /// [`Layer`]: crate::Layer
344    /// [`Service`]: crate::Service
345    pub fn service<S>(&self, service: S) -> L::Service
346    where
347        L: Layer<S>,
348    {
349        self.layer.layer(service)
350    }
351
352    /// Wrap the async function `F` with the middleware provided by this [`ServiceBuilder`]'s
353    /// [`Layer`]s, returning a new [`Service`].
354    ///
355    /// This is a convenience method which is equivalent to calling
356    /// [`ServiceBuilder::service`] with a [`service_fn`], like this:
357    ///
358    /// ```rust
359    /// # use tower_async::{ServiceBuilder, service_fn};
360    /// # async fn handler_fn(_: ()) -> Result<(), ()> { Ok(()) }
361    /// # let _ = {
362    /// ServiceBuilder::new()
363    ///     // ...
364    ///     .service(service_fn(handler_fn))
365    /// # };
366    /// ```
367    ///
368    /// # Example
369    ///
370    /// ```rust
371    /// use std::time::Duration;
372    /// use tower_async::{ServiceBuilder, ServiceExt, BoxError, service_fn};
373    ///
374    /// # #[tokio::main]
375    /// # async fn main() -> Result<(), BoxError> {
376    /// async fn handle(request: &'static str) -> Result<&'static str, BoxError> {
377    ///    Ok(request)
378    /// }
379    ///
380    /// let svc = ServiceBuilder::new()
381    ///     .timeout(Duration::from_secs(10))
382    ///     .service_fn(handle);
383    ///
384    /// let response = svc.oneshot("foo").await?;
385    ///
386    /// assert_eq!(response, "foo");
387    /// # Ok(())
388    /// # }
389    /// ```
390    ///
391    /// [`Layer`]: crate::Layer
392    /// [`Service`]: crate::Service
393    /// [`service_fn`]: crate::service_fn
394    #[cfg(feature = "util")]
395    pub fn service_fn<F>(self, f: F) -> L::Service
396    where
397        L: Layer<crate::util::ServiceFn<F>>,
398    {
399        self.service(crate::util::service_fn(f))
400    }
401
402    /// Check that the builder implements `Clone`.
403    ///
404    /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
405    ///
406    /// Doesn't actually change the builder but serves as a type check.
407    ///
408    /// # Example
409    ///
410    /// ```rust
411    /// use tower_async::ServiceBuilder;
412    ///
413    /// let builder = ServiceBuilder::new()
414    ///     // Do something before processing the request
415    ///     .map_request(|request: String| {
416    ///         println!("got request!");
417    ///         request
418    ///     })
419    ///     // Ensure our `ServiceBuilder` can be cloned
420    ///     .check_clone()
421    ///     // Do something after processing the request
422    ///     .map_response(|response: String| {
423    ///         println!("got response!");
424    ///         response
425    ///     });
426    /// ```
427    #[inline]
428    pub fn check_clone(self) -> Self
429    where
430        Self: Clone,
431    {
432        self
433    }
434
435    /// Check that the builder when given a service of type `S` produces a service that implements
436    /// `Clone`.
437    ///
438    /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
439    ///
440    /// Doesn't actually change the builder but serves as a type check.
441    ///
442    /// # Example
443    ///
444    /// ```rust
445    /// use tower_async::ServiceBuilder;
446    ///
447    /// # #[derive(Clone)]
448    /// # struct MyService;
449    /// #
450    /// let builder = ServiceBuilder::new()
451    ///     // Do something before processing the request
452    ///     .map_request(|request: String| {
453    ///         println!("got request!");
454    ///         request
455    ///     })
456    ///     // Ensure that the service produced when given a `MyService` implements
457    ///     .check_service_clone::<MyService>()
458    ///     // Do something after processing the request
459    ///     .map_response(|response: String| {
460    ///         println!("got response!");
461    ///         response
462    ///     });
463    /// ```
464    #[inline]
465    pub fn check_service_clone<S>(self) -> Self
466    where
467        L: Layer<S>,
468        L::Service: Clone,
469    {
470        self
471    }
472
473    /// Check that the builder when given a service of type `S` produces a service with the given
474    /// request, response, and error types.
475    ///
476    /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
477    ///
478    /// Doesn't actually change the builder but serves as a type check.
479    ///
480    /// # Example
481    ///
482    /// ```rust
483    /// use tower_async::ServiceBuilder;
484    /// use std::task::{Poll, Context};
485    /// use tower_async::{Service, ServiceExt};
486    ///
487    /// // An example service
488    /// struct MyService;
489    ///
490    /// impl Service<Request> for MyService {
491    ///   type Response = Response;
492    ///   type Error = Error;
493    ///
494    ///   async fn call(&self, request: Request) -> Result<Self::Response, Self::Error> {
495    ///       // ...
496    ///       # todo!()
497    ///   }
498    /// }
499    ///
500    /// struct Request;
501    /// struct Response;
502    /// struct Error;
503    ///
504    /// struct WrappedResponse(Response);
505    ///
506    /// let builder = ServiceBuilder::new()
507    ///     // At this point in the builder if given a `MyService` it produces a service that
508    ///     // accepts `Request`s, produces `Response`s, and fails with `Error`s
509    ///     .check_service::<MyService, Request, Response, Error>()
510    ///     // Wrap responses in `WrappedResponse`
511    ///     .map_response(|response: Response| WrappedResponse(response))
512    ///     // Now the response type will be `WrappedResponse`
513    ///     .check_service::<MyService, _, WrappedResponse, _>();
514    /// ```
515    #[inline]
516    pub fn check_service<S, T, U, E>(self) -> Self
517    where
518        L: Layer<S>,
519        L::Service: Service<T, Response = U, Error = E>,
520    {
521        self
522    }
523}
524
525impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> {
526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527        f.debug_tuple("ServiceBuilder").field(&self.layer).finish()
528    }
529}
530
531impl<S, L> Layer<S> for ServiceBuilder<L>
532where
533    L: Layer<S>,
534{
535    type Service = L::Service;
536
537    fn layer(&self, inner: S) -> Self::Service {
538        self.layer.layer(inner)
539    }
540}