praxis_core/config/
body_limits.rs1use serde::Deserialize;
7
8pub 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)]
50#[serde(default, deny_unknown_fields)]
51pub struct BodyLimitsConfig {
52 #[serde(default = "default_max_body_bytes")]
57 pub max_request_bytes: Option<usize>,
58
59 #[serde(default = "default_max_body_bytes")]
64 pub max_response_bytes: Option<usize>,
65}
66
67impl Default for BodyLimitsConfig {
68 fn default() -> Self {
69 Self {
70 max_request_bytes: default_max_body_bytes(),
71 max_response_bytes: default_max_body_bytes(),
72 }
73 }
74}
75
76#[expect(clippy::unnecessary_wraps, reason = "serde default requires matching field type")]
78fn default_max_body_bytes() -> Option<usize> {
79 Some(DEFAULT_MAX_BODY_BYTES)
80}
81
82#[cfg(test)]
87#[expect(clippy::allow_attributes, reason = "blanket test suppressions")]
88#[allow(
89 clippy::unwrap_used,
90 clippy::expect_used,
91 clippy::indexing_slicing,
92 clippy::needless_raw_strings,
93 clippy::needless_raw_string_hashes,
94 reason = "tests use unwrap/expect/indexing/raw strings for brevity"
95)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn defaults_are_ten_mib() {
101 let limits = BodyLimitsConfig::default();
102 assert_eq!(
103 limits.max_request_bytes,
104 Some(DEFAULT_MAX_BODY_BYTES),
105 "max_request_bytes should default to 10 MiB"
106 );
107 assert_eq!(
108 limits.max_response_bytes,
109 Some(DEFAULT_MAX_BODY_BYTES),
110 "max_response_bytes should default to 10 MiB"
111 );
112 }
113
114 #[test]
115 fn parse_full_config() {
116 let limits: BodyLimitsConfig = serde_yaml::from_str(
117 r#"
118max_request_bytes: 1048576
119max_response_bytes: 524288
120"#,
121 )
122 .unwrap();
123 assert_eq!(
124 limits.max_request_bytes,
125 Some(1_048_576),
126 "max_request_bytes should be parsed"
127 );
128 assert_eq!(
129 limits.max_response_bytes,
130 Some(524_288),
131 "max_response_bytes should be parsed"
132 );
133 }
134
135 #[test]
136 fn parse_empty_yields_defaults() {
137 let limits: BodyLimitsConfig = serde_yaml::from_str("{}").unwrap();
138 assert_eq!(
139 limits.max_request_bytes,
140 Some(DEFAULT_MAX_BODY_BYTES),
141 "empty YAML should use 10 MiB defaults"
142 );
143 assert_eq!(
144 limits.max_response_bytes,
145 Some(DEFAULT_MAX_BODY_BYTES),
146 "empty YAML should use 10 MiB defaults"
147 );
148 }
149
150 #[test]
151 fn parse_explicit_null_yields_none() {
152 let limits: BodyLimitsConfig = serde_yaml::from_str(
153 r#"
154max_request_bytes: null
155max_response_bytes: null
156"#,
157 )
158 .unwrap();
159 assert!(limits.max_request_bytes.is_none(), "explicit null should be None");
160 assert!(limits.max_response_bytes.is_none(), "explicit null should be None");
161 }
162}