icap_rs/server/timeouts.rs
1//! Server-side timeout configuration.
2//!
3//! Group all per-connection deadlines in one struct so they can be configured
4//! at once via [`ServerBuilder::with_timeouts`](super::builder::ServerBuilder::with_timeouts)
5//! and stored inside the [`Server`](super::Server) as a single field.
6//!
7//! All fields default to `None` (no timeout). TLS handshake timeouts are
8//! configured on [`ServerTlsConfig`](crate::tls::ServerTlsConfig).
9
10use std::time::Duration;
11
12/// Aggregated server deadlines applied per connection and for graceful shutdown.
13///
14/// - [`header_read`](Self::header_read): max time to receive a full ICAP header
15/// block (`CRLFCRLF`) once the request has started arriving. Mitigates
16/// slowloris-style header attacks.
17/// - [`body_read`](Self::body_read): max time budget for reading the encapsulated
18/// body of a single request (chunked decoding included).
19/// - [`write`](Self::write): max time to write any single response chunk to the
20/// client.
21/// - [`idle_keepalive`](Self::idle_keepalive): max time to wait for the **first**
22/// byte of the next request on a kept-alive connection (after the previous
23/// response was flushed). Used only for the leading read; once any bytes
24/// arrive, [`header_read`](Self::header_read) governs the rest of the header
25/// block.
26/// - [`shutdown_drain`](Self::shutdown_drain): max time to wait for in-flight
27/// requests to finish after a shutdown signal. If the deadline expires, the
28/// remaining connections are cancelled. When `None` the server waits
29/// indefinitely.
30#[derive(Debug, Clone, Default)]
31#[must_use]
32pub struct ServerTimeouts {
33 pub header_read: Option<Duration>,
34 pub body_read: Option<Duration>,
35 pub write: Option<Duration>,
36 pub idle_keepalive: Option<Duration>,
37 pub shutdown_drain: Option<Duration>,
38}
39
40impl ServerTimeouts {
41 /// Construct a `ServerTimeouts` with every deadline disabled (`None`).
42 pub const fn new() -> Self {
43 Self {
44 header_read: None,
45 body_read: None,
46 write: None,
47 idle_keepalive: None,
48 shutdown_drain: None,
49 }
50 }
51
52 /// Set the [`header_read`](Self::header_read) deadline.
53 ///
54 /// Limits how long the server waits to receive a full ICAP header block
55 /// (`CRLFCRLF`) once the request has started arriving.
56 pub const fn with_header_read(mut self, dur: Duration) -> Self {
57 self.header_read = Some(dur);
58 self
59 }
60
61 /// Set the [`body_read`](Self::body_read) deadline.
62 ///
63 /// Bounds the time budget for reading the encapsulated body of a single
64 /// request, including chunked decoding.
65 pub const fn with_body_read(mut self, dur: Duration) -> Self {
66 self.body_read = Some(dur);
67 self
68 }
69
70 /// Set the [`write`](Self::write) deadline.
71 ///
72 /// Bounds the time to write any single response chunk to the client.
73 pub const fn with_write(mut self, dur: Duration) -> Self {
74 self.write = Some(dur);
75 self
76 }
77
78 /// Set the [`idle_keepalive`](Self::idle_keepalive) deadline.
79 ///
80 /// Bounds how long the server waits for the **first** byte of the next
81 /// request on a kept-alive connection after the previous response was
82 /// flushed. Once any byte arrives, [`with_header_read`](Self::with_header_read)
83 /// governs the rest of the header block.
84 pub const fn with_idle_keepalive(mut self, dur: Duration) -> Self {
85 self.idle_keepalive = Some(dur);
86 self
87 }
88
89 /// Set the [`shutdown_drain`](Self::shutdown_drain) deadline.
90 ///
91 /// Bounds how long the server waits for active connections to finish after
92 /// a shutdown signal. Connections still in flight when the deadline expires
93 /// are cancelled. When not set the drain waits indefinitely.
94 pub const fn with_shutdown_drain(mut self, dur: Duration) -> Self {
95 self.shutdown_drain = Some(dur);
96 self
97 }
98}