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}