use std::time::Duration;
pub const MAX_HEADERS_CEILING: usize = 128;
#[derive(Clone, Debug)]
pub struct Limits {
pub max_head_bytes: usize,
pub max_headers: usize,
pub max_body_bytes: u64,
pub header_timeout: Duration,
pub body_timeout: Duration,
pub idle_timeout: Duration,
pub write_timeout: Duration,
}
impl Limits {
pub(crate) fn clamp_max_headers(&mut self) {
if self.max_headers > MAX_HEADERS_CEILING {
tracing::warn!(
configured = self.max_headers,
ceiling = MAX_HEADERS_CEILING,
"Limits::max_headers exceeds MAX_HEADERS_CEILING; clamping"
);
self.max_headers = MAX_HEADERS_CEILING;
}
}
}
impl Default for Limits {
fn default() -> Self {
Self {
max_head_bytes: 16 * 1024,
max_headers: 96,
max_body_bytes: 2 * 1024 * 1024,
header_timeout: Duration::from_secs(10),
body_timeout: Duration::from_secs(30),
idle_timeout: Duration::from_secs(75),
write_timeout: Duration::from_secs(30),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_are_the_documented_values() {
let l = Limits::default();
assert_eq!(l.max_head_bytes, 16 * 1024);
assert_eq!(l.max_headers, 96);
assert_eq!(l.max_body_bytes, 2 * 1024 * 1024);
assert_eq!(l.header_timeout, Duration::from_secs(10));
assert_eq!(l.body_timeout, Duration::from_secs(30));
assert_eq!(l.idle_timeout, Duration::from_secs(75));
assert_eq!(l.write_timeout, Duration::from_secs(30));
}
#[test]
fn max_headers_fits_the_parser_scratch_array() {
assert!(Limits::default().max_headers <= MAX_HEADERS_CEILING);
}
#[test]
fn builder_overrides_apply() {
let l = Limits {
max_body_bytes: 64,
..Default::default()
};
assert_eq!(l.max_body_bytes, 64);
assert_eq!(l.max_headers, 96, "unrelated fields keep their defaults");
}
}