tower_async/
lib.rs

1#![warn(
2    missing_debug_implementations,
3    missing_docs,
4    rust_2018_idioms,
5    unreachable_pub
6)]
7#![forbid(unsafe_code)]
8#![allow(elided_lifetimes_in_paths, clippy::type_complexity)]
9#![cfg_attr(test, allow(clippy::float_cmp))]
10#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))]
11// `rustdoc::broken_intra_doc_links` is checked on CI
12
13//! `async fn(Request) -> Result<Response, Error>`
14//!
15//! ## Fork
16//!
17//! Tower Async is a fork of <https://github.com/tower-rs/tower>
18//! and makes use of `async traits` to simplify things and make it more easier
19//! to integrate async functions into middleware.
20//!
21//! This fork is made entirely with the needs of the author in mind,
22//! and thus might not yet contain all features you might need.
23//!
24//! Come join us at discord at <https://discord.com/channels/1114459060050333696/1123537825929900113>
25//! or tag `@glendc` at Tokio's Tower discord instead.
26//!
27//! Where suitable we'll keep in sync (manually) with Tower and if the
28//! opportunity arises we'll contribute back "upstream" as well.
29//! Given however how big the diversange we aren't sure how likely that is.
30//!
31//! ## Overview
32//!
33//! Tower Async aims to make it as easy as possible to build robust networking clients and
34//! servers. It is protocol agnostic, but is designed around a request / response
35//! pattern. If your protocol is entirely stream based, Tower may not be a good fit.
36//!
37//! Tower Async provides a simple core abstraction, the [`Service`] trait, which
38//! represents an asynchronous function taking a request and returning either a
39//! response or an error. This abstraction can be used to model both clients and
40//! servers.
41//!
42//! Generic components, like [timeouts], [rate limiting], and [load balancing],
43//! can be modeled as [`Service`]s that wrap some inner service and apply
44//! additional behavior before or after the inner service is called. This allows
45//! implementing these components in a protocol-agnostic, composable way. Typically,
46//! such services are referred to as _middleware_.
47//!
48//! An additional abstraction, the [`Layer`] trait, is used to compose
49//! middleware with [`Service`]s. If a [`Service`] can be thought of as an
50//! asynchronous function from a request type to a response type, a [`Layer`] is
51//! a function taking a [`Service`] of one type and returning a [`Service`] of a
52//! different type. The [`ServiceBuilder`] type is used to add middleware to a
53//! service by composing it with multiple [`Layer`]s.
54//!
55//! ## Difference with Tokio's official Tower Ecosystem?
56//!
57//! - Make use of `Async Traits`
58//! ([RFC-3185: Static async fn in traits](https://rust-lang.github.io/rfcs/3185-static-async-fn-in-trait.html))
59//! instead of requiring the user to manually implement Futures;
60//!    - Which in fact forces users to Box Services that rely on futures which cannot be named,
61//!      e.g. those returned by `async functions` that the user might have to face by using
62//!      common utility functions from the wider _Tokio_ ecosystem;
63//! - Drop the notion of `poll_ready` (See [the FAQ](https://github.com/plabayo/tower-async#faq)).
64//! - Use `&self` for `Service::call` instead of `&mut self`:
65//!   - this to simplify its usage;
66//!   - makes it clear that the user is responsible for proper state sharing;
67//!   - makes it more compatible with the ecosystem (e.g. `hyper` (v1) also takes services by `&self`);
68//!
69//! ## Bridging to Tokio's official Tower Ecosystem
70//!
71//! You can make use of the `tower-async-bridge` crate as found in this repo in the [./tower-async-bridge](./tower-async-bridge/) directory,
72//! and published at [crates.io](https://crates.io/) under the same name.
73//!
74//! At a high level it allows you to:
75//!
76//! - Turn a [`tower::Service`] into a [`tower_async::Service`] (requires the `into_async` feature);
77//! - Turn a [`tower_async::Service`] into a [`tower::Service`];
78//! - Use a [`tower_async::Layer`] within a [`tower`] environment (e.g. [`tower::ServiceBuilder`]);
79//! - Use a [`tower::Layer`] within a [`tower_async`] environment (e.g. [`tower_async::ServiceBuilder`]) (requires the `into_async` feature);
80//!
81//! Please check the crate's unit tests and examples to see specifically how to use the crate in order to achieve this.
82//!
83//! Furthermore we also urge you to only use this kind of approach for transition purposes and not as a permanent way of life.
84//! Best in our opinion is to use one or the other and not to combine the two. But if you do absolutely must
85//! use one combined with the other, `tower-async-bridge` should allow you to do exactly that.
86//!
87//! ### The Tower Async Ecosystem
88//!
89//! Tower Async is made up of the following crates:
90//!
91//! * [`tower-async`] (this crate)
92//! * [`tower-async-bridge`]
93//! * [`tower-async-service`]
94//! * [`tower-async-layer`]
95//! * [`tower-async-test`]
96//! * [`tower-async-http`]
97//!
98//! Since the [`Service`] and [`Layer`] traits are important integration points
99//! for all libraries using Tower, they are kept as stable as possible, and
100//! breaking changes are made rarely. Therefore, they are defined in separate
101//! crates, [`tower-async-service`] and [`tower-async-layer`]. This crate contains
102//! re-exports of those core traits, implementations of commonly-used
103//! middleware, and [utilities] for working with [`Service`]s and [`Layer`]s.
104//!
105//! [`tower-async-bridge`] is there to bridge Tokio's official Tower ecosystem
106//! with this (Aync Trait) version (Fork).
107//!
108//! Testing [`Layer`]s can be done with unit tests very easily suing [`tower-async-test`].
109//!
110//! Finally in case you are using [`tower-async`] for HTTP purposes (e.g. an HTTP web server),
111//! then you might find it useful to also make use of [`tower-async-http`] as it provides you
112//! with builder extensions and middleware specifically tailored for http purposes.
113//!
114//! ## Usage
115//!
116//! Tower provides an abstraction layer, and generic implementations of various
117//! middleware. This means that the `tower-async` crate on its own does *not* provide
118//! a working implementation of a network client or server. Instead, Tower's
119//! [`Service` trait][`Service`] provides an integration point between
120//! application code, libraries providing middleware implementations, and
121//! libraries that implement servers and/or clients for various network
122//! protocols.
123//!
124//! Depending on your particular use case, you might use Tower in several ways:
125//!
126//! * **Implementing application logic** for a networked program. You might
127//!   use the [`Service`] trait to model your application's behavior, and use
128//!   the middleware [provided by this crate][all_layers] and by other libraries
129//!   to add functionality to clients and servers provided by one or more
130//!   protocol implementations.
131//! * **Implementing middleware** to add custom behavior to network clients and
132//!   servers in a reusable manner. This might be general-purpose middleware
133//!   (and if it is, please consider releasing your middleware as a library for
134//!   other Tower users!) or application-specific behavior that needs to be
135//!   shared between multiple clients or servers.
136//! * **Implementing a network protocol**. Libraries that implement network
137//!   protocols (such as HTTP) can depend on `tower-async-service` to use the
138//!   [`Service`] trait as an integration point between the protocol and user
139//!   code. For example, a client for some protocol might implement [`Service`],
140//!   allowing users to add arbitrary Tower middleware to those clients.
141//!   Similarly, a server might be created from a user-provided [`Service`].
142//!
143//!   Additionally, when a network protocol requires functionality already
144//!   provided by existing Tower middleware, a protocol implementation might use
145//!   Tower middleware internally, as well as an integration point.
146//!
147//! ### Library Support
148//!
149//! Following are some libraries that make use of Tower Async (instead of Tower)
150//! and the [`Service`] trait:
151//!
152//! * [`rama`]: A proxy framework to anonymise your network traffic.
153//!
154//! [`rama`]: https://crates.io/crates/rama
155//!
156//! If you're the maintainer of a crate that supports Tower Async, we'd love to add
157//! your crate to this list! Please [open a PR] adding a brief description of
158//! your library!
159//!
160//! ### Getting Started
161//!
162//! The various middleware implementations provided by this crate are feature
163//! flagged, so that users can only compile the parts of Tower they need. By
164//! default, all the optional middleware are disabled.
165//!
166//! To get started using all of Tower's optional middleware, add this to your
167//! `Cargo.toml`:
168//!
169//! ```toml
170//! tower-async = { version = "0.2", features = ["full"] }
171//! ```
172//!
173//! Alternatively, you can only enable some features. For example,
174//! to enable only the [`timeout`][timeouts] middleware, write:
175//!
176//! ```toml
177//! tower-async = { version = "0.2", features = ["timeout"] }
178//! ```
179//!
180//! See [here][all_layers] for a complete list of all middleware provided by
181//! Tower.
182//!
183//! Browse the examples at [`tower-async-http/examples`](https://github.com/plabayo/tower-async/tree/master/tower-async-http/examples) to see some examples
184//! on how to use `tower-async` and its sibling crates. While these are focussed on http examples,
185//! note that:
186//!
187//! - `tower-async` can work for any request-response flow (akin to `tower`);
188//! - you can also use `tower-async` with http web services without making use of the `tower-async-http` crate,
189//!   it only is there to provide extra middleware for http-specific purposes, but this is all optional.
190//!
191//! The documentation also contains some smaller examples and of course the codebase can be read as well,
192//! together with its unit tests.
193//!
194//! [`Service`]: https://docs.rs/tower-async/latest/tower-async/trait.Service.html
195//! [`Layer`]: https://docs.rs/tower-async/latest/tower-async/trait.Layer.html
196//! [all_layers]: https://docs.rs/tower-async/latest/tower-async/#modules
197//! [timeouts]: https://docs.rs/tower-async/latest/tower-async/timeout/
198//! [`ServiceBuilder`]: https://docs.rs/tower-async/latest/tower-async/struct.ServiceBuilder.html
199//! [utilities]: https://docs.rs/tower-async/latest/tower-async/trait.ServiceExt.html
200//! [`tower-async`]: https://crates.io/crates/tower
201//! [`tower-async-bridge`]: https://crates.io/crates/tower-async-bridge
202//! [`tower-async-service`]: https://crates.io/crates/tower-async-service
203//! [`tower-async-layer`]: https://crates.io/crates/tower-async-layer
204//! [open a PR]: https://github.com/plabayo/tower-async/compare
205//!
206//! [`tower`]: https://docs.rs/tower/*/tower
207//! [`tower::Service`]: https://docs.rs/tower/*/tower/trait.Service.html
208//! [`tower::ServiceBuilder`]: https://docs.rs/tower/*/tower/builder/struct.ServiceBuilder.html
209//! [`tower::Layer`]: https://docs.rs/tower/*/tower/trait.Layer.html
210//! [`tower_async`]: https://docs.rs/tower-async/*/tower_async
211//! [`tower_async::Service`]: https://docs.rs/tower-async-service/*/tower_async_service/trait.Service.html
212//! [`tower_async::ServiceBuilder`]: https://docs.rs/tower-async/*/tower_async/builder/struct.ServiceBuilder.html
213//! [`tower_async::Layer`]: https://docs.rs/tower-async-layer/*/tower_async_layer/trait.Layer.html
214//!
215//! ## Supported Rust Versions
216//!
217//! Tower Async requires nightly Rust for the time being and has no backwards compatibility
218//! promises for the time being.
219//!
220//! Once `async traits` are stabilized we'll start supporting stable rust once again,
221//! and we can start working towards backwards compatibility.
222//!
223//! Read <https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizing-async-fn-in-trait.html> for more information
224//! on this roadmap by the Rust Language Core Team.
225
226#[cfg(feature = "filter")]
227pub mod filter;
228
229#[cfg(feature = "limit")]
230pub mod limit;
231
232#[cfg(feature = "make")]
233pub mod make;
234#[cfg(feature = "retry")]
235pub mod retry;
236#[cfg(feature = "timeout")]
237pub mod timeout;
238#[cfg(feature = "util")]
239pub mod util;
240
241pub mod builder;
242pub mod layer;
243
244#[cfg(feature = "util")]
245#[doc(inline)]
246pub use self::util::{service_fn, ServiceExt};
247
248#[doc(inline)]
249pub use crate::builder::ServiceBuilder;
250#[cfg(feature = "make")]
251#[doc(inline)]
252pub use crate::make::MakeService;
253#[doc(inline)]
254pub use tower_async_layer::Layer;
255#[doc(inline)]
256pub use tower_async_service::Service;
257
258#[allow(unreachable_pub)]
259mod sealed {
260    pub trait Sealed<T> {}
261}
262
263/// Alias for a type-erased error type.
264pub type BoxError = Box<dyn std::error::Error + Send + Sync>;