tower_timeout/
lib.rs

1#![doc(html_root_url = "https://docs.rs/tower-timeout/0.3.0")]
2#![warn(
3    missing_debug_implementations,
4    missing_docs,
5    rust_2018_idioms,
6    unreachable_pub
7)]
8
9//! Tower middleware that applies a timeout to requests.
10//!
11//! If the response does not complete within the specified timeout, the response
12//! will be aborted.
13
14pub mod error;
15pub mod future;
16mod layer;
17
18pub use crate::layer::TimeoutLayer;
19
20use crate::{error::Error, future::ResponseFuture};
21use std::task::{Context, Poll};
22use std::time::Duration;
23use tower_service::Service;
24
25/// Applies a timeout to requests.
26#[derive(Debug, Clone)]
27pub struct Timeout<T> {
28    inner: T,
29    timeout: Duration,
30}
31
32// ===== impl Timeout =====
33
34impl<T> Timeout<T> {
35    /// Creates a new Timeout
36    pub fn new(inner: T, timeout: Duration) -> Self {
37        Timeout { inner, timeout }
38    }
39}
40
41impl<S, Request> Service<Request> for Timeout<S>
42where
43    S: Service<Request>,
44    S::Error: Into<Error>,
45{
46    type Response = S::Response;
47    type Error = Error;
48    type Future = ResponseFuture<S::Future>;
49
50    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
51        match self.inner.poll_ready(cx) {
52            Poll::Pending => Poll::Pending,
53            Poll::Ready(r) => Poll::Ready(r.map_err(Into::into)),
54        }
55    }
56
57    fn call(&mut self, request: Request) -> Self::Future {
58        let response = self.inner.call(request);
59        let sleep = tokio::time::delay_for(self.timeout);
60
61        ResponseFuture::new(response, sleep)
62    }
63}