diff --git a/src/extract/mod.rs b/src/extract/mod.rs index 5a870f68..6ba954e6 100644 --- a/src/extract/mod.rs +++ b/src/extract/mod.rs @@ -29,13 +29,6 @@ //! # }; //! ``` //! -//! Technically extractors can also be used as "guards", for example to require -//! that requests are authorized. However the recommended way to do that is -//! using Tower middleware, such as [`tower_http::auth::RequireAuthorization`]. -//! Extractors have to be applied to each handler, whereas middleware can be -//! applied to a whole stack at once, which is typically what you want for -//! authorization. -//! //! # Defining custom extractors //! //! You can also define your own extractors by implementing [`FromRequest`]: diff --git a/src/lib.rs b/src/lib.rs index 1fb4759d..6ec28d50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -485,7 +485,8 @@ //! # }; //! ``` //! -//! See the [`service`] module for more details. +//! Routing to arbitrary services in this way has complications for backpressure +//! ([`Service::poll_ready`]). See the [`service`] module for more details. //! //! # Nesting applications //! diff --git a/src/service/mod.rs b/src/service/mod.rs index 997e4a76..a0ba2080 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -28,8 +28,8 @@ //! //! Generally routing to one of multiple services and backpressure doesn't mix //! well. Ideally you would want ensure a service is ready to receive a request -//! before calling the service. However in order to know which service to call -//! you need the request... +//! before calling the it. However in order to know which service to call you +//! need the request... //! //! One approach is to not consider the router service itself ready until all //! destination services are ready. That is the approach used by @@ -37,15 +37,22 @@ //! //! Another approach is to always consider all services ready (always return //! `Poll::Ready(Ok(()))`) from `Service::poll_ready` and then actually drive -//! readiness inside the response future. This works well when your services -//! don't care about backpressure and are always ready anyway. +//! readiness inside the response future returned by `Service::call`. This works +//! well when your services don't care about backpressure and are always ready +//! anyway. //! -//! tower-web expects that most services used in your app wont care about +//! tower-web expects that all services used in your app wont care about //! backpressure and so it uses the latter strategy. However that means you //! should avoid routing to a service (or using a middleware) that _does_ care //! about backpressure. At the very least you should [load shed] so requests are //! dropped quickly and don't keep piling up. //! +//! It also means if `poll_ready` returns an error that error will be returned +//! in the response future from `call`, and _not_ from `poll_ready`. In that +//! case the underlying service will _not_ be discarded and will continue to be +//! used for future requests. Services that expect to be discarded if +//! `poll_ready` fails should _not_ be used with tower-web. +//! //! One possible approach is to only apply backpressure sensitive middleware //! around your entire app. This is possible because tower-web applications are //! themselves services: @@ -66,11 +73,12 @@ //! ``` //! //! However when applying middleware around your whole application in this way -//! you have to take care that errors are still being dealt with appropriately. +//! you have to take care that errors are still being handled with +//! appropriately. //! //! Also note that handlers created from async functions don't care about //! backpressure and are always ready. So if you're not using any Tower -//! middleware you don't have to worry about backpressure. +//! middleware you don't have to worry about any of this. //! //! [`Redirect`]: tower_http::services::Redirect //! [load shed]: tower::load_shed