/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tower-0.5.3/src/util/mod.rs
Line | Count | Source |
1 | | //! Various utility types and functions that are generally used with Tower. |
2 | | |
3 | | mod and_then; |
4 | | mod boxed; |
5 | | mod boxed_clone; |
6 | | mod boxed_clone_sync; |
7 | | mod call_all; |
8 | | mod either; |
9 | | |
10 | | mod future_service; |
11 | | mod map_err; |
12 | | mod map_request; |
13 | | mod map_response; |
14 | | mod map_result; |
15 | | |
16 | | mod map_future; |
17 | | mod oneshot; |
18 | | mod optional; |
19 | | mod ready; |
20 | | mod service_fn; |
21 | | mod then; |
22 | | |
23 | | pub mod rng; |
24 | | |
25 | | pub use self::{ |
26 | | and_then::{AndThen, AndThenLayer}, |
27 | | boxed::{ |
28 | | BoxCloneServiceLayer, BoxCloneSyncServiceLayer, BoxLayer, BoxService, UnsyncBoxService, |
29 | | }, |
30 | | boxed_clone::BoxCloneService, |
31 | | boxed_clone_sync::BoxCloneSyncService, |
32 | | either::Either, |
33 | | future_service::{future_service, FutureService}, |
34 | | map_err::{MapErr, MapErrLayer}, |
35 | | map_future::{MapFuture, MapFutureLayer}, |
36 | | map_request::{MapRequest, MapRequestLayer}, |
37 | | map_response::{MapResponse, MapResponseLayer}, |
38 | | map_result::{MapResult, MapResultLayer}, |
39 | | oneshot::Oneshot, |
40 | | optional::Optional, |
41 | | ready::{Ready, ReadyOneshot}, |
42 | | service_fn::{service_fn, ServiceFn}, |
43 | | then::{Then, ThenLayer}, |
44 | | }; |
45 | | |
46 | | pub use self::call_all::{CallAll, CallAllUnordered}; |
47 | | use std::future::Future; |
48 | | |
49 | | use crate::layer::util::Identity; |
50 | | |
51 | | pub mod error { |
52 | | //! Error types |
53 | | |
54 | | pub use super::optional::error as optional; |
55 | | } |
56 | | |
57 | | pub mod future { |
58 | | //! Future types |
59 | | |
60 | | pub use super::and_then::AndThenFuture; |
61 | | pub use super::either::EitherResponseFuture; |
62 | | pub use super::map_err::MapErrFuture; |
63 | | pub use super::map_response::MapResponseFuture; |
64 | | pub use super::map_result::MapResultFuture; |
65 | | pub use super::optional::future as optional; |
66 | | pub use super::then::ThenFuture; |
67 | | } |
68 | | |
69 | | /// An extension trait for `Service`s that provides a variety of convenient |
70 | | /// adapters |
71 | | pub trait ServiceExt<Request>: tower_service::Service<Request> { |
72 | | /// Yields a mutable reference to the service when it is ready to accept a request. |
73 | 0 | fn ready(&mut self) -> Ready<'_, Self, Request> |
74 | 0 | where |
75 | 0 | Self: Sized, |
76 | | { |
77 | 0 | Ready::new(self) |
78 | 0 | } |
79 | | |
80 | | /// Yields the service when it is ready to accept a request. |
81 | 0 | fn ready_oneshot(self) -> ReadyOneshot<Self, Request> |
82 | 0 | where |
83 | 0 | Self: Sized, |
84 | | { |
85 | 0 | ReadyOneshot::new(self) |
86 | 0 | } |
87 | | |
88 | | /// Consume this `Service`, calling it with the provided request once it is ready. |
89 | 0 | fn oneshot(self, req: Request) -> Oneshot<Self, Request> |
90 | 0 | where |
91 | 0 | Self: Sized, |
92 | | { |
93 | 0 | Oneshot::new(self, req) |
94 | 0 | } Unexecuted instantiation: <tower::util::boxed_clone_sync::BoxCloneSyncService<http::request::Request<axum_core::body::Body>, http::response::Response<axum_core::body::Body>, core::convert::Infallible> as tower::util::ServiceExt<http::request::Request<axum_core::body::Body>>>::oneshot Unexecuted instantiation: <_ as tower::util::ServiceExt<_>>::oneshot |
95 | | |
96 | | /// Process all requests from the given [`Stream`], and produce a [`Stream`] of their responses. |
97 | | /// |
98 | | /// This is essentially [`Stream<Item = Request>`][stream] + `Self` => [`Stream<Item = |
99 | | /// Response>`][stream]. See the documentation for [`CallAll`] for |
100 | | /// details. |
101 | | /// |
102 | | /// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html |
103 | | /// [stream]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html |
104 | 0 | fn call_all<S>(self, reqs: S) -> CallAll<Self, S> |
105 | 0 | where |
106 | 0 | Self: Sized, |
107 | 0 | S: futures_core::Stream<Item = Request>, |
108 | | { |
109 | 0 | CallAll::new(self, reqs) |
110 | 0 | } |
111 | | |
112 | | /// Executes a new future after this service's future resolves. This does |
113 | | /// not alter the behaviour of the [`poll_ready`] method. |
114 | | /// |
115 | | /// This method can be used to change the [`Response`] type of the service |
116 | | /// into a different type. You can use this method to chain along a computation once the |
117 | | /// service's response has been resolved. |
118 | | /// |
119 | | /// [`Response`]: crate::Service::Response |
120 | | /// [`poll_ready`]: crate::Service::poll_ready |
121 | | /// |
122 | | /// # Example |
123 | | /// ``` |
124 | | /// # use std::task::{Poll, Context}; |
125 | | /// # use tower::{Service, ServiceExt}; |
126 | | /// # |
127 | | /// # struct DatabaseService; |
128 | | /// # impl DatabaseService { |
129 | | /// # fn new(address: &str) -> Self { |
130 | | /// # DatabaseService |
131 | | /// # } |
132 | | /// # } |
133 | | /// # |
134 | | /// # struct Record { |
135 | | /// # pub name: String, |
136 | | /// # pub age: u16 |
137 | | /// # } |
138 | | /// # |
139 | | /// # impl Service<u32> for DatabaseService { |
140 | | /// # type Response = Record; |
141 | | /// # type Error = u8; |
142 | | /// # type Future = std::future::Ready<Result<Record, u8>>; |
143 | | /// # |
144 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
145 | | /// # Poll::Ready(Ok(())) |
146 | | /// # } |
147 | | /// # |
148 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
149 | | /// # std::future::ready(Ok(Record { name: "Jack".into(), age: 32 })) |
150 | | /// # } |
151 | | /// # } |
152 | | /// # |
153 | | /// # async fn avatar_lookup(name: String) -> Result<Vec<u8>, u8> { Ok(vec![]) } |
154 | | /// # |
155 | | /// # fn main() { |
156 | | /// # async { |
157 | | /// // A service returning Result<Record, _> |
158 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
159 | | /// |
160 | | /// // Map the response into a new response |
161 | | /// let mut new_service = service.and_then(|record: Record| async move { |
162 | | /// let name = record.name; |
163 | | /// avatar_lookup(name).await |
164 | | /// }); |
165 | | /// |
166 | | /// // Call the new service |
167 | | /// let id = 13; |
168 | | /// let avatar = new_service.call(id).await.unwrap(); |
169 | | /// # }; |
170 | | /// # } |
171 | | /// ``` |
172 | 0 | fn and_then<F>(self, f: F) -> AndThen<Self, F> |
173 | 0 | where |
174 | 0 | Self: Sized, |
175 | 0 | F: Clone, |
176 | | { |
177 | 0 | AndThen::new(self, f) |
178 | 0 | } |
179 | | |
180 | | /// Maps this service's response value to a different value. This does not |
181 | | /// alter the behaviour of the [`poll_ready`] method. |
182 | | /// |
183 | | /// This method can be used to change the [`Response`] type of the service |
184 | | /// into a different type. It is similar to the [`Result::map`] |
185 | | /// method. You can use this method to chain along a computation once the |
186 | | /// service's response has been resolved. |
187 | | /// |
188 | | /// [`Response`]: crate::Service::Response |
189 | | /// [`poll_ready`]: crate::Service::poll_ready |
190 | | /// |
191 | | /// # Example |
192 | | /// ``` |
193 | | /// # use std::task::{Poll, Context}; |
194 | | /// # use tower::{Service, ServiceExt}; |
195 | | /// # |
196 | | /// # struct DatabaseService; |
197 | | /// # impl DatabaseService { |
198 | | /// # fn new(address: &str) -> Self { |
199 | | /// # DatabaseService |
200 | | /// # } |
201 | | /// # } |
202 | | /// # |
203 | | /// # struct Record { |
204 | | /// # pub name: String, |
205 | | /// # pub age: u16 |
206 | | /// # } |
207 | | /// # |
208 | | /// # impl Service<u32> for DatabaseService { |
209 | | /// # type Response = Record; |
210 | | /// # type Error = u8; |
211 | | /// # type Future = std::future::Ready<Result<Record, u8>>; |
212 | | /// # |
213 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
214 | | /// # Poll::Ready(Ok(())) |
215 | | /// # } |
216 | | /// # |
217 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
218 | | /// # std::future::ready(Ok(Record { name: "Jack".into(), age: 32 })) |
219 | | /// # } |
220 | | /// # } |
221 | | /// # |
222 | | /// # fn main() { |
223 | | /// # async { |
224 | | /// // A service returning Result<Record, _> |
225 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
226 | | /// |
227 | | /// // Map the response into a new response |
228 | | /// let mut new_service = service.map_response(|record| record.name); |
229 | | /// |
230 | | /// // Call the new service |
231 | | /// let id = 13; |
232 | | /// let name = new_service |
233 | | /// .ready() |
234 | | /// .await? |
235 | | /// .call(id) |
236 | | /// .await?; |
237 | | /// # Ok::<(), u8>(()) |
238 | | /// # }; |
239 | | /// # } |
240 | | /// ``` |
241 | 0 | fn map_response<F, Response>(self, f: F) -> MapResponse<Self, F> |
242 | 0 | where |
243 | 0 | Self: Sized, |
244 | 0 | F: FnOnce(Self::Response) -> Response + Clone, |
245 | | { |
246 | 0 | MapResponse::new(self, f) |
247 | 0 | } |
248 | | |
249 | | /// Maps this service's error value to a different value. This does not |
250 | | /// alter the behaviour of the [`poll_ready`] method. |
251 | | /// |
252 | | /// This method can be used to change the [`Error`] type of the service |
253 | | /// into a different type. It is similar to the [`Result::map_err`] method. |
254 | | /// |
255 | | /// [`Error`]: crate::Service::Error |
256 | | /// [`poll_ready`]: crate::Service::poll_ready |
257 | | /// |
258 | | /// # Example |
259 | | /// ``` |
260 | | /// # use std::task::{Poll, Context}; |
261 | | /// # use tower::{Service, ServiceExt}; |
262 | | /// # |
263 | | /// # struct DatabaseService; |
264 | | /// # impl DatabaseService { |
265 | | /// # fn new(address: &str) -> Self { |
266 | | /// # DatabaseService |
267 | | /// # } |
268 | | /// # } |
269 | | /// # |
270 | | /// # struct Error { |
271 | | /// # pub code: u32, |
272 | | /// # pub message: String |
273 | | /// # } |
274 | | /// # |
275 | | /// # impl Service<u32> for DatabaseService { |
276 | | /// # type Response = String; |
277 | | /// # type Error = Error; |
278 | | /// # type Future = std::future::Ready<Result<String, Error>>; |
279 | | /// # |
280 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
281 | | /// # Poll::Ready(Ok(())) |
282 | | /// # } |
283 | | /// # |
284 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
285 | | /// # std::future::ready(Ok(String::new())) |
286 | | /// # } |
287 | | /// # } |
288 | | /// # |
289 | | /// # fn main() { |
290 | | /// # async { |
291 | | /// // A service returning Result<_, Error> |
292 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
293 | | /// |
294 | | /// // Map the error to a new error |
295 | | /// let mut new_service = service.map_err(|err| err.code); |
296 | | /// |
297 | | /// // Call the new service |
298 | | /// let id = 13; |
299 | | /// let code = new_service |
300 | | /// .ready() |
301 | | /// .await? |
302 | | /// .call(id) |
303 | | /// .await |
304 | | /// .unwrap_err(); |
305 | | /// # Ok::<(), u32>(()) |
306 | | /// # }; |
307 | | /// # } |
308 | | /// ``` |
309 | 0 | fn map_err<F, Error>(self, f: F) -> MapErr<Self, F> |
310 | 0 | where |
311 | 0 | Self: Sized, |
312 | 0 | F: FnOnce(Self::Error) -> Error + Clone, |
313 | | { |
314 | 0 | MapErr::new(self, f) |
315 | 0 | } |
316 | | |
317 | | /// Maps this service's result type (`Result<Self::Response, Self::Error>`) |
318 | | /// to a different value, regardless of whether the future succeeds or |
319 | | /// fails. |
320 | | /// |
321 | | /// This is similar to the [`map_response`] and [`map_err`] combinators, |
322 | | /// except that the *same* function is invoked when the service's future |
323 | | /// completes, whether it completes successfully or fails. This function |
324 | | /// takes the [`Result`] returned by the service's future, and returns a |
325 | | /// [`Result`]. |
326 | | /// |
327 | | /// Like the standard library's [`Result::and_then`], this method can be |
328 | | /// used to implement control flow based on `Result` values. For example, it |
329 | | /// may be used to implement error recovery, by turning some [`Err`] |
330 | | /// responses from the service into [`Ok`] responses. Similarly, some |
331 | | /// successful responses from the service could be rejected, by returning an |
332 | | /// [`Err`] conditionally, depending on the value inside the [`Ok`]. Finally, |
333 | | /// this method can also be used to implement behaviors that must run when a |
334 | | /// service's future completes, regardless of whether it succeeded or failed. |
335 | | /// |
336 | | /// This method can be used to change the [`Response`] type of the service |
337 | | /// into a different type. It can also be used to change the [`Error`] type |
338 | | /// of the service. However, because the [`map_result`] function is not applied |
339 | | /// to the errors returned by the service's [`poll_ready`] method, it must |
340 | | /// be possible to convert the service's [`Error`] type into the error type |
341 | | /// returned by the [`map_result`] function. This is trivial when the function |
342 | | /// returns the same error type as the service, but in other cases, it can |
343 | | /// be useful to use [`BoxError`] to erase differing error types. |
344 | | /// |
345 | | /// # Examples |
346 | | /// |
347 | | /// Recovering from certain errors: |
348 | | /// |
349 | | /// ``` |
350 | | /// # use std::task::{Poll, Context}; |
351 | | /// # use tower::{Service, ServiceExt}; |
352 | | /// # |
353 | | /// # struct DatabaseService; |
354 | | /// # impl DatabaseService { |
355 | | /// # fn new(address: &str) -> Self { |
356 | | /// # DatabaseService |
357 | | /// # } |
358 | | /// # } |
359 | | /// # |
360 | | /// # struct Record { |
361 | | /// # pub name: String, |
362 | | /// # pub age: u16 |
363 | | /// # } |
364 | | /// # #[derive(Debug)] |
365 | | /// # enum DbError { |
366 | | /// # Parse(std::num::ParseIntError), |
367 | | /// # NoRecordsFound, |
368 | | /// # } |
369 | | /// # |
370 | | /// # impl Service<u32> for DatabaseService { |
371 | | /// # type Response = Vec<Record>; |
372 | | /// # type Error = DbError; |
373 | | /// # type Future = std::future::Ready<Result<Vec<Record>, DbError>>; |
374 | | /// # |
375 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
376 | | /// # Poll::Ready(Ok(())) |
377 | | /// # } |
378 | | /// # |
379 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
380 | | /// # std::future::ready(Ok(vec![Record { name: "Jack".into(), age: 32 }])) |
381 | | /// # } |
382 | | /// # } |
383 | | /// # |
384 | | /// # fn main() { |
385 | | /// # async { |
386 | | /// // A service returning Result<Vec<Record>, DbError> |
387 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
388 | | /// |
389 | | /// // If the database returns no records for the query, we just want an empty `Vec`. |
390 | | /// let mut new_service = service.map_result(|result| match result { |
391 | | /// // If the error indicates that no records matched the query, return an empty |
392 | | /// // `Vec` instead. |
393 | | /// Err(DbError::NoRecordsFound) => Ok(Vec::new()), |
394 | | /// // Propagate all other responses (`Ok` and `Err`) unchanged |
395 | | /// x => x, |
396 | | /// }); |
397 | | /// |
398 | | /// // Call the new service |
399 | | /// let id = 13; |
400 | | /// let name = new_service |
401 | | /// .ready() |
402 | | /// .await? |
403 | | /// .call(id) |
404 | | /// .await?; |
405 | | /// # Ok::<(), DbError>(()) |
406 | | /// # }; |
407 | | /// # } |
408 | | /// ``` |
409 | | /// |
410 | | /// Rejecting some `Ok` responses: |
411 | | /// |
412 | | /// ``` |
413 | | /// # use std::task::{Poll, Context}; |
414 | | /// # use tower::{Service, ServiceExt}; |
415 | | /// # |
416 | | /// # struct DatabaseService; |
417 | | /// # impl DatabaseService { |
418 | | /// # fn new(address: &str) -> Self { |
419 | | /// # DatabaseService |
420 | | /// # } |
421 | | /// # } |
422 | | /// # |
423 | | /// # struct Record { |
424 | | /// # pub name: String, |
425 | | /// # pub age: u16 |
426 | | /// # } |
427 | | /// # type DbError = String; |
428 | | /// # type AppError = String; |
429 | | /// # |
430 | | /// # impl Service<u32> for DatabaseService { |
431 | | /// # type Response = Record; |
432 | | /// # type Error = DbError; |
433 | | /// # type Future = std::future::Ready<Result<Record, DbError>>; |
434 | | /// # |
435 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
436 | | /// # Poll::Ready(Ok(())) |
437 | | /// # } |
438 | | /// # |
439 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
440 | | /// # std::future::ready(Ok(Record { name: "Jack".into(), age: 32 })) |
441 | | /// # } |
442 | | /// # } |
443 | | /// # |
444 | | /// # fn main() { |
445 | | /// # async { |
446 | | /// use tower::BoxError; |
447 | | /// |
448 | | /// // A service returning Result<Record, DbError> |
449 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
450 | | /// |
451 | | /// // If the user is zero years old, return an error. |
452 | | /// let mut new_service = service.map_result(|result| { |
453 | | /// let record = result?; |
454 | | /// |
455 | | /// if record.age == 0 { |
456 | | /// // Users must have been born to use our app! |
457 | | /// let app_error = AppError::from("users cannot be 0 years old!"); |
458 | | /// |
459 | | /// // Box the error to erase its type (as it can be an `AppError` |
460 | | /// // *or* the inner service's `DbError`). |
461 | | /// return Err(BoxError::from(app_error)); |
462 | | /// } |
463 | | /// |
464 | | /// // Otherwise, return the record. |
465 | | /// Ok(record) |
466 | | /// }); |
467 | | /// |
468 | | /// // Call the new service |
469 | | /// let id = 13; |
470 | | /// let record = new_service |
471 | | /// .ready() |
472 | | /// .await? |
473 | | /// .call(id) |
474 | | /// .await?; |
475 | | /// # Ok::<(), BoxError>(()) |
476 | | /// # }; |
477 | | /// # } |
478 | | /// ``` |
479 | | /// |
480 | | /// Performing an action that must be run for both successes and failures: |
481 | | /// |
482 | | /// ``` |
483 | | /// # use std::convert::TryFrom; |
484 | | /// # use std::task::{Poll, Context}; |
485 | | /// # use tower::{Service, ServiceExt}; |
486 | | /// # |
487 | | /// # struct DatabaseService; |
488 | | /// # impl DatabaseService { |
489 | | /// # fn new(address: &str) -> Self { |
490 | | /// # DatabaseService |
491 | | /// # } |
492 | | /// # } |
493 | | /// # |
494 | | /// # impl Service<u32> for DatabaseService { |
495 | | /// # type Response = String; |
496 | | /// # type Error = u8; |
497 | | /// # type Future = std::future::Ready<Result<String, u8>>; |
498 | | /// # |
499 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
500 | | /// # Poll::Ready(Ok(())) |
501 | | /// # } |
502 | | /// # |
503 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
504 | | /// # std::future::ready(Ok(String::new())) |
505 | | /// # } |
506 | | /// # } |
507 | | /// # |
508 | | /// # fn main() { |
509 | | /// # async { |
510 | | /// // A service returning Result<Record, DbError> |
511 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
512 | | /// |
513 | | /// // Print a message whenever a query completes. |
514 | | /// let mut new_service = service.map_result(|result| { |
515 | | /// println!("query completed; success={}", result.is_ok()); |
516 | | /// result |
517 | | /// }); |
518 | | /// |
519 | | /// // Call the new service |
520 | | /// let id = 13; |
521 | | /// let response = new_service |
522 | | /// .ready() |
523 | | /// .await? |
524 | | /// .call(id) |
525 | | /// .await; |
526 | | /// # response |
527 | | /// # }; |
528 | | /// # } |
529 | | /// ``` |
530 | | /// |
531 | | /// [`map_response`]: ServiceExt::map_response |
532 | | /// [`map_err`]: ServiceExt::map_err |
533 | | /// [`map_result`]: ServiceExt::map_result |
534 | | /// [`Error`]: crate::Service::Error |
535 | | /// [`Response`]: crate::Service::Response |
536 | | /// [`poll_ready`]: crate::Service::poll_ready |
537 | | /// [`BoxError`]: crate::BoxError |
538 | 0 | fn map_result<F, Response, Error>(self, f: F) -> MapResult<Self, F> |
539 | 0 | where |
540 | 0 | Self: Sized, |
541 | 0 | Error: From<Self::Error>, |
542 | 0 | F: FnOnce(Result<Self::Response, Self::Error>) -> Result<Response, Error> + Clone, |
543 | | { |
544 | 0 | MapResult::new(self, f) |
545 | 0 | } |
546 | | |
547 | | /// Composes a function *in front of* the service. |
548 | | /// |
549 | | /// This adapter produces a new service that passes each value through the |
550 | | /// given function `f` before sending it to `self`. |
551 | | /// |
552 | | /// # Example |
553 | | /// ``` |
554 | | /// # use std::convert::TryFrom; |
555 | | /// # use std::task::{Poll, Context}; |
556 | | /// # use tower::{Service, ServiceExt}; |
557 | | /// # |
558 | | /// # struct DatabaseService; |
559 | | /// # impl DatabaseService { |
560 | | /// # fn new(address: &str) -> Self { |
561 | | /// # DatabaseService |
562 | | /// # } |
563 | | /// # } |
564 | | /// # |
565 | | /// # impl Service<String> for DatabaseService { |
566 | | /// # type Response = String; |
567 | | /// # type Error = u8; |
568 | | /// # type Future = std::future::Ready<Result<String, u8>>; |
569 | | /// # |
570 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
571 | | /// # Poll::Ready(Ok(())) |
572 | | /// # } |
573 | | /// # |
574 | | /// # fn call(&mut self, request: String) -> Self::Future { |
575 | | /// # std::future::ready(Ok(String::new())) |
576 | | /// # } |
577 | | /// # } |
578 | | /// # |
579 | | /// # fn main() { |
580 | | /// # async { |
581 | | /// // A service taking a String as a request |
582 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
583 | | /// |
584 | | /// // Map the request to a new request |
585 | | /// let mut new_service = service.map_request(|id: u32| id.to_string()); |
586 | | /// |
587 | | /// // Call the new service |
588 | | /// let id = 13; |
589 | | /// let response = new_service |
590 | | /// .ready() |
591 | | /// .await? |
592 | | /// .call(id) |
593 | | /// .await; |
594 | | /// # response |
595 | | /// # }; |
596 | | /// # } |
597 | | /// ``` |
598 | 0 | fn map_request<F, NewRequest>(self, f: F) -> MapRequest<Self, F> |
599 | 0 | where |
600 | 0 | Self: Sized, |
601 | 0 | F: FnMut(NewRequest) -> Request, |
602 | | { |
603 | 0 | MapRequest::new(self, f) |
604 | 0 | } |
605 | | |
606 | | /// Composes this service with a [`Filter`] that conditionally accepts or |
607 | | /// rejects requests based on a [predicate]. |
608 | | /// |
609 | | /// This adapter produces a new service that passes each value through the |
610 | | /// given function `predicate` before sending it to `self`. |
611 | | /// |
612 | | /// # Example |
613 | | /// ``` |
614 | | /// # use std::convert::TryFrom; |
615 | | /// # use std::task::{Poll, Context}; |
616 | | /// # use tower::{Service, ServiceExt}; |
617 | | /// # |
618 | | /// # struct DatabaseService; |
619 | | /// # impl DatabaseService { |
620 | | /// # fn new(address: &str) -> Self { |
621 | | /// # DatabaseService |
622 | | /// # } |
623 | | /// # } |
624 | | /// # |
625 | | /// # #[derive(Debug)] enum DbError { |
626 | | /// # Parse(std::num::ParseIntError) |
627 | | /// # } |
628 | | /// # |
629 | | /// # impl std::fmt::Display for DbError { |
630 | | /// # fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(self, f) } |
631 | | /// # } |
632 | | /// # impl std::error::Error for DbError {} |
633 | | /// # impl Service<u32> for DatabaseService { |
634 | | /// # type Response = String; |
635 | | /// # type Error = DbError; |
636 | | /// # type Future = std::future::Ready<Result<String, DbError>>; |
637 | | /// # |
638 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
639 | | /// # Poll::Ready(Ok(())) |
640 | | /// # } |
641 | | /// # |
642 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
643 | | /// # std::future::ready(Ok(String::new())) |
644 | | /// # } |
645 | | /// # } |
646 | | /// # |
647 | | /// # fn main() { |
648 | | /// # async { |
649 | | /// // A service taking a u32 as a request and returning Result<_, DbError> |
650 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
651 | | /// |
652 | | /// // Fallibly map the request to a new request |
653 | | /// let mut new_service = service |
654 | | /// .filter(|id_str: &str| id_str.parse().map_err(DbError::Parse)); |
655 | | /// |
656 | | /// // Call the new service |
657 | | /// let id = "13"; |
658 | | /// let response = new_service |
659 | | /// .ready() |
660 | | /// .await? |
661 | | /// .call(id) |
662 | | /// .await; |
663 | | /// # response |
664 | | /// # }; |
665 | | /// # } |
666 | | /// ``` |
667 | | /// |
668 | | /// [`Filter`]: crate::filter::Filter |
669 | | /// [predicate]: crate::filter::Predicate |
670 | | #[cfg(feature = "filter")] |
671 | | fn filter<F, NewRequest>(self, filter: F) -> crate::filter::Filter<Self, F> |
672 | | where |
673 | | Self: Sized, |
674 | | F: crate::filter::Predicate<NewRequest>, |
675 | | { |
676 | | crate::filter::Filter::new(self, filter) |
677 | | } |
678 | | |
679 | | /// Composes this service with an [`AsyncFilter`] that conditionally accepts or |
680 | | /// rejects requests based on an [async predicate]. |
681 | | /// |
682 | | /// This adapter produces a new service that passes each value through the |
683 | | /// given function `predicate` before sending it to `self`. |
684 | | /// |
685 | | /// # Example |
686 | | /// ``` |
687 | | /// # use std::convert::TryFrom; |
688 | | /// # use std::task::{Poll, Context}; |
689 | | /// # use tower::{Service, ServiceExt}; |
690 | | /// # |
691 | | /// # #[derive(Clone)] struct DatabaseService; |
692 | | /// # impl DatabaseService { |
693 | | /// # fn new(address: &str) -> Self { |
694 | | /// # DatabaseService |
695 | | /// # } |
696 | | /// # } |
697 | | /// # #[derive(Debug)] |
698 | | /// # enum DbError { |
699 | | /// # Rejected |
700 | | /// # } |
701 | | /// # impl std::fmt::Display for DbError { |
702 | | /// # fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(self, f) } |
703 | | /// # } |
704 | | /// # impl std::error::Error for DbError {} |
705 | | /// # |
706 | | /// # impl Service<u32> for DatabaseService { |
707 | | /// # type Response = String; |
708 | | /// # type Error = DbError; |
709 | | /// # type Future = std::future::Ready<Result<String, DbError>>; |
710 | | /// # |
711 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
712 | | /// # Poll::Ready(Ok(())) |
713 | | /// # } |
714 | | /// # |
715 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
716 | | /// # std::future::ready(Ok(String::new())) |
717 | | /// # } |
718 | | /// # } |
719 | | /// # |
720 | | /// # fn main() { |
721 | | /// # async { |
722 | | /// // A service taking a u32 as a request and returning Result<_, DbError> |
723 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
724 | | /// |
725 | | /// /// Returns `true` if we should query the database for an ID. |
726 | | /// async fn should_query(id: u32) -> bool { |
727 | | /// // ... |
728 | | /// # true |
729 | | /// } |
730 | | /// |
731 | | /// // Filter requests based on `should_query`. |
732 | | /// let mut new_service = service |
733 | | /// .filter_async(|id: u32| async move { |
734 | | /// if should_query(id).await { |
735 | | /// return Ok(id); |
736 | | /// } |
737 | | /// |
738 | | /// Err(DbError::Rejected) |
739 | | /// }); |
740 | | /// |
741 | | /// // Call the new service |
742 | | /// let id = 13; |
743 | | /// # let id: u32 = id; |
744 | | /// let response = new_service |
745 | | /// .ready() |
746 | | /// .await? |
747 | | /// .call(id) |
748 | | /// .await; |
749 | | /// # response |
750 | | /// # }; |
751 | | /// # } |
752 | | /// ``` |
753 | | /// |
754 | | /// [`AsyncFilter`]: crate::filter::AsyncFilter |
755 | | /// [asynchronous predicate]: crate::filter::AsyncPredicate |
756 | | #[cfg(feature = "filter")] |
757 | | fn filter_async<F, NewRequest>(self, filter: F) -> crate::filter::AsyncFilter<Self, F> |
758 | | where |
759 | | Self: Sized, |
760 | | F: crate::filter::AsyncPredicate<NewRequest>, |
761 | | { |
762 | | crate::filter::AsyncFilter::new(self, filter) |
763 | | } |
764 | | |
765 | | /// Composes an asynchronous function *after* this service. |
766 | | /// |
767 | | /// This takes a function or closure returning a future, and returns a new |
768 | | /// `Service` that chains that function after this service's [`Future`]. The |
769 | | /// new `Service`'s future will consist of this service's future, followed |
770 | | /// by the future returned by calling the chained function with the future's |
771 | | /// [`Output`] type. The chained function is called regardless of whether |
772 | | /// this service's future completes with a successful response or with an |
773 | | /// error. |
774 | | /// |
775 | | /// This method can be thought of as an equivalent to the [`futures` |
776 | | /// crate]'s [`FutureExt::then`] combinator, but acting on `Service`s that |
777 | | /// _return_ futures, rather than on an individual future. Similarly to that |
778 | | /// combinator, [`ServiceExt::then`] can be used to implement asynchronous |
779 | | /// error recovery, by calling some asynchronous function with errors |
780 | | /// returned by this service. Alternatively, it may also be used to call a |
781 | | /// fallible async function with the successful response of this service. |
782 | | /// |
783 | | /// This method can be used to change the [`Response`] type of the service |
784 | | /// into a different type. It can also be used to change the [`Error`] type |
785 | | /// of the service. However, because the `then` function is not applied |
786 | | /// to the errors returned by the service's [`poll_ready`] method, it must |
787 | | /// be possible to convert the service's [`Error`] type into the error type |
788 | | /// returned by the `then` future. This is trivial when the function |
789 | | /// returns the same error type as the service, but in other cases, it can |
790 | | /// be useful to use [`BoxError`] to erase differing error types. |
791 | | /// |
792 | | /// # Examples |
793 | | /// |
794 | | /// ``` |
795 | | /// # use std::task::{Poll, Context}; |
796 | | /// # use tower::{Service, ServiceExt}; |
797 | | /// # |
798 | | /// # struct DatabaseService; |
799 | | /// # impl DatabaseService { |
800 | | /// # fn new(address: &str) -> Self { |
801 | | /// # DatabaseService |
802 | | /// # } |
803 | | /// # } |
804 | | /// # |
805 | | /// # type Record = (); |
806 | | /// # type DbError = (); |
807 | | /// # |
808 | | /// # impl Service<u32> for DatabaseService { |
809 | | /// # type Response = Record; |
810 | | /// # type Error = DbError; |
811 | | /// # type Future = std::future::Ready<Result<Record, DbError>>; |
812 | | /// # |
813 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
814 | | /// # Poll::Ready(Ok(())) |
815 | | /// # } |
816 | | /// # |
817 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
818 | | /// # std::future::ready(Ok(())) |
819 | | /// # } |
820 | | /// # } |
821 | | /// # |
822 | | /// # fn main() { |
823 | | /// // A service returning Result<Record, DbError> |
824 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
825 | | /// |
826 | | /// // An async function that attempts to recover from errors returned by the |
827 | | /// // database. |
828 | | /// async fn recover_from_error(error: DbError) -> Result<Record, DbError> { |
829 | | /// // ... |
830 | | /// # Ok(()) |
831 | | /// } |
832 | | /// # async { |
833 | | /// |
834 | | /// // If the database service returns an error, attempt to recover by |
835 | | /// // calling `recover_from_error`. Otherwise, return the successful response. |
836 | | /// let mut new_service = service.then(|result| async move { |
837 | | /// match result { |
838 | | /// Ok(record) => Ok(record), |
839 | | /// Err(e) => recover_from_error(e).await, |
840 | | /// } |
841 | | /// }); |
842 | | /// |
843 | | /// // Call the new service |
844 | | /// let id = 13; |
845 | | /// let record = new_service |
846 | | /// .ready() |
847 | | /// .await? |
848 | | /// .call(id) |
849 | | /// .await?; |
850 | | /// # Ok::<(), DbError>(()) |
851 | | /// # }; |
852 | | /// # } |
853 | | /// ``` |
854 | | /// |
855 | | /// [`Future`]: crate::Service::Future |
856 | | /// [`Output`]: std::future::Future::Output |
857 | | /// [`futures` crate]: https://docs.rs/futures |
858 | | /// [`FutureExt::then`]: https://docs.rs/futures/latest/futures/future/trait.FutureExt.html#method.then |
859 | | /// [`Error`]: crate::Service::Error |
860 | | /// [`Response`]: crate::Service::Response |
861 | | /// [`poll_ready`]: crate::Service::poll_ready |
862 | | /// [`BoxError`]: crate::BoxError |
863 | 0 | fn then<F, Response, Error, Fut>(self, f: F) -> Then<Self, F> |
864 | 0 | where |
865 | 0 | Self: Sized, |
866 | 0 | Error: From<Self::Error>, |
867 | 0 | F: FnOnce(Result<Self::Response, Self::Error>) -> Fut + Clone, |
868 | 0 | Fut: Future<Output = Result<Response, Error>>, |
869 | | { |
870 | 0 | Then::new(self, f) |
871 | 0 | } |
872 | | |
873 | | /// Composes a function that transforms futures produced by the service. |
874 | | /// |
875 | | /// This takes a function or closure returning a future computed from the future returned by |
876 | | /// the service's [`call`] method, as opposed to the responses produced by the future. |
877 | | /// |
878 | | /// # Examples |
879 | | /// |
880 | | /// ``` |
881 | | /// # use std::task::{Poll, Context}; |
882 | | /// # use tower::{Service, ServiceExt, BoxError}; |
883 | | /// # |
884 | | /// # struct DatabaseService; |
885 | | /// # impl DatabaseService { |
886 | | /// # fn new(address: &str) -> Self { |
887 | | /// # DatabaseService |
888 | | /// # } |
889 | | /// # } |
890 | | /// # |
891 | | /// # type Record = (); |
892 | | /// # type DbError = crate::BoxError; |
893 | | /// # |
894 | | /// # impl Service<u32> for DatabaseService { |
895 | | /// # type Response = Record; |
896 | | /// # type Error = DbError; |
897 | | /// # type Future = std::future::Ready<Result<Record, DbError>>; |
898 | | /// # |
899 | | /// # fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
900 | | /// # Poll::Ready(Ok(())) |
901 | | /// # } |
902 | | /// # |
903 | | /// # fn call(&mut self, request: u32) -> Self::Future { |
904 | | /// # std::future::ready(Ok(())) |
905 | | /// # } |
906 | | /// # } |
907 | | /// # |
908 | | /// # fn main() { |
909 | | /// use std::time::Duration; |
910 | | /// use tokio::time::timeout; |
911 | | /// |
912 | | /// // A service returning Result<Record, DbError> |
913 | | /// let service = DatabaseService::new("127.0.0.1:8080"); |
914 | | /// # async { |
915 | | /// |
916 | | /// let mut new_service = service.map_future(|future| async move { |
917 | | /// let res = timeout(Duration::from_secs(1), future).await?; |
918 | | /// Ok::<_, BoxError>(res) |
919 | | /// }); |
920 | | /// |
921 | | /// // Call the new service |
922 | | /// let id = 13; |
923 | | /// let record = new_service |
924 | | /// .ready() |
925 | | /// .await? |
926 | | /// .call(id) |
927 | | /// .await?; |
928 | | /// # Ok::<(), BoxError>(()) |
929 | | /// # }; |
930 | | /// # } |
931 | | /// ``` |
932 | | /// |
933 | | /// Note that normally you wouldn't implement timeouts like this and instead use [`Timeout`]. |
934 | | /// |
935 | | /// [`call`]: crate::Service::call |
936 | | /// [`Timeout`]: crate::timeout::Timeout |
937 | 0 | fn map_future<F, Fut, Response, Error>(self, f: F) -> MapFuture<Self, F> |
938 | 0 | where |
939 | 0 | Self: Sized, |
940 | 0 | F: FnMut(Self::Future) -> Fut, |
941 | 0 | Error: From<Self::Error>, |
942 | 0 | Fut: Future<Output = Result<Response, Error>>, |
943 | | { |
944 | 0 | MapFuture::new(self, f) |
945 | 0 | } Unexecuted instantiation: <tonic::transport::channel::service::add_origin::AddOrigin<tonic::transport::channel::service::user_agent::UserAgent<tonic::transport::service::grpc_timeout::GrpcTimeout<tower::util::either::Either<tower::limit::concurrency::service::ConcurrencyLimit<tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>>, tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>>>>> as tower::util::ServiceExt<http::request::Request<tonic::body::Body>>>::map_future::<<tower::util::boxed::sync::BoxService<http::request::Request<tonic::body::Body>, http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>>::new<tonic::transport::channel::service::add_origin::AddOrigin<tonic::transport::channel::service::user_agent::UserAgent<tonic::transport::service::grpc_timeout::GrpcTimeout<tower::util::either::Either<tower::limit::concurrency::service::ConcurrencyLimit<tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>>, tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<tonic::transport::channel::uds_connector::UdsConnector>>, http::uri::Uri>>>>>>>::{closure#0}, core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>> + core::marker::Send>>, http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>Unexecuted instantiation: <tonic::transport::channel::service::add_origin::AddOrigin<tonic::transport::channel::service::user_agent::UserAgent<tonic::transport::service::grpc_timeout::GrpcTimeout<tower::util::either::Either<tower::limit::concurrency::service::ConcurrencyLimit<tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>>, tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>>>>> as tower::util::ServiceExt<http::request::Request<tonic::body::Body>>>::map_future::<<tower::util::boxed::sync::BoxService<http::request::Request<tonic::body::Body>, http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>>::new<tonic::transport::channel::service::add_origin::AddOrigin<tonic::transport::channel::service::user_agent::UserAgent<tonic::transport::service::grpc_timeout::GrpcTimeout<tower::util::either::Either<tower::limit::concurrency::service::ConcurrencyLimit<tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>>, tower::util::either::Either<tower::limit::rate::service::RateLimit<tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>, tonic::transport::channel::service::reconnect::Reconnect<tonic::transport::channel::service::connection::MakeSendRequestService<tonic::transport::channel::service::connector::Connector<hyper_util::client::legacy::connect::http::HttpConnector>>, http::uri::Uri>>>>>>>::{closure#0}, core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>> + core::marker::Send>>, http::response::Response<tonic::body::Body>, alloc::boxed::Box<dyn core::error::Error + core::marker::Send + core::marker::Sync>>Unexecuted instantiation: <axum::util::MapIntoResponse<axum::handler::service::HandlerService<tonic::service::router::unimplemented, ((),), ()>> as tower::util::ServiceExt<http::request::Request<axum_core::body::Body>>>::map_future::<<tower::util::boxed_clone_sync::BoxCloneSyncService<http::request::Request<axum_core::body::Body>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>>::new<axum::util::MapIntoResponse<axum::handler::service::HandlerService<tonic::service::router::unimplemented, ((),), ()>>>::{closure#0}, core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<http::response::Response<axum_core::body::Body>, core::convert::Infallible>> + core::marker::Send>>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>Unexecuted instantiation: <axum::util::MapIntoResponse<tower::util::service_fn::ServiceFn<<axum::routing::method_routing::MethodRouter>::new::{closure#0}>> as tower::util::ServiceExt<http::request::Request<axum_core::body::Body>>>::map_future::<<tower::util::boxed_clone_sync::BoxCloneSyncService<http::request::Request<axum_core::body::Body>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>>::new<axum::util::MapIntoResponse<tower::util::service_fn::ServiceFn<<axum::routing::method_routing::MethodRouter>::new::{closure#0}>>>::{closure#0}, core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<http::response::Response<axum_core::body::Body>, core::convert::Infallible>> + core::marker::Send>>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>Unexecuted instantiation: <axum::util::MapIntoResponse<axum::routing::not_found::NotFound> as tower::util::ServiceExt<http::request::Request<axum_core::body::Body>>>::map_future::<<tower::util::boxed_clone_sync::BoxCloneSyncService<http::request::Request<axum_core::body::Body>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>>::new<axum::util::MapIntoResponse<axum::routing::not_found::NotFound>>::{closure#0}, core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future<Output = core::result::Result<http::response::Response<axum_core::body::Body>, core::convert::Infallible>> + core::marker::Send>>, http::response::Response<axum_core::body::Body>, core::convert::Infallible>Unexecuted instantiation: <_ as tower::util::ServiceExt<_>>::map_future::<_, _, _, _> |
946 | | |
947 | | /// Convert the service into a [`Service`] + [`Send`] trait object. |
948 | | /// |
949 | | /// See [`BoxService`] for more details. |
950 | | /// |
951 | | /// If `Self` implements the [`Clone`] trait, the [`boxed_clone`] method |
952 | | /// can be used instead, to produce a boxed service which will also |
953 | | /// implement [`Clone`]. |
954 | | /// |
955 | | /// # Example |
956 | | /// |
957 | | /// ``` |
958 | | /// use tower::{Service, ServiceExt, BoxError, service_fn, util::BoxService}; |
959 | | /// # |
960 | | /// # struct Request; |
961 | | /// # struct Response; |
962 | | /// # impl Response { |
963 | | /// # fn new() -> Self { Self } |
964 | | /// # } |
965 | | /// |
966 | | /// let service = service_fn(|req: Request| async { |
967 | | /// Ok::<_, BoxError>(Response::new()) |
968 | | /// }); |
969 | | /// |
970 | | /// let service: BoxService<Request, Response, BoxError> = service |
971 | | /// .map_request(|req| { |
972 | | /// println!("received request"); |
973 | | /// req |
974 | | /// }) |
975 | | /// .map_response(|res| { |
976 | | /// println!("response produced"); |
977 | | /// res |
978 | | /// }) |
979 | | /// .boxed(); |
980 | | /// # let service = assert_service(service); |
981 | | /// # fn assert_service<S, R>(svc: S) -> S |
982 | | /// # where S: Service<R> { svc } |
983 | | /// ``` |
984 | | /// |
985 | | /// [`Service`]: crate::Service |
986 | | /// [`boxed_clone`]: Self::boxed_clone |
987 | 0 | fn boxed(self) -> BoxService<Request, Self::Response, Self::Error> |
988 | 0 | where |
989 | 0 | Self: Sized + Send + 'static, |
990 | 0 | Self::Future: Send + 'static, |
991 | | { |
992 | 0 | BoxService::new(self) |
993 | 0 | } |
994 | | |
995 | | /// Convert the service into a [`Service`] + [`Clone`] + [`Send`] trait object. |
996 | | /// |
997 | | /// This is similar to the [`boxed`] method, but it requires that `Self` implement |
998 | | /// [`Clone`], and the returned boxed service implements [`Clone`]. |
999 | | /// See [`BoxCloneService`] for more details. |
1000 | | /// |
1001 | | /// # Example |
1002 | | /// |
1003 | | /// ``` |
1004 | | /// use tower::{Service, ServiceExt, BoxError, service_fn, util::BoxCloneService}; |
1005 | | /// # |
1006 | | /// # struct Request; |
1007 | | /// # struct Response; |
1008 | | /// # impl Response { |
1009 | | /// # fn new() -> Self { Self } |
1010 | | /// # } |
1011 | | /// |
1012 | | /// let service = service_fn(|req: Request| async { |
1013 | | /// Ok::<_, BoxError>(Response::new()) |
1014 | | /// }); |
1015 | | /// |
1016 | | /// let service: BoxCloneService<Request, Response, BoxError> = service |
1017 | | /// .map_request(|req| { |
1018 | | /// println!("received request"); |
1019 | | /// req |
1020 | | /// }) |
1021 | | /// .map_response(|res| { |
1022 | | /// println!("response produced"); |
1023 | | /// res |
1024 | | /// }) |
1025 | | /// .boxed_clone(); |
1026 | | /// |
1027 | | /// // The boxed service can still be cloned. |
1028 | | /// service.clone(); |
1029 | | /// # let service = assert_service(service); |
1030 | | /// # fn assert_service<S, R>(svc: S) -> S |
1031 | | /// # where S: Service<R> { svc } |
1032 | | /// ``` |
1033 | | /// |
1034 | | /// [`Service`]: crate::Service |
1035 | | /// [`boxed`]: Self::boxed |
1036 | 0 | fn boxed_clone(self) -> BoxCloneService<Request, Self::Response, Self::Error> |
1037 | 0 | where |
1038 | 0 | Self: Clone + Sized + Send + 'static, |
1039 | 0 | Self::Future: Send + 'static, |
1040 | | { |
1041 | 0 | BoxCloneService::new(self) |
1042 | 0 | } |
1043 | | } |
1044 | | |
1045 | | impl<T: ?Sized, Request> ServiceExt<Request> for T where T: tower_service::Service<Request> {} |
1046 | | |
1047 | | /// Convert an `Option<Layer>` into a [`Layer`]. |
1048 | | /// |
1049 | | /// ``` |
1050 | | /// # use std::time::Duration; |
1051 | | /// # use tower::Service; |
1052 | | /// # use tower::builder::ServiceBuilder; |
1053 | | /// use tower::util::option_layer; |
1054 | | /// # use tower::timeout::TimeoutLayer; |
1055 | | /// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send { |
1056 | | /// # let timeout = Some(Duration::new(10, 0)); |
1057 | | /// // Layer to apply a timeout if configured |
1058 | | /// let maybe_timeout = option_layer(timeout.map(TimeoutLayer::new)); |
1059 | | /// |
1060 | | /// ServiceBuilder::new() |
1061 | | /// .layer(maybe_timeout) |
1062 | | /// .service(svc); |
1063 | | /// # } |
1064 | | /// ``` |
1065 | | /// |
1066 | | /// [`Layer`]: crate::layer::Layer |
1067 | 0 | pub fn option_layer<L>(layer: Option<L>) -> Either<L, Identity> { |
1068 | 0 | if let Some(layer) = layer { |
1069 | 0 | Either::Left(layer) |
1070 | | } else { |
1071 | 0 | Either::Right(Identity::new()) |
1072 | | } |
1073 | 0 | } Unexecuted instantiation: tower::util::option_layer::<tower::limit::concurrency::layer::ConcurrencyLimitLayer> Unexecuted instantiation: tower::util::option_layer::<tower::limit::rate::layer::RateLimitLayer> Unexecuted instantiation: tower::util::option_layer::<_> |