mirror of
https://github.com/Noratrieb/101844-repro.git
synced 2026-01-14 14:25:02 +01:00
no build
This commit is contained in:
parent
f5f20836d4
commit
fa88e78ef7
6 changed files with 0 additions and 1477 deletions
|
|
@ -1,418 +0,0 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# Unreleased
|
||||
|
||||
- None.
|
||||
|
||||
# 0.4.13 (June 17, 2022)
|
||||
|
||||
### Added
|
||||
|
||||
- **load_shed**: Public constructor for `Overloaded` error ([#661])
|
||||
|
||||
### Fixed
|
||||
|
||||
- **util**: Fix hang with `call_all` when the `Stream` of requests is pending
|
||||
([#656])
|
||||
- **ready_cache**: Ensure cancelation is observed by pending services ([#668],
|
||||
fixes [#415])
|
||||
- **docs**: Fix a missing section header due to a typo ([#646])
|
||||
- **docs**: Fix broken links to `Service` trait ([#659])
|
||||
|
||||
|
||||
[#661]: https://github.com/tower-rs/tower/pull/661
|
||||
[#656]: https://github.com/tower-rs/tower/pull/656
|
||||
[#668]: https://github.com/tower-rs/tower/pull/668
|
||||
[#415]: https://github.com/tower-rs/tower/pull/415
|
||||
[#646]: https://github.com/tower-rs/tower/pull/646
|
||||
[#659]: https://github.com/tower-rs/tower/pull/659
|
||||
|
||||
# 0.4.12 (February 16, 2022)
|
||||
|
||||
### Fixed
|
||||
|
||||
- **hedge**, **load**, **retry**: Fix use of `Instant` operations that can panic
|
||||
on platforms where `Instant` is not monotonic ([#633])
|
||||
- Disable `attributes` feature on `tracing` dependency ([#623])
|
||||
- Remove unused dependencies and dependency features with some feature
|
||||
combinations ([#603], [#602])
|
||||
- **docs**: Fix a typo in the RustDoc for `Buffer` ([#622])
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated minimum supported Rust version (MSRV) to 1.49.0.
|
||||
- **hedge**: Updated `hdrhistogram` dependency to v7.0 ([#602])
|
||||
- Updated `tokio-util` dependency to v0.7 ([#638])
|
||||
|
||||
[#633]: https://github.com/tower-rs/tower/pull/633
|
||||
[#623]: https://github.com/tower-rs/tower/pull/623
|
||||
[#603]: https://github.com/tower-rs/tower/pull/603
|
||||
[#602]: https://github.com/tower-rs/tower/pull/602
|
||||
[#622]: https://github.com/tower-rs/tower/pull/622
|
||||
[#638]: https://github.com/tower-rs/tower/pull/638
|
||||
|
||||
# 0.4.11 (November 18, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- **util**: Add `BoxCloneService` which is a `Clone + Send` boxed `Service` ([#615])
|
||||
- **util**: Add `ServiceExt::boxed` and `ServiceExt::boxed_clone` for applying the
|
||||
`BoxService` and `BoxCloneService` middleware ([#616])
|
||||
- **builder**: Add `ServiceBuilder::boxed` and `ServiceBuilder::boxed_clone` for
|
||||
applying `BoxService` and `BoxCloneService` layers ([#616])
|
||||
|
||||
### Fixed
|
||||
|
||||
- **util**: Remove redundant `F: Clone` bound from `ServiceExt::map_request` ([#607])
|
||||
- **util**: Remove unnecessary `Debug` bounds from `impl Debug for BoxService` ([#617])
|
||||
- **util**: Remove unnecessary `Debug` bounds from `impl Debug for UnsyncBoxService` ([#617])
|
||||
- **balance**: Remove redundant `Req: Clone` bound from `Clone` impls
|
||||
for `MakeBalance`, and `MakeBalanceLayer` ([#607])
|
||||
- **balance**: Remove redundant `Req: Debug` bound from `Debug` impls
|
||||
for `MakeBalance`, `MakeFuture`, `Balance`, and `Pool` ([#607])
|
||||
- **ready-cache**: Remove redundant `Req: Debug` bound from `Debug` impl
|
||||
for `ReadyCache` ([#607])
|
||||
- **steer**: Remove redundant `Req: Debug` bound from `Debug` impl
|
||||
for `Steer` ([#607])
|
||||
- **docs**: Fix `doc(cfg(...))` attributes
|
||||
of `PeakEwmaDiscover`, and `PendingRequestsDiscover` ([#610])
|
||||
|
||||
[#607]: https://github.com/tower-rs/tower/pull/607
|
||||
[#610]: https://github.com/tower-rs/tower/pull/610
|
||||
[#615]: https://github.com/tower-rs/tower/pull/615
|
||||
[#616]: https://github.com/tower-rs/tower/pull/616
|
||||
[#617]: https://github.com/tower-rs/tower/pull/617
|
||||
|
||||
# 0.4.10 (October 19, 2021)
|
||||
|
||||
- Fix accidental breaking change when using the
|
||||
`rustdoc::broken_intra_doc_links` lint ([#605])
|
||||
- Clarify that tower's minimum supported rust version is 1.46 ([#605])
|
||||
|
||||
[#605]: https://github.com/tower-rs/tower/pull/605
|
||||
|
||||
# 0.4.9 (October 13, 2021)
|
||||
|
||||
- Migrate to [pin-project-lite] ([#595])
|
||||
- **builder**: Implement `Layer` for `ServiceBuilder` ([#600])
|
||||
- **builder**: Add `ServiceBuilder::and_then` analogous to
|
||||
`ServiceExt::and_then` ([#601])
|
||||
|
||||
[#600]: https://github.com/tower-rs/tower/pull/600
|
||||
[#601]: https://github.com/tower-rs/tower/pull/601
|
||||
[#595]: https://github.com/tower-rs/tower/pull/595
|
||||
[pin-project-lite]: https://crates.io/crates/pin-project-lite
|
||||
|
||||
# 0.4.8 (May 28, 2021)
|
||||
|
||||
- **builder**: Add `ServiceBuilder::map_result` analogous to
|
||||
`ServiceExt::map_result` ([#583])
|
||||
- **limit**: Add `GlobalConcurrencyLimitLayer` to allow reusing a concurrency
|
||||
limit across multiple services ([#574])
|
||||
|
||||
[#574]: https://github.com/tower-rs/tower/pull/574
|
||||
[#583]: https://github.com/tower-rs/tower/pull/583
|
||||
|
||||
# 0.4.7 (April 27, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- **builder**: Add `ServiceBuilder::check_service` to check the request,
|
||||
response, and error types of the output service. ([#576])
|
||||
- **builder**: Add `ServiceBuilder::check_service_clone` to check the output
|
||||
service can be cloned. ([#576])
|
||||
|
||||
### Fixed
|
||||
|
||||
- **spawn_ready**: Abort spawned background tasks when the `SpawnReady` service
|
||||
is dropped, fixing a potential task/resource leak (#[581])
|
||||
- Fixed broken documentation links ([#578])
|
||||
|
||||
[#576]: https://github.com/tower-rs/tower/pull/576
|
||||
[#578]: https://github.com/tower-rs/tower/pull/578
|
||||
[#581]: https://github.com/tower-rs/tower/pull/581
|
||||
|
||||
# 0.4.6 (February 26, 2021)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- **util**: Deprecated `ServiceExt::ready_and` (renamed to `ServiceExt::ready`).
|
||||
([#567])
|
||||
- **util**: Deprecated `ReadyAnd` future (renamed to `Ready`). ([#567])
|
||||
### Added
|
||||
|
||||
- **builder**: Add `ServiceBuilder::layer_fn` to add a layer built from a
|
||||
function. ([#560])
|
||||
- **builder**: Add `ServiceBuilder::map_future` for transforming the futures
|
||||
produced by a service. ([#559])
|
||||
- **builder**: Add `ServiceBuilder::service_fn` for applying `Layer`s to an
|
||||
async function using `util::service_fn`. ([#564])
|
||||
- **util**: Add example for `service_fn`. ([#563])
|
||||
- **util**: Add `BoxLayer` for creating boxed `Layer` trait objects. ([#569])
|
||||
|
||||
[#567]: https://github.com/tower-rs/tower/pull/567
|
||||
[#560]: https://github.com/tower-rs/tower/pull/560
|
||||
[#559]: https://github.com/tower-rs/tower/pull/559
|
||||
[#564]: https://github.com/tower-rs/tower/pull/564
|
||||
[#563]: https://github.com/tower-rs/tower/pull/563
|
||||
[#569]: https://github.com/tower-rs/tower/pull/569
|
||||
|
||||
# 0.4.5 (February 10, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- **util**: Add `ServiceExt::map_future`. ([#542])
|
||||
- **builder**: Add `ServiceBuilder::option_layer` to optionally add a layer. ([#555])
|
||||
- **make**: Add `Shared` which lets you implement `MakeService` by cloning a
|
||||
service. ([#533])
|
||||
|
||||
### Fixed
|
||||
|
||||
- **util**: Make combinators that contain closures implement `Debug`. They
|
||||
previously wouldn't since closures never implement `Debug`. ([#552])
|
||||
- **steer**: Implement `Clone` for `Steer`. ([#554])
|
||||
- **spawn-ready**: SpawnReady now propagates the current `tracing` span to
|
||||
spawned tasks ([#557])
|
||||
- Only pull in `tracing` for the features that need it. ([#551])
|
||||
|
||||
[#542]: https://github.com/tower-rs/tower/pull/542
|
||||
[#555]: https://github.com/tower-rs/tower/pull/555
|
||||
[#557]: https://github.com/tower-rs/tower/pull/557
|
||||
[#533]: https://github.com/tower-rs/tower/pull/533
|
||||
[#551]: https://github.com/tower-rs/tower/pull/551
|
||||
[#554]: https://github.com/tower-rs/tower/pull/554
|
||||
[#552]: https://github.com/tower-rs/tower/pull/552
|
||||
|
||||
# 0.4.4 (January 20, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- **util**: Implement `Layer` for `Either<A, B>`. ([#531])
|
||||
- **util**: Implement `Clone` for `FilterLayer`. ([#535])
|
||||
- **timeout**: Implement `Clone` for `TimeoutLayer`. ([#535])
|
||||
- **limit**: Implement `Clone` for `RateLimitLayer`. ([#535])
|
||||
|
||||
### Fixed
|
||||
|
||||
- Added "full" feature which turns on all other features. ([#532])
|
||||
- **spawn-ready**: Avoid oneshot allocations. ([#538])
|
||||
|
||||
[#531]: https://github.com/tower-rs/tower/pull/531
|
||||
[#532]: https://github.com/tower-rs/tower/pull/532
|
||||
[#535]: https://github.com/tower-rs/tower/pull/535
|
||||
[#538]: https://github.com/tower-rs/tower/pull/538
|
||||
|
||||
# 0.4.3 (January 13, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- **filter**: `Filter::check` and `AsyncFilter::check` methods which check a
|
||||
request against the filter's `Predicate` ([#521])
|
||||
- **filter**: Added `get_ref`, `get_mut`, and `into_inner` methods to `Filter`
|
||||
and `AsyncFilter`, allowing access to the wrapped service ([#522])
|
||||
- **util**: Added `layer` associated function to `AndThen`, `Then`,
|
||||
`MapRequest`, `MapResponse`, and `MapResult` types. These return a `Layer`
|
||||
that produces middleware of that type, as a convenience to avoid having to
|
||||
import the `Layer` type separately. ([#524])
|
||||
- **util**: Added missing `Clone` impls to `AndThenLayer`, `MapRequestLayer`,
|
||||
and `MapErrLayer`, when the mapped function implements `Clone` ([#525])
|
||||
- **util**: Added `FutureService::new` constructor, with less restrictive bounds
|
||||
than the `future_service` free function ([#523])
|
||||
|
||||
[#521]: https://github.com/tower-rs/tower/pull/521
|
||||
[#522]: https://github.com/tower-rs/tower/pull/522
|
||||
[#523]: https://github.com/tower-rs/tower/pull/523
|
||||
[#524]: https://github.com/tower-rs/tower/pull/524
|
||||
[#525]: https://github.com/tower-rs/tower/pull/525
|
||||
|
||||
# 0.4.2 (January 11, 2021)
|
||||
|
||||
### Added
|
||||
|
||||
- Export `layer_fn` and `LayerFn` from the `tower::layer` module. ([#516])
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix missing `Sync` implementation for `Buffer` and `ConcurrencyLimit` ([#518])
|
||||
|
||||
[#518]: https://github.com/tower-rs/tower/pull/518
|
||||
[#516]: https://github.com/tower-rs/tower/pull/516
|
||||
|
||||
# 0.4.1 (January 7, 2021)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Updated `tower-layer` to 0.3.1 to fix broken re-exports.
|
||||
|
||||
# 0.4.0 (January 7, 2021)
|
||||
|
||||
This is a major breaking release including a large number of changes. In
|
||||
particular, this release updates `tower` to depend on Tokio 1.0, and moves all
|
||||
middleware into the `tower` crate. In addition, Tower 0.4 reworks several
|
||||
middleware APIs, as well as introducing new ones.
|
||||
|
||||
This release does *not* change the core `Service` or `Layer` traits, so `tower`
|
||||
0.4 still depends on `tower-service` 0.3 and `tower-layer` 0.3. This means that
|
||||
`tower` 0.4 is still compatible with libraries that depend on those crates.
|
||||
|
||||
### Added
|
||||
|
||||
- **make**: Added `MakeService::into_service` and `MakeService::as_service` for
|
||||
converting `MakeService`s into `Service`s ([#492])
|
||||
- **steer**: Added `steer` middleware for routing requests to one of a set of
|
||||
services ([#426])
|
||||
- **util**: Added `MapRequest` middleware and `ServiceExt::map_request`, for
|
||||
applying a function to a request before passing it to the inner service
|
||||
([#435])
|
||||
- **util**: Added `MapResponse` middleware and `ServiceExt::map_response`, for
|
||||
applying a function to the `Response` type of an inner service after its
|
||||
future completes ([#435])
|
||||
- **util**: Added `MapErr` middleware and `ServiceExt::map_err`, for
|
||||
applying a function to the `Error` returned by an inner service if it fails
|
||||
([#396])
|
||||
- **util**: Added `MapResult` middleware and `ServiceExt::map_result`, for
|
||||
applying a function to the `Result` returned by an inner service's future
|
||||
regardless of whether it succeeds or fails ([#499])
|
||||
- **util**: Added `Then` middleware and `ServiceExt::then`, for chaining another
|
||||
future after an inner service's future completes (with a `Response` or an
|
||||
`Error`) ([#500])
|
||||
- **util**: Added `AndThen` middleware and `ServiceExt::and_then`, for
|
||||
chaining another future after an inner service's future completes successfully
|
||||
([#485])
|
||||
- **util**: Added `layer_fn`, for constructing a `Layer` from a function taking
|
||||
a `Service` and returning a different `Service` ([#491])
|
||||
- **util**: Added `FutureService`, which implements `Service` for a
|
||||
`Future` whose `Output` type is a `Service` ([#496])
|
||||
- **util**: Added `BoxService::layer` and `UnsyncBoxService::layer`, to make
|
||||
constructing layers more ergonomic ([#503])
|
||||
- **layer**: Added `Layer` impl for `&Layer` ([#446])
|
||||
- **retry**: Added `Retry::get_ref`, `Retry::get_mut`, and `Retry::into_inner`
|
||||
to access the inner service ([#463])
|
||||
- **timeout**: Added `Timeout::get_ref`, `Timeout::get_mut`, and
|
||||
`Timeout::into_inner` to access the inner service ([#463])
|
||||
- **buffer**: Added `Clone` and `Copy` impls for `BufferLayer` (#[493])
|
||||
- Several documentation improvements ([#442], [#444], [#445], [#449], [#487],
|
||||
[#490], [#506]])
|
||||
|
||||
### Changed
|
||||
|
||||
- All middleware `tower-*` crates were merged into `tower` and placed
|
||||
behind feature flags ([#432])
|
||||
- Updated Tokio dependency to 1.0 ([#489])
|
||||
- **builder**: Make `ServiceBuilder::service` take `self` by reference rather
|
||||
than by value ([#504])
|
||||
- **reconnect**: Return errors from `MakeService` in the response future, rather than
|
||||
in `poll_ready`, allowing the reconnect service to be reused when a reconnect
|
||||
fails ([#386], [#437])
|
||||
- **discover**: Changed `Discover` to be a sealed trait alias for a
|
||||
`TryStream<Item = Change>`. `Discover` implementations are now written by
|
||||
implementing `Stream`. ([#443])
|
||||
- **load**: Renamed the `Instrument` trait to `TrackCompletion` ([#445])
|
||||
- **load**: Renamed `NoInstrument` to `CompleteOnResponse` ([#445])
|
||||
- **balance**: Renamed `BalanceLayer` to `MakeBalanceLayer` ([#449])
|
||||
- **balance**: Renamed `BalanceMake` to `MakeBalance` ([#449])
|
||||
- **ready-cache**: Changed `ready_cache::error::Failed`'s `fmt::Debug` impl to
|
||||
require the key type to also implement `fmt::Debug` ([#467])
|
||||
- **filter**: Changed `Filter` and `Predicate` to use a synchronous function as
|
||||
a predicate ([#508])
|
||||
- **filter**: Renamed the previous `Filter` and `Predicate` (where `Predicate`s
|
||||
returned a `Future`) to `AsyncFilter` and `AsyncPredicate` ([#508])
|
||||
- **filter**: `Predicate`s now take a `Request` type by value and may return a
|
||||
new request, potentially of a different type ([#508])
|
||||
- **filter**: `Predicate`s may now return an error of any type ([#508])
|
||||
|
||||
### Fixed
|
||||
|
||||
- **limit**: Fixed an issue where `RateLimit` services do not reset the remaining
|
||||
count when rate limiting ([#438], [#439])
|
||||
- **util**: Fixed a bug where `oneshot` futures panic if the service does not
|
||||
immediately become ready ([#447])
|
||||
- **ready-cache**: Fixed `ready_cache::error::Failed` not returning inner error types
|
||||
via `Error::source` ([#467])
|
||||
- **hedge**: Fixed an interaction with `buffer` where `buffer` slots were
|
||||
eagerly reserved for hedge requests even if they were not sent ([#472])
|
||||
- **hedge**: Fixed the use of a fixed 10 second bound on the hedge latency
|
||||
histogram resulting on errors with longer-lived requests. The latency
|
||||
histogram now automatically resizes ([#484])
|
||||
- **buffer**: Fixed an issue where tasks waiting for buffer capacity were not
|
||||
woken when a buffer is dropped, potentially resulting in a task leak ([#480])
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `ServiceExt::ready`.
|
||||
- **discover**: Removed `discover::stream` module, since `Discover` is now an
|
||||
alias for `Stream` ([#443])
|
||||
- **buffer**: Removed `MakeBalance::from_rng`, which caused all balancers to use
|
||||
the same RNG ([#497])
|
||||
|
||||
[#432]: https://github.com/tower-rs/tower/pull/432
|
||||
[#426]: https://github.com/tower-rs/tower/pull/426
|
||||
[#435]: https://github.com/tower-rs/tower/pull/435
|
||||
[#499]: https://github.com/tower-rs/tower/pull/499
|
||||
[#386]: https://github.com/tower-rs/tower/pull/386
|
||||
[#437]: https://github.com/tower-rs/tower/pull/487
|
||||
[#438]: https://github.com/tower-rs/tower/pull/438
|
||||
[#437]: https://github.com/tower-rs/tower/pull/439
|
||||
[#443]: https://github.com/tower-rs/tower/pull/443
|
||||
[#442]: https://github.com/tower-rs/tower/pull/442
|
||||
[#444]: https://github.com/tower-rs/tower/pull/444
|
||||
[#445]: https://github.com/tower-rs/tower/pull/445
|
||||
[#446]: https://github.com/tower-rs/tower/pull/446
|
||||
[#447]: https://github.com/tower-rs/tower/pull/447
|
||||
[#449]: https://github.com/tower-rs/tower/pull/449
|
||||
[#463]: https://github.com/tower-rs/tower/pull/463
|
||||
[#396]: https://github.com/tower-rs/tower/pull/396
|
||||
[#467]: https://github.com/tower-rs/tower/pull/467
|
||||
[#472]: https://github.com/tower-rs/tower/pull/472
|
||||
[#480]: https://github.com/tower-rs/tower/pull/480
|
||||
[#484]: https://github.com/tower-rs/tower/pull/484
|
||||
[#489]: https://github.com/tower-rs/tower/pull/489
|
||||
[#497]: https://github.com/tower-rs/tower/pull/497
|
||||
[#487]: https://github.com/tower-rs/tower/pull/487
|
||||
[#493]: https://github.com/tower-rs/tower/pull/493
|
||||
[#491]: https://github.com/tower-rs/tower/pull/491
|
||||
[#495]: https://github.com/tower-rs/tower/pull/495
|
||||
[#503]: https://github.com/tower-rs/tower/pull/503
|
||||
[#504]: https://github.com/tower-rs/tower/pull/504
|
||||
[#492]: https://github.com/tower-rs/tower/pull/492
|
||||
[#500]: https://github.com/tower-rs/tower/pull/500
|
||||
[#490]: https://github.com/tower-rs/tower/pull/490
|
||||
[#506]: https://github.com/tower-rs/tower/pull/506
|
||||
[#508]: https://github.com/tower-rs/tower/pull/508
|
||||
[#485]: https://github.com/tower-rs/tower/pull/485
|
||||
|
||||
# 0.3.1 (January 17, 2020)
|
||||
|
||||
- Allow opting out of tracing/log (#410).
|
||||
|
||||
# 0.3.0 (December 19, 2019)
|
||||
|
||||
- Update all tower based crates to `0.3`.
|
||||
- Update to `tokio 0.2`
|
||||
- Update to `futures 0.3`
|
||||
|
||||
# 0.3.0-alpha.2 (September 30, 2019)
|
||||
|
||||
- Move to `futures-*-preview 0.3.0-alpha.19`
|
||||
- Move to `pin-project 0.4`
|
||||
|
||||
# 0.3.0-alpha.1a (September 13, 2019)
|
||||
|
||||
- Update `tower-buffer` to `0.3.0-alpha.1b`
|
||||
|
||||
# 0.3.0-alpha.1 (September 11, 2019)
|
||||
|
||||
- Move to `std::future`
|
||||
|
||||
# 0.1.1 (July 19, 2019)
|
||||
|
||||
- Add `ServiceBuilder::into_inner`
|
||||
|
||||
# 0.1.0 (April 26, 2019)
|
||||
|
||||
- Initial release
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
Copyright (c) 2019 Tower Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
# Tower
|
||||
|
||||
Tower is a library of modular and reusable components for building robust
|
||||
networking clients and servers.
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![Documentation][docs-badge]][docs-url]
|
||||
[![Documentation (master)][docs-master-badge]][docs-master-url]
|
||||
[![MIT licensed][mit-badge]][mit-url]
|
||||
[![Build Status][actions-badge]][actions-url]
|
||||
[![Discord chat][discord-badge]][discord-url]
|
||||
|
||||
[crates-badge]: https://img.shields.io/crates/v/tower.svg
|
||||
[crates-url]: https://crates.io/crates/tower
|
||||
[docs-badge]: https://docs.rs/tower/badge.svg
|
||||
[docs-url]: https://docs.rs/tower
|
||||
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
|
||||
[docs-master-url]: https://tower-rs.github.io/tower/tower
|
||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[mit-url]: LICENSE
|
||||
[actions-badge]: https://github.com/tower-rs/tower/workflows/CI/badge.svg
|
||||
[actions-url]:https://github.com/tower-rs/tower/actions?query=workflow%3ACI
|
||||
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
|
||||
[discord-url]: https://discord.gg/EeF3cQw
|
||||
## Overview
|
||||
|
||||
Tower aims to make it as easy as possible to build robust networking clients and
|
||||
servers. It is protocol agnostic, but is designed around a request / response
|
||||
pattern. If your protocol is entirely stream based, Tower may not be a good fit.
|
||||
|
||||
Tower provides a simple core abstraction, the [`Service`] trait, which
|
||||
represents an asynchronous function taking a request and returning either a
|
||||
response or an error. This abstraction can be used to model both clients and
|
||||
servers.
|
||||
|
||||
Generic components, like [timeouts], [rate limiting], and [load balancing],
|
||||
can be modeled as [`Service`]s that wrap some inner service and apply
|
||||
additional behavior before or after the inner service is called. This allows
|
||||
implementing these components in a protocol-agnostic, composable way. Typically,
|
||||
such services are referred to as _middleware_.
|
||||
|
||||
An additional abstraction, the [`Layer`] trait, is used to compose
|
||||
middleware with [`Service`]s. If a [`Service`] can be thought of as an
|
||||
asynchronous function from a request type to a response type, a [`Layer`] is
|
||||
a function taking a [`Service`] of one type and returning a [`Service`] of a
|
||||
different type. The [`ServiceBuilder`] type is used to add middleware to a
|
||||
service by composing it with multiple multiple [`Layer`]s.
|
||||
|
||||
### The Tower Ecosystem
|
||||
|
||||
Tower is made up of the following crates:
|
||||
|
||||
* [`tower`] (this crate)
|
||||
* [`tower-service`]
|
||||
* [`tower-layer`]
|
||||
* [`tower-test`]
|
||||
|
||||
Since the [`Service`] and [`Layer`] traits are important integration points
|
||||
for all libraries using Tower, they are kept as stable as possible, and
|
||||
breaking changes are made rarely. Therefore, they are defined in separate
|
||||
crates, [`tower-service`] and [`tower-layer`]. This crate contains
|
||||
re-exports of those core traits, implementations of commonly-used
|
||||
middleware, and [utilities] for working with [`Service`]s and [`Layer`]s.
|
||||
Finally, the [`tower-test`] crate provides tools for testing programs using
|
||||
Tower.
|
||||
|
||||
## Usage
|
||||
|
||||
Tower provides an abstraction layer, and generic implementations of various
|
||||
middleware. This means that the `tower` crate on its own does *not* provide
|
||||
a working implementation of a network client or server. Instead, Tower's
|
||||
[`Service` trait][`Service`] provides an integration point between
|
||||
application code, libraries providing middleware implementations, and
|
||||
libraries that implement servers and/or clients for various network
|
||||
protocols.
|
||||
|
||||
Depending on your particular use case, you might use Tower in several ways:
|
||||
|
||||
* **Implementing application logic** for a networked program. You might
|
||||
use the [`Service`] trait to model your application's behavior, and use
|
||||
the middleware [provided by this crate][all_layers] and by other libraries
|
||||
to add functionality to clients and servers provided by one or more
|
||||
protocol implementations.
|
||||
* **Implementing middleware** to add custom behavior to network clients and
|
||||
servers in a reusable manner. This might be general-purpose middleware
|
||||
(and if it is, please consider releasing your middleware as a library for
|
||||
other Tower users!) or application-specific behavior that needs to be
|
||||
shared between multiple clients or servers.
|
||||
* **Implementing a network protocol**. Libraries that implement network
|
||||
protocols (such as HTTP) can depend on `tower-service` to use the
|
||||
[`Service`] trait as an integration point between the protocol and user
|
||||
code. For example, a client for some protocol might implement [`Service`],
|
||||
allowing users to add arbitrary Tower middleware to those clients.
|
||||
Similarly, a server might be created from a user-provided [`Service`].
|
||||
|
||||
Additionally, when a network protocol requires functionality already
|
||||
provided by existing Tower middleware, a protocol implementation might use
|
||||
Tower middleware internally, as well as as an integration point.
|
||||
|
||||
### Library Support
|
||||
|
||||
A number of third-party libraries support Tower and the [`Service`] trait.
|
||||
The following is an incomplete list of such libraries:
|
||||
|
||||
* [`hyper`]: A fast and correct low-level HTTP implementation.
|
||||
* [`tonic`]: A [gRPC-over-HTTP/2][grpc] implementation built on top of
|
||||
[`hyper`]. See [here][tonic-examples] for examples of using [`tonic`] with
|
||||
Tower.
|
||||
* [`warp`]: A lightweight, composable web framework. See
|
||||
[here][warp-service] for details on using [`warp`] with Tower.
|
||||
* [`tower-lsp`] and its fork, [`lspower`]: implementations of the [Language
|
||||
Server Protocol][lsp] based on Tower.
|
||||
* [`kube`]: Kubernetes client and futures controller runtime. [`kube::Client`]
|
||||
makes use of the Tower ecosystem: [`tower`], [`tower-http`], and
|
||||
[`tower-test`]. See [here][kube-example-minimal] and
|
||||
[here][kube-example-trace] for examples of using [`kube`] with Tower.
|
||||
|
||||
[`hyper`]: https://crates.io/crates/hyper
|
||||
[`tonic`]: https://crates.io/crates/tonic
|
||||
[tonic-examples]: https://github.com/hyperium/tonic/tree/master/examples/src/tower
|
||||
[grpc]: https://grpc.io
|
||||
[`warp`]: https://crates.io/crates/warp
|
||||
[warp-service]: https://docs.rs/warp/0.2.5/warp/fn.service.html
|
||||
[`tower-lsp`]: https://crates.io/crates/tower-lsp
|
||||
[`lspower`]: https://crates.io/crates/lspower
|
||||
[lsp]: https://microsoft.github.io/language-server-protocol/
|
||||
[`kube`]: https://crates.io/crates/kube
|
||||
[`kube::Client`]: https://docs.rs/kube/latest/kube/struct.Client.html
|
||||
[kube-example-minimal]: https://github.com/clux/kube-rs/blob/master/examples/custom_client.rs
|
||||
[kube-example-trace]: https://github.com/clux/kube-rs/blob/master/examples/custom_client_trace.rs
|
||||
[`tower-http`]: https://crates.io/crates/tower-http
|
||||
|
||||
If you're the maintainer of a crate that supports Tower, we'd love to add
|
||||
your crate to this list! Please [open a PR] adding a brief description of
|
||||
your library!
|
||||
|
||||
### Getting Started
|
||||
|
||||
The various middleware implementations provided by this crate are feature
|
||||
flagged, so that users can only compile the parts of Tower they need. By
|
||||
default, all the optional middleware are disabled.
|
||||
|
||||
To get started using all of Tower's optional middleware, add this to your
|
||||
`Cargo.toml`:
|
||||
|
||||
```toml
|
||||
tower = { version = "0.4", features = ["full"] }
|
||||
```
|
||||
|
||||
Alternatively, you can only enable some features. For example, to enable
|
||||
only the [`retry`] and [`timeout`][timeouts] middleware, write:
|
||||
|
||||
```toml
|
||||
tower = { version = "0.4", features = ["retry", "timeout"] }
|
||||
```
|
||||
|
||||
See [here][all_layers] for a complete list of all middleware provided by
|
||||
Tower.
|
||||
|
||||
[`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
|
||||
[`Layer`]: https://docs.rs/tower/latest/tower/trait.Layer.html
|
||||
[all_layers]: https://docs.rs/tower/latest/tower/#modules
|
||||
[timeouts]: https://docs.rs/tower/latest/tower/timeout/
|
||||
[rate limiting]: https://docs.rs/tower/latest/tower/limit/rate
|
||||
[load balancing]: https://docs.rs/tower/latest/tower/balance/
|
||||
[`ServiceBuilder`]: https://docs.rs/tower/latest/tower/struct.ServiceBuilder.html
|
||||
[utilities]: https://docs.rs/tower/latest/tower/trait.ServiceExt.html
|
||||
[`tower`]: https://crates.io/crates/tower
|
||||
[`tower-service`]: https://crates.io/crates/tower-service
|
||||
[`tower-layer`]: https://crates.io/crates/tower-layer
|
||||
[`tower-test`]: https://crates.io/crates/tower-test
|
||||
[`retry`]: https://docs.rs/tower/latest/tower/retry
|
||||
[open a PR]: https://github.com/tower-rs/tower/compare
|
||||
|
||||
|
||||
## Supported Rust Versions
|
||||
|
||||
Tower will keep a rolling MSRV (minimum supported Rust version) policy of **at
|
||||
least** 6 months. When increasing the MSRV, the new Rust version must have been
|
||||
released at least six months ago. The current MSRV is 1.49.0.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license](LICENSE).
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in Tower by you, shall be licensed as MIT, without any additional
|
||||
terms or conditions.
|
||||
|
|
@ -1,828 +0,0 @@
|
|||
//! Builder types to compose layers and services
|
||||
|
||||
use tower_layer::{Identity, Layer, Stack};
|
||||
use tower_service::Service;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Declaratively construct [`Service`] values.
|
||||
///
|
||||
/// [`ServiceBuilder`] provides a [builder-like interface][builder] for composing
|
||||
/// layers to be applied to a [`Service`].
|
||||
///
|
||||
/// # Service
|
||||
///
|
||||
/// A [`Service`] is a trait representing an asynchronous function of a request
|
||||
/// to a response. It is similar to `async fn(Request) -> Result<Response, Error>`.
|
||||
///
|
||||
/// A [`Service`] is typically bound to a single transport, such as a TCP
|
||||
/// connection. It defines how _all_ inbound or outbound requests are handled
|
||||
/// by that connection.
|
||||
///
|
||||
/// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
|
||||
///
|
||||
/// # Order
|
||||
///
|
||||
/// The order in which layers are added impacts how requests are handled. Layers
|
||||
/// that are added first will be called with the request first. The argument to
|
||||
/// `service` will be last to see the request.
|
||||
///
|
||||
/// ```
|
||||
/// # // this (and other) doctest is ignored because we don't have a way
|
||||
/// # // to say that it should only be run with cfg(feature = "...")
|
||||
/// # use tower::Service;
|
||||
/// # use tower::builder::ServiceBuilder;
|
||||
/// # #[cfg(all(feature = "buffer", feature = "limit"))]
|
||||
/// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
|
||||
/// ServiceBuilder::new()
|
||||
/// .buffer(100)
|
||||
/// .concurrency_limit(10)
|
||||
/// .service(svc)
|
||||
/// # ;
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// In the above example, the buffer layer receives the request first followed
|
||||
/// by `concurrency_limit`. `buffer` enables up to 100 request to be in-flight
|
||||
/// **on top of** the requests that have already been forwarded to the next
|
||||
/// layer. Combined with `concurrency_limit`, this allows up to 110 requests to be
|
||||
/// in-flight.
|
||||
///
|
||||
/// ```
|
||||
/// # use tower::Service;
|
||||
/// # use tower::builder::ServiceBuilder;
|
||||
/// # #[cfg(all(feature = "buffer", feature = "limit"))]
|
||||
/// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
|
||||
/// ServiceBuilder::new()
|
||||
/// .concurrency_limit(10)
|
||||
/// .buffer(100)
|
||||
/// .service(svc)
|
||||
/// # ;
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The above example is similar, but the order of layers is reversed. Now,
|
||||
/// `concurrency_limit` applies first and only allows 10 requests to be in-flight
|
||||
/// total.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A [`Service`] stack with a single layer:
|
||||
///
|
||||
/// ```
|
||||
/// # use tower::Service;
|
||||
/// # use tower::builder::ServiceBuilder;
|
||||
/// # #[cfg(feature = "limit")]
|
||||
/// # use tower::limit::concurrency::ConcurrencyLimitLayer;
|
||||
/// # #[cfg(feature = "limit")]
|
||||
/// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
|
||||
/// ServiceBuilder::new()
|
||||
/// .concurrency_limit(5)
|
||||
/// .service(svc);
|
||||
/// # ;
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// A [`Service`] stack with _multiple_ layers that contain rate limiting,
|
||||
/// in-flight request limits, and a channel-backed, clonable [`Service`]:
|
||||
///
|
||||
/// ```
|
||||
/// # use tower::Service;
|
||||
/// # use tower::builder::ServiceBuilder;
|
||||
/// # use std::time::Duration;
|
||||
/// # #[cfg(all(feature = "buffer", feature = "limit"))]
|
||||
/// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
|
||||
/// ServiceBuilder::new()
|
||||
/// .buffer(5)
|
||||
/// .concurrency_limit(5)
|
||||
/// .rate_limit(5, Duration::from_secs(1))
|
||||
/// .service(svc);
|
||||
/// # ;
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`Service`]: crate::Service
|
||||
#[derive(Clone)]
|
||||
pub struct ServiceBuilder<L> {
|
||||
layer: L,
|
||||
}
|
||||
|
||||
impl Default for ServiceBuilder<Identity> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceBuilder<Identity> {
|
||||
/// Create a new [`ServiceBuilder`].
|
||||
pub fn new() -> Self {
|
||||
ServiceBuilder {
|
||||
layer: Identity::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> ServiceBuilder<L> {
|
||||
/// Add a new layer `T` into the [`ServiceBuilder`].
|
||||
///
|
||||
/// This wraps the inner service with the service provided by a user-defined
|
||||
/// [`Layer`]. The provided layer must implement the [`Layer`] trait.
|
||||
///
|
||||
/// [`Layer`]: crate::Layer
|
||||
pub fn layer<T>(self, layer: T) -> ServiceBuilder<Stack<T, L>> {
|
||||
ServiceBuilder {
|
||||
layer: Stack::new(layer, self.layer),
|
||||
}
|
||||
}
|
||||
|
||||
/// Optionally add a new layer `T` into the [`ServiceBuilder`].
|
||||
///
|
||||
/// ```
|
||||
/// # use std::time::Duration;
|
||||
/// # use tower::Service;
|
||||
/// # use tower::builder::ServiceBuilder;
|
||||
/// # use tower::timeout::TimeoutLayer;
|
||||
/// # async fn wrap<S>(svc: S) where S: Service<(), Error = &'static str> + 'static + Send, S::Future: Send {
|
||||
/// # let timeout = Some(Duration::new(10, 0));
|
||||
/// // Apply a timeout if configured
|
||||
/// ServiceBuilder::new()
|
||||
/// .option_layer(timeout.map(TimeoutLayer::new))
|
||||
/// .service(svc)
|
||||
/// # ;
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn option_layer<T>(
|
||||
self,
|
||||
layer: Option<T>,
|
||||
) -> ServiceBuilder<Stack<crate::util::Either<T, Identity>, L>> {
|
||||
self.layer(crate::util::option_layer(layer))
|
||||
}
|
||||
|
||||
/// Add a [`Layer`] built from a function that accepts a service and returns another service.
|
||||
///
|
||||
/// See the documentation for [`layer_fn`] for more details.
|
||||
///
|
||||
/// [`layer_fn`]: crate::layer::layer_fn
|
||||
pub fn layer_fn<F>(self, f: F) -> ServiceBuilder<Stack<crate::layer::LayerFn<F>, L>> {
|
||||
self.layer(crate::layer::layer_fn(f))
|
||||
}
|
||||
|
||||
/// Buffer requests when the next layer is not ready.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`Buffer`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`Buffer`]: crate::buffer
|
||||
#[cfg(feature = "buffer")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "buffer")))]
|
||||
pub fn buffer<Request>(
|
||||
self,
|
||||
bound: usize,
|
||||
) -> ServiceBuilder<Stack<crate::buffer::BufferLayer<Request>, L>> {
|
||||
self.layer(crate::buffer::BufferLayer::new(bound))
|
||||
}
|
||||
|
||||
/// Limit the max number of in-flight requests.
|
||||
///
|
||||
/// A request is in-flight from the time the request is received until the
|
||||
/// response future completes. This includes the time spent in the next
|
||||
/// layers.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the
|
||||
/// [`ConcurrencyLimit`] middleware.
|
||||
///
|
||||
/// [`ConcurrencyLimit`]: crate::limit::concurrency
|
||||
#[cfg(feature = "limit")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "limit")))]
|
||||
pub fn concurrency_limit(
|
||||
self,
|
||||
max: usize,
|
||||
) -> ServiceBuilder<Stack<crate::limit::ConcurrencyLimitLayer, L>> {
|
||||
self.layer(crate::limit::ConcurrencyLimitLayer::new(max))
|
||||
}
|
||||
|
||||
/// Drop requests when the next layer is unable to respond to requests.
|
||||
///
|
||||
/// Usually, when a service or middleware does not have capacity to process a
|
||||
/// request (i.e., [`poll_ready`] returns [`Pending`]), the caller waits until
|
||||
/// capacity becomes available.
|
||||
///
|
||||
/// [`LoadShed`] immediately responds with an error when the next layer is
|
||||
/// out of capacity.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`LoadShed`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`LoadShed`]: crate::load_shed
|
||||
/// [`poll_ready`]: crate::Service::poll_ready
|
||||
/// [`Pending`]: std::task::Poll::Pending
|
||||
#[cfg(feature = "load-shed")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "load-shed")))]
|
||||
pub fn load_shed(self) -> ServiceBuilder<Stack<crate::load_shed::LoadShedLayer, L>> {
|
||||
self.layer(crate::load_shed::LoadShedLayer::new())
|
||||
}
|
||||
|
||||
/// Limit requests to at most `num` per the given duration.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`RateLimit`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`RateLimit`]: crate::limit::rate
|
||||
#[cfg(feature = "limit")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "limit")))]
|
||||
pub fn rate_limit(
|
||||
self,
|
||||
num: u64,
|
||||
per: std::time::Duration,
|
||||
) -> ServiceBuilder<Stack<crate::limit::RateLimitLayer, L>> {
|
||||
self.layer(crate::limit::RateLimitLayer::new(num, per))
|
||||
}
|
||||
|
||||
/// Retry failed requests according to the given [retry policy][policy].
|
||||
///
|
||||
/// `policy` determines which failed requests will be retried. It must
|
||||
/// implement the [`retry::Policy`][policy] trait.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`Retry`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`Retry`]: crate::retry
|
||||
/// [policy]: crate::retry::Policy
|
||||
#[cfg(feature = "retry")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "retry")))]
|
||||
pub fn retry<P>(self, policy: P) -> ServiceBuilder<Stack<crate::retry::RetryLayer<P>, L>> {
|
||||
self.layer(crate::retry::RetryLayer::new(policy))
|
||||
}
|
||||
|
||||
/// Fail requests that take longer than `timeout`.
|
||||
///
|
||||
/// If the next layer takes more than `timeout` to respond to a request,
|
||||
/// processing is terminated and an error is returned.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`timeout`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`timeout`]: crate::timeout
|
||||
#[cfg(feature = "timeout")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "timeout")))]
|
||||
pub fn timeout(
|
||||
self,
|
||||
timeout: std::time::Duration,
|
||||
) -> ServiceBuilder<Stack<crate::timeout::TimeoutLayer, L>> {
|
||||
self.layer(crate::timeout::TimeoutLayer::new(timeout))
|
||||
}
|
||||
|
||||
/// Conditionally reject requests based on `predicate`.
|
||||
///
|
||||
/// `predicate` must implement the [`Predicate`] trait.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`Filter`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`Filter`]: crate::filter
|
||||
/// [`Predicate`]: crate::filter::Predicate
|
||||
#[cfg(feature = "filter")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "filter")))]
|
||||
pub fn filter<P>(
|
||||
self,
|
||||
predicate: P,
|
||||
) -> ServiceBuilder<Stack<crate::filter::FilterLayer<P>, L>> {
|
||||
self.layer(crate::filter::FilterLayer::new(predicate))
|
||||
}
|
||||
|
||||
/// Conditionally reject requests based on an asynchronous `predicate`.
|
||||
///
|
||||
/// `predicate` must implement the [`AsyncPredicate`] trait.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`AsyncFilter`]
|
||||
/// middleware.
|
||||
///
|
||||
/// [`AsyncFilter`]: crate::filter::AsyncFilter
|
||||
/// [`AsyncPredicate`]: crate::filter::AsyncPredicate
|
||||
#[cfg(feature = "filter")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "filter")))]
|
||||
pub fn filter_async<P>(
|
||||
self,
|
||||
predicate: P,
|
||||
) -> ServiceBuilder<Stack<crate::filter::AsyncFilterLayer<P>, L>> {
|
||||
self.layer(crate::filter::AsyncFilterLayer::new(predicate))
|
||||
}
|
||||
|
||||
/// Map one request type to another.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`MapRequest`]
|
||||
/// middleware.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Changing the type of a request:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tower::ServiceBuilder;
|
||||
/// use tower::ServiceExt;
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() -> Result<(), ()> {
|
||||
/// // Suppose we have some `Service` whose request type is `String`:
|
||||
/// let string_svc = tower::service_fn(|request: String| async move {
|
||||
/// println!("request: {}", request);
|
||||
/// Ok(())
|
||||
/// });
|
||||
///
|
||||
/// // ...but we want to call that service with a `usize`. What do we do?
|
||||
///
|
||||
/// let usize_svc = ServiceBuilder::new()
|
||||
/// // Add a middlware that converts the request type to a `String`:
|
||||
/// .map_request(|request: usize| format!("{}", request))
|
||||
/// // ...and wrap the string service with that middleware:
|
||||
/// .service(string_svc);
|
||||
///
|
||||
/// // Now, we can call that service with a `usize`:
|
||||
/// usize_svc.oneshot(42).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Modifying the request value:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tower::ServiceBuilder;
|
||||
/// use tower::ServiceExt;
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() -> Result<(), ()> {
|
||||
/// // A service that takes a number and returns it:
|
||||
/// let svc = tower::service_fn(|request: usize| async move {
|
||||
/// Ok(request)
|
||||
/// });
|
||||
///
|
||||
/// let svc = ServiceBuilder::new()
|
||||
/// // Add a middleware that adds 1 to each request
|
||||
/// .map_request(|request: usize| request + 1)
|
||||
/// .service(svc);
|
||||
///
|
||||
/// let response = svc.oneshot(1).await?;
|
||||
/// assert_eq!(response, 2);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`MapRequest`]: crate::util::MapRequest
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn map_request<F, R1, R2>(
|
||||
self,
|
||||
f: F,
|
||||
) -> ServiceBuilder<Stack<crate::util::MapRequestLayer<F>, L>>
|
||||
where
|
||||
F: FnMut(R1) -> R2 + Clone,
|
||||
{
|
||||
self.layer(crate::util::MapRequestLayer::new(f))
|
||||
}
|
||||
|
||||
/// Map one response type to another.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`MapResponse`]
|
||||
/// middleware.
|
||||
///
|
||||
/// See the documentation for the [`map_response` combinator] for details.
|
||||
///
|
||||
/// [`MapResponse`]: crate::util::MapResponse
|
||||
/// [`map_response` combinator]: crate::util::ServiceExt::map_response
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn map_response<F>(
|
||||
self,
|
||||
f: F,
|
||||
) -> ServiceBuilder<Stack<crate::util::MapResponseLayer<F>, L>> {
|
||||
self.layer(crate::util::MapResponseLayer::new(f))
|
||||
}
|
||||
|
||||
/// Map one error type to another.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`MapErr`]
|
||||
/// middleware.
|
||||
///
|
||||
/// See the documentation for the [`map_err` combinator] for details.
|
||||
///
|
||||
/// [`MapErr`]: crate::util::MapErr
|
||||
/// [`map_err` combinator]: crate::util::ServiceExt::map_err
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn map_err<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapErrLayer<F>, L>> {
|
||||
self.layer(crate::util::MapErrLayer::new(f))
|
||||
}
|
||||
|
||||
/// Composes a function that transforms futures produced by the service.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`MapFutureLayer`] middleware.
|
||||
///
|
||||
/// See the documentation for the [`map_future`] combinator for details.
|
||||
///
|
||||
/// [`MapFutureLayer`]: crate::util::MapFutureLayer
|
||||
/// [`map_future`]: crate::util::ServiceExt::map_future
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn map_future<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapFutureLayer<F>, L>> {
|
||||
self.layer(crate::util::MapFutureLayer::new(f))
|
||||
}
|
||||
|
||||
/// Apply an asynchronous function after the service, regardless of whether the future
|
||||
/// succeeds or fails.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`Then`]
|
||||
/// middleware.
|
||||
///
|
||||
/// This is similar to the [`map_response`] and [`map_err`] functions,
|
||||
/// except that the *same* function is invoked when the service's future
|
||||
/// completes, whether it completes successfully or fails. This function
|
||||
/// takes the [`Result`] returned by the service's future, and returns a
|
||||
/// [`Result`].
|
||||
///
|
||||
/// See the documentation for the [`then` combinator] for details.
|
||||
///
|
||||
/// [`Then`]: crate::util::Then
|
||||
/// [`then` combinator]: crate::util::ServiceExt::then
|
||||
/// [`map_response`]: ServiceBuilder::map_response
|
||||
/// [`map_err`]: ServiceBuilder::map_err
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::ThenLayer<F>, L>> {
|
||||
self.layer(crate::util::ThenLayer::new(f))
|
||||
}
|
||||
|
||||
/// Executes a new future after this service's future resolves. This does
|
||||
/// not alter the behaviour of the [`poll_ready`] method.
|
||||
///
|
||||
/// This method can be used to change the [`Response`] type of the service
|
||||
/// into a different type. You can use this method to chain along a computation once the
|
||||
/// service's response has been resolved.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`AndThen`]
|
||||
/// middleware.
|
||||
///
|
||||
/// See the documentation for the [`and_then` combinator] for details.
|
||||
///
|
||||
/// [`Response`]: crate::Service::Response
|
||||
/// [`poll_ready`]: crate::Service::poll_ready
|
||||
/// [`and_then` combinator]: crate::util::ServiceExt::and_then
|
||||
/// [`AndThen`]: crate::util::AndThen
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn and_then<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::AndThenLayer<F>, L>> {
|
||||
self.layer(crate::util::AndThenLayer::new(f))
|
||||
}
|
||||
|
||||
/// Maps this service's result type (`Result<Self::Response, Self::Error>`)
|
||||
/// to a different value, regardless of whether the future succeeds or
|
||||
/// fails.
|
||||
///
|
||||
/// This wraps the inner service with an instance of the [`MapResult`]
|
||||
/// middleware.
|
||||
///
|
||||
/// See the documentation for the [`map_result` combinator] for details.
|
||||
///
|
||||
/// [`map_result` combinator]: crate::util::ServiceExt::map_result
|
||||
/// [`MapResult`]: crate::util::MapResult
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn map_result<F>(self, f: F) -> ServiceBuilder<Stack<crate::util::MapResultLayer<F>, L>> {
|
||||
self.layer(crate::util::MapResultLayer::new(f))
|
||||
}
|
||||
|
||||
/// Returns the underlying `Layer` implementation.
|
||||
pub fn into_inner(self) -> L {
|
||||
self.layer
|
||||
}
|
||||
|
||||
/// Wrap the service `S` with the middleware provided by this
|
||||
/// [`ServiceBuilder`]'s [`Layer`]'s, returning a new [`Service`].
|
||||
///
|
||||
/// [`Layer`]: crate::Layer
|
||||
/// [`Service`]: crate::Service
|
||||
pub fn service<S>(&self, service: S) -> L::Service
|
||||
where
|
||||
L: Layer<S>,
|
||||
{
|
||||
self.layer.layer(service)
|
||||
}
|
||||
|
||||
/// Wrap the async function `F` with the middleware provided by this [`ServiceBuilder`]'s
|
||||
/// [`Layer`]s, returning a new [`Service`].
|
||||
///
|
||||
/// This is a convenience method which is equivalent to calling
|
||||
/// [`ServiceBuilder::service`] with a [`service_fn`], like this:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use tower::{ServiceBuilder, service_fn};
|
||||
/// # async fn handler_fn(_: ()) -> Result<(), ()> { Ok(()) }
|
||||
/// # let _ = {
|
||||
/// ServiceBuilder::new()
|
||||
/// // ...
|
||||
/// .service(service_fn(handler_fn))
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::time::Duration;
|
||||
/// use tower::{ServiceBuilder, ServiceExt, BoxError, service_fn};
|
||||
///
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() -> Result<(), BoxError> {
|
||||
/// async fn handle(request: &'static str) -> Result<&'static str, BoxError> {
|
||||
/// Ok(request)
|
||||
/// }
|
||||
///
|
||||
/// let svc = ServiceBuilder::new()
|
||||
/// .buffer(1024)
|
||||
/// .timeout(Duration::from_secs(10))
|
||||
/// .service_fn(handle);
|
||||
///
|
||||
/// let response = svc.oneshot("foo").await?;
|
||||
///
|
||||
/// assert_eq!(response, "foo");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`Layer`]: crate::Layer
|
||||
/// [`Service`]: crate::Service
|
||||
/// [`service_fn`]: crate::service_fn
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn service_fn<F>(self, f: F) -> L::Service
|
||||
where
|
||||
L: Layer<crate::util::ServiceFn<F>>,
|
||||
{
|
||||
self.service(crate::util::service_fn(f))
|
||||
}
|
||||
|
||||
/// Check that the builder implements `Clone`.
|
||||
///
|
||||
/// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
|
||||
///
|
||||
/// Doesn't actually change the builder but serves as a type check.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tower::ServiceBuilder;
|
||||
///
|
||||
/// let builder = ServiceBuilder::new()
|
||||
/// // Do something before processing the request
|
||||
/// .map_request(|request: String| {
|
||||
/// println!("got request!");
|
||||
/// request
|
||||
/// })
|
||||
/// // Ensure our `ServiceBuilder` can be cloned
|
||||
/// .check_clone()
|
||||
/// // Do something after processing the request
|
||||
/// .map_response(|response: String| {
|
||||
/// println!("got response!");
|
||||
/// response
|
||||
/// });
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn check_clone(self) -> Self
|
||||
where
|
||||
Self: Clone,
|
||||
{
|
||||
self
|
||||
}
|
||||
|
||||
/// Check that the builder when given a service of type `S` produces a service that implements
|
||||
/// `Clone`.
|
||||
///
|
||||
/// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
|
||||
///
|
||||
/// Doesn't actually change the builder but serves as a type check.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tower::ServiceBuilder;
|
||||
///
|
||||
/// # #[derive(Clone)]
|
||||
/// # struct MyService;
|
||||
/// #
|
||||
/// let builder = ServiceBuilder::new()
|
||||
/// // Do something before processing the request
|
||||
/// .map_request(|request: String| {
|
||||
/// println!("got request!");
|
||||
/// request
|
||||
/// })
|
||||
/// // Ensure that the service produced when given a `MyService` implements
|
||||
/// .check_service_clone::<MyService>()
|
||||
/// // Do something after processing the request
|
||||
/// .map_response(|response: String| {
|
||||
/// println!("got response!");
|
||||
/// response
|
||||
/// });
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn check_service_clone<S>(self) -> Self
|
||||
where
|
||||
L: Layer<S>,
|
||||
L::Service: Clone,
|
||||
{
|
||||
self
|
||||
}
|
||||
|
||||
/// Check that the builder when given a service of type `S` produces a service with the given
|
||||
/// request, response, and error types.
|
||||
///
|
||||
/// This can be useful when debugging type errors in `ServiceBuilder`s with lots of layers.
|
||||
///
|
||||
/// Doesn't actually change the builder but serves as a type check.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tower::ServiceBuilder;
|
||||
/// use std::task::{Poll, Context};
|
||||
/// use tower::{Service, ServiceExt};
|
||||
///
|
||||
/// // An example service
|
||||
/// struct MyService;
|
||||
///
|
||||
/// impl Service<Request> for MyService {
|
||||
/// type Response = Response;
|
||||
/// type Error = Error;
|
||||
/// type Future = futures_util::future::Ready<Result<Response, Error>>;
|
||||
///
|
||||
/// fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
/// // ...
|
||||
/// # todo!()
|
||||
/// }
|
||||
///
|
||||
/// fn call(&mut self, request: Request) -> Self::Future {
|
||||
/// // ...
|
||||
/// # todo!()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// struct Request;
|
||||
/// struct Response;
|
||||
/// struct Error;
|
||||
///
|
||||
/// struct WrappedResponse(Response);
|
||||
///
|
||||
/// let builder = ServiceBuilder::new()
|
||||
/// // At this point in the builder if given a `MyService` it produces a service that
|
||||
/// // accepts `Request`s, produces `Response`s, and fails with `Error`s
|
||||
/// .check_service::<MyService, Request, Response, Error>()
|
||||
/// // Wrap responses in `WrappedResponse`
|
||||
/// .map_response(|response: Response| WrappedResponse(response))
|
||||
/// // Now the response type will be `WrappedResponse`
|
||||
/// .check_service::<MyService, _, WrappedResponse, _>();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn check_service<S, T, U, E>(self) -> Self
|
||||
where
|
||||
L: Layer<S>,
|
||||
L::Service: Service<T, Response = U, Error = E>,
|
||||
{
|
||||
self
|
||||
}
|
||||
|
||||
/// This wraps the inner service with the [`Layer`] returned by [`BoxService::layer()`].
|
||||
///
|
||||
/// See that method for more details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use tower::{Service, ServiceBuilder, BoxError, util::BoxService};
|
||||
/// use std::time::Duration;
|
||||
/// #
|
||||
/// # struct Request;
|
||||
/// # struct Response;
|
||||
/// # impl Response {
|
||||
/// # fn new() -> Self { Self }
|
||||
/// # }
|
||||
///
|
||||
/// let service: BoxService<Request, Response, BoxError> = ServiceBuilder::new()
|
||||
/// .boxed()
|
||||
/// .load_shed()
|
||||
/// .concurrency_limit(64)
|
||||
/// .timeout(Duration::from_secs(10))
|
||||
/// .service_fn(|req: Request| async {
|
||||
/// Ok::<_, BoxError>(Response::new())
|
||||
/// });
|
||||
/// # let service = assert_service(service);
|
||||
/// # fn assert_service<S, R>(svc: S) -> S
|
||||
/// # where S: Service<R> { svc }
|
||||
/// ```
|
||||
///
|
||||
/// [`BoxService::layer()`]: crate::util::BoxService::layer()
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn boxed<S, R>(
|
||||
self,
|
||||
) -> ServiceBuilder<
|
||||
Stack<
|
||||
tower_layer::LayerFn<
|
||||
fn(
|
||||
L::Service,
|
||||
) -> crate::util::BoxService<
|
||||
R,
|
||||
<L::Service as Service<R>>::Response,
|
||||
<L::Service as Service<R>>::Error,
|
||||
>,
|
||||
>,
|
||||
L,
|
||||
>,
|
||||
>
|
||||
where
|
||||
L: Layer<S>,
|
||||
L::Service: Service<R> + Send + 'static,
|
||||
<L::Service as Service<R>>::Future: Send + 'static,
|
||||
{
|
||||
self.layer(crate::util::BoxService::layer())
|
||||
}
|
||||
|
||||
/// This wraps the inner service with the [`Layer`] returned by [`BoxCloneService::layer()`].
|
||||
///
|
||||
/// This is similar to the [`boxed`] method, but it requires that `Self` implement
|
||||
/// [`Clone`], and the returned boxed service implements [`Clone`].
|
||||
///
|
||||
/// See [`BoxCloneService`] for more details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use tower::{Service, ServiceBuilder, BoxError, util::BoxCloneService};
|
||||
/// use std::time::Duration;
|
||||
/// #
|
||||
/// # struct Request;
|
||||
/// # struct Response;
|
||||
/// # impl Response {
|
||||
/// # fn new() -> Self { Self }
|
||||
/// # }
|
||||
///
|
||||
/// let service: BoxCloneService<Request, Response, BoxError> = ServiceBuilder::new()
|
||||
/// .boxed_clone()
|
||||
/// .load_shed()
|
||||
/// .concurrency_limit(64)
|
||||
/// .timeout(Duration::from_secs(10))
|
||||
/// .service_fn(|req: Request| async {
|
||||
/// Ok::<_, BoxError>(Response::new())
|
||||
/// });
|
||||
/// # let service = assert_service(service);
|
||||
///
|
||||
/// // The boxed service can still be cloned.
|
||||
/// service.clone();
|
||||
/// # fn assert_service<S, R>(svc: S) -> S
|
||||
/// # where S: Service<R> { svc }
|
||||
/// ```
|
||||
///
|
||||
/// [`BoxCloneService::layer()`]: crate::util::BoxCloneService::layer()
|
||||
/// [`BoxCloneService`]: crate::util::BoxCloneService
|
||||
/// [`boxed`]: Self::boxed
|
||||
#[cfg(feature = "util")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "util")))]
|
||||
pub fn boxed_clone<S, R>(
|
||||
self,
|
||||
) -> ServiceBuilder<
|
||||
Stack<
|
||||
tower_layer::LayerFn<
|
||||
fn(
|
||||
L::Service,
|
||||
) -> crate::util::BoxCloneService<
|
||||
R,
|
||||
<L::Service as Service<R>>::Response,
|
||||
<L::Service as Service<R>>::Error,
|
||||
>,
|
||||
>,
|
||||
L,
|
||||
>,
|
||||
>
|
||||
where
|
||||
L: Layer<S>,
|
||||
L::Service: Service<R> + Clone + Send + 'static,
|
||||
<L::Service as Service<R>>::Future: Send + 'static,
|
||||
{
|
||||
self.layer(crate::util::BoxCloneService::layer())
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("ServiceBuilder").field(&self.layer).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, L> Layer<S> for ServiceBuilder<L>
|
||||
where
|
||||
L: Layer<S>,
|
||||
{
|
||||
type Service = L::Service;
|
||||
|
||||
fn layer(&self, inner: S) -> Self::Service {
|
||||
self.layer.layer(inner)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
//! A collection of [`Layer`] based tower services
|
||||
//!
|
||||
//! [`Layer`]: crate::Layer
|
||||
|
||||
pub use tower_layer::{layer_fn, Layer, LayerFn};
|
||||
|
||||
/// Utilities for combining layers
|
||||
///
|
||||
/// [`Identity`]: crate::layer::util::Identity
|
||||
/// [`Layer`]: crate::Layer
|
||||
/// [`Stack`]: crate::layer::util::Stack
|
||||
pub mod util {
|
||||
pub use tower_layer::{Identity, Stack};
|
||||
}
|
||||
|
|
@ -8,8 +8,6 @@ pub mod discover;
|
|||
|
||||
pub mod make;
|
||||
|
||||
pub mod builder;
|
||||
pub mod layer;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
mod sealed {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue