1use std::fmt;
6use std::time::Duration;
7
8#[derive(Debug, Clone)]
23pub struct ServeLimits {
24 pub max_request_size: usize,
26 pub max_headers: usize,
28 pub max_header_size: usize,
30 pub keep_alive_timeout: Duration,
32 pub client_timeout: Duration,
34 pub max_pipelined: usize,
36 pub max_connections: usize,
38}
39
40impl Default for ServeLimits {
41 fn default() -> Self {
42 Self {
43 max_request_size: 2 * 1024 * 1024, max_headers: 100,
45 max_header_size: 8 * 1024, keep_alive_timeout: Duration::from_secs(5),
47 client_timeout: Duration::from_secs(5),
48 max_pipelined: 16,
49 max_connections: 1024,
50 }
51 }
52}
53
54impl ServeLimits {
55 pub fn new() -> Self {
57 Self::default()
58 }
59
60 #[must_use]
62 pub fn with_max_request_size(mut self, size: usize) -> Self {
63 self.max_request_size = size;
64 self
65 }
66
67 #[must_use]
69 pub fn with_max_headers(mut self, count: usize) -> Self {
70 self.max_headers = count;
71 self
72 }
73
74 #[must_use]
76 pub fn with_max_connections(mut self, count: usize) -> Self {
77 self.max_connections = count;
78 self
79 }
80
81 pub fn validate_request(
83 &self,
84 headers_count: usize,
85 body_size: usize,
86 ) -> Result<(), LimitError> {
87 if headers_count > self.max_headers {
88 return Err(LimitError::TooManyHeaders { count: headers_count, max: self.max_headers });
89 }
90 if body_size > self.max_request_size {
91 return Err(LimitError::BodyTooLarge { size: body_size, max: self.max_request_size });
92 }
93 Ok(())
94 }
95
96 pub fn validate_header_size(&self, size: usize) -> Result<(), LimitError> {
98 if size > self.max_header_size {
99 return Err(LimitError::HeaderTooLarge { size, max: self.max_header_size });
100 }
101 Ok(())
102 }
103
104 pub fn validate_pipelined(&self, count: usize) -> Result<(), LimitError> {
106 if count > self.max_pipelined {
107 return Err(LimitError::TooManyPipelined { count, max: self.max_pipelined });
108 }
109 Ok(())
110 }
111
112 pub fn validate_connections(&self, current: usize) -> Result<(), LimitError> {
114 if current >= self.max_connections {
115 return Err(LimitError::ConnectionLimitReached { current, max: self.max_connections });
116 }
117 Ok(())
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum LimitError {
124 TooManyHeaders {
126 count: usize,
128 max: usize,
130 },
131 BodyTooLarge {
133 size: usize,
135 max: usize,
137 },
138 HeaderTooLarge {
140 size: usize,
142 max: usize,
144 },
145 TooManyPipelined {
147 count: usize,
149 max: usize,
151 },
152 ConnectionLimitReached {
154 current: usize,
156 max: usize,
158 },
159}
160
161impl fmt::Display for LimitError {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 match self {
164 LimitError::TooManyHeaders { count, max } => {
165 write!(f, "too many headers: {} (max {})", count, max)
166 }
167 LimitError::BodyTooLarge { size, max } => {
168 write!(f, "body too large: {} bytes (max {})", size, max)
169 }
170 LimitError::HeaderTooLarge { size, max } => {
171 write!(f, "header too large: {} bytes (max {})", size, max)
172 }
173 LimitError::TooManyPipelined { count, max } => {
174 write!(f, "too many pipelined requests: {} (max {})", count, max)
175 }
176 LimitError::ConnectionLimitReached { current, max } => {
177 write!(f, "connection limit reached: {} (max {})", current, max)
178 }
179 }
180 }
181}
182
183impl std::error::Error for LimitError {}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_serve_limits_default() {
191 let limits = ServeLimits::default();
192 assert_eq!(limits.max_request_size, 2 * 1024 * 1024);
193 assert_eq!(limits.max_headers, 100);
194 assert_eq!(limits.max_header_size, 8 * 1024);
195 assert_eq!(limits.max_pipelined, 16);
196 assert_eq!(limits.max_connections, 1024);
197 }
198
199 #[test]
200 fn test_serve_limits_builder() {
201 let limits = ServeLimits::new()
202 .with_max_request_size(1024)
203 .with_max_headers(50)
204 .with_max_connections(100);
205
206 assert_eq!(limits.max_request_size, 1024);
207 assert_eq!(limits.max_headers, 50);
208 assert_eq!(limits.max_connections, 100);
209 }
210
211 #[test]
212 fn test_validate_request_ok() {
213 let limits = ServeLimits::default();
214 assert!(limits.validate_request(50, 1024).is_ok());
215 }
216
217 #[test]
218 fn test_validate_request_too_many_headers() {
219 let limits = ServeLimits::default();
220 let result = limits.validate_request(200, 1024);
221 assert!(matches!(result, Err(LimitError::TooManyHeaders { .. })));
222 }
223
224 #[test]
225 fn test_validate_request_body_too_large() {
226 let limits = ServeLimits::default();
227 let result = limits.validate_request(50, 10 * 1024 * 1024);
228 assert!(matches!(result, Err(LimitError::BodyTooLarge { .. })));
229 }
230
231 #[test]
232 fn test_validate_header_size_ok() {
233 let limits = ServeLimits::default();
234 assert!(limits.validate_header_size(1024).is_ok());
235 }
236
237 #[test]
238 fn test_validate_header_size_too_large() {
239 let limits = ServeLimits::default();
240 let result = limits.validate_header_size(16 * 1024);
241 assert!(matches!(result, Err(LimitError::HeaderTooLarge { .. })));
242 }
243
244 #[test]
245 fn test_validate_pipelined_ok() {
246 let limits = ServeLimits::default();
247 assert!(limits.validate_pipelined(10).is_ok());
248 }
249
250 #[test]
251 fn test_validate_pipelined_too_many() {
252 let limits = ServeLimits::default();
253 let result = limits.validate_pipelined(20);
254 assert!(matches!(result, Err(LimitError::TooManyPipelined { .. })));
255 }
256
257 #[test]
258 fn test_validate_connections_ok() {
259 let limits = ServeLimits::default();
260 assert!(limits.validate_connections(500).is_ok());
261 }
262
263 #[test]
264 fn test_validate_connections_limit_reached() {
265 let limits = ServeLimits::default();
266 let result = limits.validate_connections(1024);
267 assert!(matches!(result, Err(LimitError::ConnectionLimitReached { .. })));
268 }
269
270 #[test]
271 fn test_limit_error_display() {
272 let err = LimitError::TooManyHeaders { count: 150, max: 100 };
273 assert_eq!(format!("{}", err), "too many headers: 150 (max 100)");
274
275 let err = LimitError::BodyTooLarge { size: 5000000, max: 2097152 };
276 assert_eq!(format!("{}", err), "body too large: 5000000 bytes (max 2097152)");
277 }
278
279 #[test]
280 fn test_limit_error_eq() {
281 let err1 = LimitError::TooManyHeaders { count: 150, max: 100 };
282 let err2 = LimitError::TooManyHeaders { count: 150, max: 100 };
283 let err3 = LimitError::TooManyHeaders { count: 200, max: 100 };
284
285 assert_eq!(err1, err2);
286 assert_ne!(err1, err3);
287 }
288
289 #[test]
293 fn test_falsify_exact_boundaries() {
294 let limits = ServeLimits::new()
295 .with_max_headers(100)
296 .with_max_request_size(1000)
297 .with_max_connections(10);
298
299 assert!(limits.validate_request(100, 0).is_ok());
301 assert!(limits.validate_request(101, 0).is_err());
302
303 assert!(limits.validate_request(0, 1000).is_ok());
305 assert!(limits.validate_request(0, 1001).is_err());
306
307 assert!(limits.validate_connections(9).is_ok());
309 assert!(limits.validate_connections(10).is_err());
310 }
311
312 #[test]
314 fn test_falsify_zero_values_pass() {
315 let limits = ServeLimits::default();
316
317 assert!(
319 limits.validate_request(0, 0).is_ok(),
320 "FALSIFICATION FAILED: Zero values should always pass"
321 );
322 assert!(
323 limits.validate_header_size(0).is_ok(),
324 "FALSIFICATION FAILED: Zero header size should pass"
325 );
326 assert!(
327 limits.validate_pipelined(0).is_ok(),
328 "FALSIFICATION FAILED: Zero pipelined should pass"
329 );
330 assert!(
331 limits.validate_connections(0).is_ok(),
332 "FALSIFICATION FAILED: Zero connections should pass"
333 );
334 }
335}