use serde::Deserialize;
pub const DEFAULT_MAX_BODY_BYTES: usize = 10_485_760;
pub const ABSOLUTE_MAX_BODY_BYTES: usize = 67_108_864;
#[derive(Debug, Clone, Deserialize, serde::Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct BodyLimitsConfig {
#[serde(default = "default_max_body_bytes")]
pub max_request_bytes: Option<usize>,
#[serde(default = "default_max_body_bytes")]
pub max_response_bytes: Option<usize>,
}
impl Default for BodyLimitsConfig {
fn default() -> Self {
Self {
max_request_bytes: default_max_body_bytes(),
max_response_bytes: default_max_body_bytes(),
}
}
}
#[expect(clippy::unnecessary_wraps, reason = "serde default requires matching field type")]
fn default_max_body_bytes() -> Option<usize> {
Some(DEFAULT_MAX_BODY_BYTES)
}
#[cfg(test)]
#[expect(clippy::allow_attributes, reason = "blanket test suppressions")]
#[allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::indexing_slicing,
clippy::needless_raw_strings,
clippy::needless_raw_string_hashes,
reason = "tests use unwrap/expect/indexing/raw strings for brevity"
)]
mod tests {
use super::*;
#[test]
fn defaults_are_ten_mib() {
let limits = BodyLimitsConfig::default();
assert_eq!(
limits.max_request_bytes,
Some(DEFAULT_MAX_BODY_BYTES),
"max_request_bytes should default to 10 MiB"
);
assert_eq!(
limits.max_response_bytes,
Some(DEFAULT_MAX_BODY_BYTES),
"max_response_bytes should default to 10 MiB"
);
}
#[test]
fn parse_full_config() {
let limits: BodyLimitsConfig = serde_yaml::from_str(
r#"
max_request_bytes: 1048576
max_response_bytes: 524288
"#,
)
.unwrap();
assert_eq!(
limits.max_request_bytes,
Some(1_048_576),
"max_request_bytes should be parsed"
);
assert_eq!(
limits.max_response_bytes,
Some(524_288),
"max_response_bytes should be parsed"
);
}
#[test]
fn parse_empty_yields_defaults() {
let limits: BodyLimitsConfig = serde_yaml::from_str("{}").unwrap();
assert_eq!(
limits.max_request_bytes,
Some(DEFAULT_MAX_BODY_BYTES),
"empty YAML should use 10 MiB defaults"
);
assert_eq!(
limits.max_response_bytes,
Some(DEFAULT_MAX_BODY_BYTES),
"empty YAML should use 10 MiB defaults"
);
}
#[test]
fn parse_explicit_null_yields_none() {
let limits: BodyLimitsConfig = serde_yaml::from_str(
r#"
max_request_bytes: null
max_response_bytes: null
"#,
)
.unwrap();
assert!(limits.max_request_bytes.is_none(), "explicit null should be None");
assert!(limits.max_response_bytes.is_none(), "explicit null should be None");
}
}