1 | //! Builder types to compose layers and services |
2 | |
3 | use tower_layer::{Identity, Layer, Stack}; |
4 | use tower_service::Service; |
5 | |
6 | use 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 | /// ``` |
31 | /// # // this (and other) doctest is ignored because we don't have a way |
32 | /// # // to say that it should only be run with cfg(feature = "...") |
33 | /// # use tower::Service; |
34 | /// # use tower::builder::ServiceBuilder; |
35 | /// # #[cfg (all(feature = "buffer" , feature = "limit" ))] |
36 | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
37 | /// ServiceBuilder::new() |
38 | /// .buffer(100) |
39 | /// .concurrency_limit(10) |
40 | /// .service(svc) |
41 | /// # ; |
42 | /// # } |
43 | /// ``` |
44 | /// |
45 | /// In the above example, the buffer layer receives the request first followed |
46 | /// by `concurrency_limit`. `buffer` enables up to 100 request to be in-flight |
47 | /// **on top of** the requests that have already been forwarded to the next |
48 | /// layer. Combined with `concurrency_limit`, this allows up to 110 requests to be |
49 | /// in-flight. |
50 | /// |
51 | /// ``` |
52 | /// # use tower::Service; |
53 | /// # use tower::builder::ServiceBuilder; |
54 | /// # #[cfg (all(feature = "buffer" , feature = "limit" ))] |
55 | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
56 | /// ServiceBuilder::new() |
57 | /// .concurrency_limit(10) |
58 | /// .buffer(100) |
59 | /// .service(svc) |
60 | /// # ; |
61 | /// # } |
62 | /// ``` |
63 | /// |
64 | /// The above example is similar, but the order of layers is reversed. Now, |
65 | /// `concurrency_limit` applies first and only allows 10 requests to be in-flight |
66 | /// total. |
67 | /// |
68 | /// # Examples |
69 | /// |
70 | /// A [`Service`] stack with a single layer: |
71 | /// |
72 | /// ``` |
73 | /// # use tower::Service; |
74 | /// # use tower::builder::ServiceBuilder; |
75 | /// # #[cfg (feature = "limit" )] |
76 | /// # use tower::limit::concurrency::ConcurrencyLimitLayer; |
77 | /// # #[cfg (feature = "limit" )] |
78 | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
79 | /// ServiceBuilder::new() |
80 | /// .concurrency_limit(5) |
81 | /// .service(svc); |
82 | /// # ; |
83 | /// # } |
84 | /// ``` |
85 | /// |
86 | /// A [`Service`] stack with _multiple_ layers that contain rate limiting, |
87 | /// in-flight request limits, and a channel-backed, clonable [`Service`]: |
88 | /// |
89 | /// ``` |
90 | /// # use tower::Service; |
91 | /// # use tower::builder::ServiceBuilder; |
92 | /// # use std::time::Duration; |
93 | /// # #[cfg (all(feature = "buffer" , feature = "limit" ))] |
94 | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
95 | /// ServiceBuilder::new() |
96 | /// .buffer(5) |
97 | /// .concurrency_limit(5) |
98 | /// .rate_limit(5, Duration::from_secs(1)) |
99 | /// .service(svc); |
100 | /// # ; |
101 | /// # } |
102 | /// ``` |
103 | /// |
104 | /// [`Service`]: crate::Service |
105 | #[derive (Clone)] |
106 | pub struct ServiceBuilder<L> { |
107 | layer: L, |
108 | } |
109 | |
110 | impl Default for ServiceBuilder<Identity> { |
111 | fn default() -> Self { |
112 | Self::new() |
113 | } |
114 | } |
115 | |
116 | impl ServiceBuilder<Identity> { |
117 | /// Create a new [`ServiceBuilder`]. |
118 | pub const fn new() -> Self { |
119 | ServiceBuilder { |
120 | layer: Identity::new(), |
121 | } |
122 | } |
123 | } |
124 | |
125 | impl<L> ServiceBuilder<L> { |
126 | /// Add a new layer `T` into the [`ServiceBuilder`]. |
127 | /// |
128 | /// This wraps the inner service with the service provided by a user-defined |
129 | /// [`Layer`]. The provided layer must implement the [`Layer`] trait. |
130 | /// |
131 | /// [`Layer`]: crate::Layer |
132 | pub fn layer<T>(self, layer: T) -> ServiceBuilder<Stack<T, L>> { |
133 | ServiceBuilder { |
134 | layer: Stack::new(layer, self.layer), |
135 | } |
136 | } |
137 | |
138 | /// Optionally add a new layer `T` into the [`ServiceBuilder`]. |
139 | /// |
140 | /// ``` |
141 | /// # use std::time::Duration; |
142 | /// # use tower::Service; |
143 | /// # use tower::builder::ServiceBuilder; |
144 | /// # use tower::timeout::TimeoutLayer; |
145 | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
146 | /// # let timeout = Some(Duration::new(10, 0)); |
147 | /// // Apply a timeout if configured |
148 | /// ServiceBuilder::new() |
149 | /// .option_layer(timeout.map(TimeoutLayer::new)) |
150 | /// .service(svc) |
151 | /// # ; |
152 | /// # } |
153 | /// ``` |
154 | #[cfg (feature = "util" )] |
155 | pub fn option_layer<T>( |
156 | self, |
157 | layer: Option<T>, |
158 | ) -> ServiceBuilder<Stack<crate::util::Either<T, Identity>, L>> { |
159 | self.layer(crate::util::option_layer(layer)) |
160 | } |
161 | |
162 | /// Add a [`Layer`] built from a function that accepts a service and returns another service. |
163 | /// |
164 | /// See the documentation for [`layer_fn`] for more details. |
165 | /// |
166 | /// [`layer_fn`]: crate::layer::layer_fn |
167 | pub fn layer_fn<F>(self, f: F) -> ServiceBuilder<Stack<crate::layer::LayerFn<F>, L>> { |
168 | self.layer(crate::layer::layer_fn(f)) |
169 | } |
170 | |
171 | /// Buffer requests when the next layer is not ready. |
172 | /// |
173 | /// This wraps the inner service with an instance of the [`Buffer`] |
174 | /// middleware. |
175 | /// |
176 | /// [`Buffer`]: crate::buffer |
177 | #[cfg (feature = "buffer" )] |
178 | pub fn buffer<Request>( |
179 | self, |
180 | bound: usize, |
181 | ) -> ServiceBuilder<Stack<crate::buffer::BufferLayer<Request>, L>> { |
182 | self.layer(crate::buffer::BufferLayer::new(bound)) |
183 | } |
184 | |
185 | /// Limit the max number of in-flight requests. |
186 | /// |
187 | /// A request is in-flight from the time the request is received until the |
188 | /// response future completes. This includes the time spent in the next |
189 | /// layers. |
190 | /// |
191 | /// This wraps the inner service with an instance of the |
192 | /// [`ConcurrencyLimit`] middleware. |
193 | /// |
194 | /// [`ConcurrencyLimit`]: crate::limit::concurrency |
195 | #[cfg (feature = "limit" )] |
196 | pub fn concurrency_limit( |
197 | self, |
198 | max: usize, |
199 | ) -> ServiceBuilder<Stack<crate::limit::ConcurrencyLimitLayer, L>> { |
200 | self.layer(crate::limit::ConcurrencyLimitLayer::new(max)) |
201 | } |
202 | |
203 | /// Drop requests when the next layer is unable to respond to requests. |
204 | /// |
205 | /// Usually, when a service or middleware does not have capacity to process a |
206 | /// request (i.e., [`poll_ready`] returns [`Pending`]), the caller waits until |
207 | /// capacity becomes available. |
208 | /// |
209 | /// [`LoadShed`] immediately responds with an error when the next layer is |
210 | /// out of capacity. |
211 | /// |
212 | /// This wraps the inner service with an instance of the [`LoadShed`] |
213 | /// middleware. |
214 | /// |
215 | /// [`LoadShed`]: crate::load_shed |
216 | /// [`poll_ready`]: crate::Service::poll_ready |
217 | /// [`Pending`]: std::task::Poll::Pending |
218 | #[cfg (feature = "load-shed" )] |
219 | pub fn load_shed(self) -> ServiceBuilder<Stack<crate::load_shed::LoadShedLayer, L>> { |
220 | self.layer(crate::load_shed::LoadShedLayer::new()) |
221 | } |
222 | |
223 | /// Limit requests to at most `num` per the given duration. |
224 | /// |
225 | /// This wraps the inner service with an instance of the [`RateLimit`] |
226 | /// middleware. |
227 | /// |
228 | /// [`RateLimit`]: crate::limit::rate |
229 | #[cfg (feature = "limit" )] |
230 | pub fn rate_limit( |
231 | self, |
232 | num: u64, |
233 | per: std::time::Duration, |
234 | ) -> ServiceBuilder<Stack<crate::limit::RateLimitLayer, L>> { |
235 | self.layer(crate::limit::RateLimitLayer::new(num, per)) |
236 | } |
237 | |
238 | /// Retry failed requests according to the given [retry policy][policy]. |
239 | /// |
240 | /// `policy` determines which failed requests will be retried. It must |
241 | /// implement the [`retry::Policy`][policy] trait. |
242 | /// |
243 | /// This wraps the inner service with an instance of the [`Retry`] |
244 | /// middleware. |
245 | /// |
246 | /// [`Retry`]: crate::retry |
247 | /// [policy]: crate::retry::Policy |
248 | #[cfg (feature = "retry" )] |
249 | pub fn retry<P>(self, policy: P) -> ServiceBuilder<Stack<crate::retry::RetryLayer<P>, L>> { |
250 | self.layer(crate::retry::RetryLayer::new(policy)) |
251 | } |
252 | |
253 | /// Fail requests that take longer than `timeout`. |
254 | /// |
255 | /// If the next layer takes more than `timeout` to respond to a request, |
256 | /// processing is terminated and an error is returned. |
257 | /// |
258 | /// This wraps the inner service with an instance of the [`timeout`] |
259 | /// middleware. |
260 | /// |
261 | /// [`timeout`]: crate::timeout |
262 | #[cfg (feature = "timeout" )] |
263 | pub fn timeout( |
264 | self, |
265 | timeout: std::time::Duration, |
266 | ) -> ServiceBuilder<Stack<crate::timeout::TimeoutLayer, L>> { |
267 | self.layer(crate::timeout::TimeoutLayer::new(timeout)) |
268 | } |
269 | |
270 | /// Conditionally reject requests based on `predicate`. |
271 | /// |
272 | /// `predicate` must implement the [`Predicate`] trait. |
273 | /// |
274 | /// This wraps the inner service with an instance of the [`Filter`] |
275 | /// middleware. |
276 | /// |
277 | /// [`Filter`]: crate::filter |
278 | /// [`Predicate`]: crate::filter::Predicate |
279 | #[cfg (feature = "filter" )] |
280 | pub fn filter<P>( |
281 | self, |
282 | predicate: P, |
283 | ) -> ServiceBuilder<Stack<crate::filter::FilterLayer<P>, L>> { |
284 | self.layer(crate::filter::FilterLayer::new(predicate)) |
285 | } |
286 | |
287 | /// Conditionally reject requests based on an asynchronous `predicate`. |
288 | /// |
289 | /// `predicate` must implement the [`AsyncPredicate`] trait. |
290 | /// |
291 | /// This wraps the inner service with an instance of the [`AsyncFilter`] |
292 | /// middleware. |
293 | /// |
294 | /// [`AsyncFilter`]: crate::filter::AsyncFilter |
295 | /// [`AsyncPredicate`]: crate::filter::AsyncPredicate |
296 | #[cfg (feature = "filter" )] |
297 | pub fn filter_async<P>( |
298 | self, |
299 | predicate: P, |
300 | ) -> ServiceBuilder<Stack<crate::filter::AsyncFilterLayer<P>, L>> { |
301 | self.layer(crate::filter::AsyncFilterLayer::new(predicate)) |
302 | } |
303 | |
304 | /// Map one request type to another. |
305 | /// |
306 | /// This wraps the inner service with an instance of the [`MapRequest`] |
307 | /// middleware. |
308 | /// |
309 | /// # Examples |
310 | /// |
311 | /// Changing the type of a request: |
312 | /// |
313 | /// ```rust |
314 | /// use tower::ServiceBuilder; |
315 | /// use tower::ServiceExt; |
316 | /// |
317 | /// # #[tokio::main] |
318 | /// # async fn main() -> Result<(), ()> { |
319 | /// // Suppose we have some `Service` whose request type is `String`: |
320 | /// let string_svc = tower::service_fn(|request: String| async move { |
321 | /// println!("request: {}" , request); |
322 | /// Ok(()) |
323 | /// }); |
324 | /// |
325 | /// // ...but we want to call that service with a `usize`. What do we do? |
326 | /// |
327 | /// let usize_svc = ServiceBuilder::new() |
328 | /// // Add a middleware that converts the request type to a `String`: |
329 | /// .map_request(|request: usize| format!("{}" , request)) |
330 | /// // ...and wrap the string service with that middleware: |
331 | /// .service(string_svc); |
332 | /// |
333 | /// // Now, we can call that service with a `usize`: |
334 | /// usize_svc.oneshot(42).await?; |
335 | /// # Ok(()) |
336 | /// # } |
337 | /// ``` |
338 | /// |
339 | /// Modifying the request value: |
340 | /// |
341 | /// ```rust |
342 | /// use tower::ServiceBuilder; |
343 | /// use tower::ServiceExt; |
344 | /// |
345 | /// # #[tokio::main] |
346 | /// # async fn main() -> Result<(), ()> { |
347 | /// // A service that takes a number and returns it: |
348 | /// let svc = tower::service_fn(|request: usize| async move { |
349 | /// Ok(request) |
350 | /// }); |
351 | /// |
352 | /// let svc = ServiceBuilder::new() |
353 | /// // Add a middleware that adds 1 to each request |
354 | /// .map_request(|request: usize| request + 1) |
355 | /// .service(svc); |
356 | /// |
357 | /// let response = svc.oneshot(1).await?; |
358 | /// assert_eq!(response, 2); |
359 | /// # Ok(()) |
360 | /// # } |
361 | /// ``` |
362 | /// |
363 | /// [`MapRequest`]: crate::util::MapRequest |
364 | #[cfg (feature = "util" )] |
365 | pub fn map_request<F, R1, R2>( |
366 | self, |
367 | f: F, |
368 | ) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>> |
369 | where |
370 | F: FnMut(R1) -> R2 + Clone, |
371 | { |
372 | self.layer(crate::util::MapRequestLayer::new(f)) |
373 | } |
374 | |
375 | /// Map one response type to another. |
376 | /// |
377 | /// This wraps the inner service with an instance of the [`MapResponse`] |
378 | /// middleware. |
379 | /// |
380 | /// See the documentation for the [`map_response` combinator] for details. |
381 | /// |
382 | /// [`MapResponse`]: crate::util::MapResponse |
383 | /// [`map_response` combinator]: crate::util::ServiceExt::map_response |
384 | #[cfg (feature = "util" )] |
385 | pub fn map_response<F>( |
386 | self, |
387 | f: F, |
388 | ) -> ServiceBuilder<Stack<crate::util::MapResponseLayer<F>, L>> { |
389 | self.layer(crate::util::MapResponseLayer::new(f)) |
390 | } |
391 | |
392 | /// Map one error type to another. |
393 | /// |
394 | /// This wraps the inner service with an instance of the [`MapErr`] |
395 | /// middleware. |
396 | /// |
397 | /// See the documentation for the [`map_err` combinator] for details. |
398 | /// |
399 | /// [`MapErr`]: crate::util::MapErr |
400 | /// [`map_err` combinator]: crate::util::ServiceExt::map_err |
401 | #[cfg (feature = "util" )] |
402 | pub fn map_err<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>> { |
403 | self.layer(crate::util::MapErrLayer::new(f)) |
404 | } |
405 | |
406 | /// Composes a function that transforms futures produced by the service. |
407 | /// |
408 | /// This wraps the inner service with an instance of the [`MapFutureLayer`] middleware. |
409 | /// |
410 | /// See the documentation for the [`map_future`] combinator for details. |
411 | /// |
412 | /// [`MapFutureLayer`]: crate::util::MapFutureLayer |
413 | /// [`map_future`]: crate::util::ServiceExt::map_future |
414 | #[cfg (feature = "util" )] |
415 | pub fn map_future<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapFutureLayer<F>, L>> { |
416 | self.layer(crate::util::MapFutureLayer::new(f)) |
417 | } |
418 | |
419 | /// Apply an asynchronous function after the service, regardless of whether the future |
420 | /// succeeds or fails. |
421 | /// |
422 | /// This wraps the inner service with an instance of the [`Then`] |
423 | /// middleware. |
424 | /// |
425 | /// This is similar to the [`map_response`] and [`map_err`] functions, |
426 | /// except that the *same* function is invoked when the service's future |
427 | /// completes, whether it completes successfully or fails. This function |
428 | /// takes the [`Result`] returned by the service's future, and returns a |
429 | /// [`Result`]. |
430 | /// |
431 | /// See the documentation for the [`then` combinator] for details. |
432 | /// |
433 | /// [`Then`]: crate::util::Then |
434 | /// [`then` combinator]: crate::util::ServiceExt::then |
435 | /// [`map_response`]: ServiceBuilder::map_response |
436 | /// [`map_err`]: ServiceBuilder::map_err |
437 | #[cfg (feature = "util" )] |
438 | pub fn then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::ThenLayer<F>, L>> { |
439 | self.layer(crate::util::ThenLayer::new(f)) |
440 | } |
441 | |
442 | /// Executes a new future after this service's future resolves. This does |
443 | /// not alter the behaviour of the [`poll_ready`] method. |
444 | /// |
445 | /// This method can be used to change the [`Response`] type of the service |
446 | /// into a different type. You can use this method to chain along a computation once the |
447 | /// service's response has been resolved. |
448 | /// |
449 | /// This wraps the inner service with an instance of the [`AndThen`] |
450 | /// middleware. |
451 | /// |
452 | /// See the documentation for the [`and_then` combinator] for details. |
453 | /// |
454 | /// [`Response`]: crate::Service::Response |
455 | /// [`poll_ready`]: crate::Service::poll_ready |
456 | /// [`and_then` combinator]: crate::util::ServiceExt::and_then |
457 | /// [`AndThen`]: crate::util::AndThen |
458 | #[cfg (feature = "util" )] |
459 | pub fn and_then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::AndThenLayer<F>, L>> { |
460 | self.layer(crate::util::AndThenLayer::new(f)) |
461 | } |
462 | |
463 | /// Maps this service's result type (`Result<Self::Response, Self::Error>`) |
464 | /// to a different value, regardless of whether the future succeeds or |
465 | /// fails. |
466 | /// |
467 | /// This wraps the inner service with an instance of the [`MapResult`] |
468 | /// middleware. |
469 | /// |
470 | /// See the documentation for the [`map_result` combinator] for details. |
471 | /// |
472 | /// [`map_result` combinator]: crate::util::ServiceExt::map_result |
473 | /// [`MapResult`]: crate::util::MapResult |
474 | #[cfg (feature = "util" )] |
475 | pub fn map_result<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapResultLayer<F>, L>> { |
476 | self.layer(crate::util::MapResultLayer::new(f)) |
477 | } |
478 | |
479 | /// Returns the underlying `Layer` implementation. |
480 | pub fn into_inner(self) -> L { |
481 | self.layer |
482 | } |
483 | |
484 | /// Wrap the service `S` with the middleware provided by this |
485 | /// [`ServiceBuilder`]'s [`Layer`]'s, returning a new [`Service`]. |
486 | /// |
487 | /// [`Layer`]: crate::Layer |
488 | /// [`Service`]: crate::Service |
489 | pub fn service<S>(&self, service: S) -> L::Service |
490 | where |
491 | L: Layer<S>, |
492 | { |
493 | self.layer.layer(service) |
494 | } |
495 | |
496 | /// Wrap the async function `F` with the middleware provided by this [`ServiceBuilder`]'s |
497 | /// [`Layer`]s, returning a new [`Service`]. |
498 | /// |
499 | /// This is a convenience method which is equivalent to calling |
500 | /// [`ServiceBuilder::service`] with a [`service_fn`], like this: |
501 | /// |
502 | /// ```rust |
503 | /// # use tower::{ServiceBuilder, service_fn}; |
504 | /// # async fn handler_fn(_: ()) -> Result<(), ()> { Ok(()) } |
505 | /// # let _ = { |
506 | /// ServiceBuilder::new() |
507 | /// // ... |
508 | /// .service(service_fn(handler_fn)) |
509 | /// # }; |
510 | /// ``` |
511 | /// |
512 | /// # Example |
513 | /// |
514 | /// ```rust |
515 | /// use std::time::Duration; |
516 | /// use tower::{ServiceBuilder, ServiceExt, BoxError, service_fn}; |
517 | /// |
518 | /// # #[tokio::main] |
519 | /// # async fn main() -> Result<(), BoxError> { |
520 | /// async fn handle(request: &'static str) -> Result<&'static str, BoxError> { |
521 | /// Ok(request) |
522 | /// } |
523 | /// |
524 | /// let svc = ServiceBuilder::new() |
525 | /// .buffer(1024) |
526 | /// .timeout(Duration::from_secs(10)) |
527 | /// .service_fn(handle); |
528 | /// |
529 | /// let response = svc.oneshot("foo" ).await?; |
530 | /// |
531 | /// assert_eq!(response, "foo" ); |
532 | /// # Ok(()) |
533 | /// # } |
534 | /// ``` |
535 | /// |
536 | /// [`Layer`]: crate::Layer |
537 | /// [`Service`]: crate::Service |
538 | /// [`service_fn`]: crate::service_fn |
539 | #[cfg (feature = "util" )] |
540 | pub fn service_fn<F>(self, f: F) -> L::Service |
541 | where |
542 | L: Layer<crate::util::ServiceFn<F>>, |
543 | { |
544 | self.service(crate::util::service_fn(f)) |
545 | } |
546 | |
547 | /// Check that the builder implements `Clone`. |
548 | /// |
549 | /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers. |
550 | /// |
551 | /// Doesn't actually change the builder but serves as a type check. |
552 | /// |
553 | /// # Example |
554 | /// |
555 | /// ```rust |
556 | /// use tower::ServiceBuilder; |
557 | /// |
558 | /// let builder = ServiceBuilder::new() |
559 | /// // Do something before processing the request |
560 | /// .map_request(|request: String| { |
561 | /// println!("got request!" ); |
562 | /// request |
563 | /// }) |
564 | /// // Ensure our `ServiceBuilder` can be cloned |
565 | /// .check_clone() |
566 | /// // Do something after processing the request |
567 | /// .map_response(|response: String| { |
568 | /// println!("got response!" ); |
569 | /// response |
570 | /// }); |
571 | /// ``` |
572 | #[inline ] |
573 | pub fn check_clone(self) -> Self |
574 | where |
575 | Self: Clone, |
576 | { |
577 | self |
578 | } |
579 | |
580 | /// Check that the builder when given a service of type `S` produces a service that implements |
581 | /// `Clone`. |
582 | /// |
583 | /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers. |
584 | /// |
585 | /// Doesn't actually change the builder but serves as a type check. |
586 | /// |
587 | /// # Example |
588 | /// |
589 | /// ```rust |
590 | /// use tower::ServiceBuilder; |
591 | /// |
592 | /// # #[derive(Clone)] |
593 | /// # struct MyService; |
594 | /// # |
595 | /// let builder = ServiceBuilder::new() |
596 | /// // Do something before processing the request |
597 | /// .map_request(|request: String| { |
598 | /// println!("got request!" ); |
599 | /// request |
600 | /// }) |
601 | /// // Ensure that the service produced when given a `MyService` implements |
602 | /// .check_service_clone::<MyService>() |
603 | /// // Do something after processing the request |
604 | /// .map_response(|response: String| { |
605 | /// println!("got response!" ); |
606 | /// response |
607 | /// }); |
608 | /// ``` |
609 | #[inline ] |
610 | pub fn check_service_clone<S>(self) -> Self |
611 | where |
612 | L: Layer<S>, |
613 | L::Service: Clone, |
614 | { |
615 | self |
616 | } |
617 | |
618 | /// Check that the builder when given a service of type `S` produces a service with the given |
619 | /// request, response, and error types. |
620 | /// |
621 | /// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers. |
622 | /// |
623 | /// Doesn't actually change the builder but serves as a type check. |
624 | /// |
625 | /// # Example |
626 | /// |
627 | /// ```rust |
628 | /// use tower::ServiceBuilder; |
629 | /// use std::task::{Poll, Context}; |
630 | /// use tower::{Service, ServiceExt}; |
631 | /// |
632 | /// // An example service |
633 | /// struct MyService; |
634 | /// |
635 | /// impl Service<Request> for MyService { |
636 | /// type Response = Response; |
637 | /// type Error = Error; |
638 | /// type Future = futures_util::future::Ready<Result<Response, Error>>; |
639 | /// |
640 | /// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
641 | /// // ... |
642 | /// # todo!() |
643 | /// } |
644 | /// |
645 | /// fn call(&mut self, request: Request) -> Self::Future { |
646 | /// // ... |
647 | /// # todo!() |
648 | /// } |
649 | /// } |
650 | /// |
651 | /// struct Request; |
652 | /// struct Response; |
653 | /// struct Error; |
654 | /// |
655 | /// struct WrappedResponse(Response); |
656 | /// |
657 | /// let builder = ServiceBuilder::new() |
658 | /// // At this point in the builder if given a `MyService` it produces a service that |
659 | /// // accepts `Request`s, produces `Response`s, and fails with `Error`s |
660 | /// .check_service::<MyService, Request, Response, Error>() |
661 | /// // Wrap responses in `WrappedResponse` |
662 | /// .map_response(|response: Response| WrappedResponse(response)) |
663 | /// // Now the response type will be `WrappedResponse` |
664 | /// .check_service::<MyService, _, WrappedResponse, _>(); |
665 | /// ``` |
666 | #[inline ] |
667 | pub fn check_service<S, T, U, E>(self) -> Self |
668 | where |
669 | L: Layer<S>, |
670 | L::Service: Service<T, Response = U, Error = E>, |
671 | { |
672 | self |
673 | } |
674 | |
675 | /// This wraps the inner service with the [`Layer`] returned by [`BoxService::layer()`]. |
676 | /// |
677 | /// See that method for more details. |
678 | /// |
679 | /// # Example |
680 | /// |
681 | /// ``` |
682 | /// use tower::{Service, ServiceBuilder, BoxError, util::BoxService}; |
683 | /// use std::time::Duration; |
684 | /// # |
685 | /// # struct Request; |
686 | /// # struct Response; |
687 | /// # impl Response { |
688 | /// # fn new() -> Self { Self } |
689 | /// # } |
690 | /// |
691 | /// let service: BoxService<Request, Response, BoxError> = ServiceBuilder::new() |
692 | /// .boxed() |
693 | /// .load_shed() |
694 | /// .concurrency_limit(64) |
695 | /// .timeout(Duration::from_secs(10)) |
696 | /// .service_fn(|req: Request| async { |
697 | /// Ok::<_, BoxError>(Response::new()) |
698 | /// }); |
699 | /// # let service = assert_service(service); |
700 | /// # fn assert_service<S, R>(svc: S) -> S |
701 | /// # where S: Service<R> { svc } |
702 | /// ``` |
703 | /// |
704 | /// [`BoxService::layer()`]: crate::util::BoxService::layer() |
705 | #[cfg (feature = "util" )] |
706 | pub fn boxed<S, R>( |
707 | self, |
708 | ) -> ServiceBuilder< |
709 | Stack< |
710 | tower_layer::LayerFn< |
711 | fn( |
712 | L::Service, |
713 | ) -> crate::util::BoxService< |
714 | R, |
715 | <L::Service as Service<R>>::Response, |
716 | <L::Service as Service<R>>::Error, |
717 | >, |
718 | >, |
719 | L, |
720 | >, |
721 | > |
722 | where |
723 | L: Layer<S>, |
724 | L::Service: Service<R> + Send + 'static, |
725 | <L::Service as Service<R>>::Future: Send + 'static, |
726 | { |
727 | self.layer(crate::util::BoxService::layer()) |
728 | } |
729 | |
730 | /// This wraps the inner service with the [`Layer`] returned by [`BoxCloneService::layer()`]. |
731 | /// |
732 | /// This is similar to the [`boxed`] method, but it requires that `Self` implement |
733 | /// [`Clone`], and the returned boxed service implements [`Clone`]. |
734 | /// |
735 | /// See [`BoxCloneService`] for more details. |
736 | /// |
737 | /// # Example |
738 | /// |
739 | /// ``` |
740 | /// use tower::{Service, ServiceBuilder, BoxError, util::BoxCloneService}; |
741 | /// use std::time::Duration; |
742 | /// # |
743 | /// # struct Request; |
744 | /// # struct Response; |
745 | /// # impl Response { |
746 | /// # fn new() -> Self { Self } |
747 | /// # } |
748 | /// |
749 | /// let service: BoxCloneService<Request, Response, BoxError> = ServiceBuilder::new() |
750 | /// .boxed_clone() |
751 | /// .load_shed() |
752 | /// .concurrency_limit(64) |
753 | /// .timeout(Duration::from_secs(10)) |
754 | /// .service_fn(|req: Request| async { |
755 | /// Ok::<_, BoxError>(Response::new()) |
756 | /// }); |
757 | /// # let service = assert_service(service); |
758 | /// |
759 | /// // The boxed service can still be cloned. |
760 | /// service.clone(); |
761 | /// # fn assert_service<S, R>(svc: S) -> S |
762 | /// # where S: Service<R> { svc } |
763 | /// ``` |
764 | /// |
765 | /// [`BoxCloneService::layer()`]: crate::util::BoxCloneService::layer() |
766 | /// [`BoxCloneService`]: crate::util::BoxCloneService |
767 | /// [`boxed`]: Self::boxed |
768 | #[cfg (feature = "util" )] |
769 | pub fn boxed_clone<S, R>( |
770 | self, |
771 | ) -> ServiceBuilder< |
772 | Stack< |
773 | tower_layer::LayerFn< |
774 | fn( |
775 | L::Service, |
776 | ) -> crate::util::BoxCloneService< |
777 | R, |
778 | <L::Service as Service<R>>::Response, |
779 | <L::Service as Service<R>>::Error, |
780 | >, |
781 | >, |
782 | L, |
783 | >, |
784 | > |
785 | where |
786 | L: Layer<S>, |
787 | L::Service: Service<R> + Clone + Send + 'static, |
788 | <L::Service as Service<R>>::Future: Send + 'static, |
789 | { |
790 | self.layer(crate::util::BoxCloneService::layer()) |
791 | } |
792 | } |
793 | |
794 | impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> { |
795 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
796 | f.debug_tuple(name:"ServiceBuilder" ).field(&self.layer).finish() |
797 | } |
798 | } |
799 | |
800 | impl<S, L> Layer<S> for ServiceBuilder<L> |
801 | where |
802 | L: Layer<S>, |
803 | { |
804 | type Service = L::Service; |
805 | |
806 | fn layer(&self, inner: S) -> Self::Service { |
807 | self.layer.layer(inner) |
808 | } |
809 | } |
810 | |