tower_http/timeout/mod.rs
1//! Middleware that applies a timeout to requests.
2//!
3//! If the request does not complete within the specified timeout, it will be aborted and a
4//! response with an empty body and a custom status code will be returned.
5//!
6//! # Differences from `tower::timeout`
7//!
8//! tower's [`Timeout`](tower::timeout::Timeout) middleware uses an error to signal timeout, i.e.
9//! it changes the error type to [`BoxError`](tower::BoxError). For HTTP services that is rarely
10//! what you want as returning errors will terminate the connection without sending a response.
11//!
12//! This middleware won't change the error type and instead returns a response with an empty body
13//! and the specified status code. That means if your service's error type is [`Infallible`], it will
14//! still be [`Infallible`] after applying this middleware.
15//!
16//! # Body timeouts
17//!
18//! Two body timeout wrappers are available for limiting how long a request or response body
19//! transfer can take:
20//!
21//! - [`TimeoutBody`] resets its deadline each time a frame is received. Use this to detect
22//! idle connections where no data flows for a period of time.
23//! - [`DeadlineBody`] starts a single timer at construction and never resets it. Use
24//! this to cap the total wall-clock time spent transferring a body, regardless of how
25//! frequently data arrives.
26//!
27//! Both are applied via their corresponding layer types ([`RequestBodyTimeoutLayer`] /
28//! [`RequestBodyDeadlineLayer`] for request bodies, [`ResponseBodyTimeoutLayer`] /
29//! [`ResponseBodyDeadlineLayer`] for response bodies). They can be stacked if you
30//! want both an idle timeout and an absolute deadline.
31//!
32//! # Example
33//!
34//! ```
35//! use http::{Request, Response, StatusCode};
36//! use http_body_util::Full;
37//! use bytes::Bytes;
38//! use std::{convert::Infallible, time::Duration};
39//! use tower::ServiceBuilder;
40//! use tower_http::timeout::TimeoutLayer;
41//!
42//! async fn handle(_: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, Infallible> {
43//! // ...
44//! # Ok(Response::new(Full::default()))
45//! }
46//!
47//! # #[tokio::main]
48//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
49//! let svc = ServiceBuilder::new()
50//! // Timeout requests after 30 seconds with the specified status code
51//! .layer(TimeoutLayer::with_status_code(StatusCode::REQUEST_TIMEOUT, Duration::from_secs(30)))
52//! .service_fn(handle);
53//! # Ok(())
54//! # }
55//! ```
56//!
57//! [`Infallible`]: std::convert::Infallible
58
59mod body;
60mod deadline_body;
61mod service;
62
63pub use body::{TimeoutBody, TimeoutError};
64pub use deadline_body::DeadlineBody;
65pub use service::{
66 RequestBodyDeadline, RequestBodyDeadlineLayer, RequestBodyTimeout, RequestBodyTimeoutLayer,
67 ResponseBodyDeadline, ResponseBodyDeadlineLayer, ResponseBodyTimeout, ResponseBodyTimeoutLayer,
68 Timeout, TimeoutLayer,
69};