moirai_http/server/
config.rs1use std::io;
4use std::time::Duration;
5
6use crate::request::MAX_HEADER_SLOTS;
7
8pub const DEFAULT_MAX_CONNECTIONS: usize = 256;
10pub const DEFAULT_MAX_HEADER_BYTES: usize = 16 * 1024;
12pub const DEFAULT_MAX_HEADER_COUNT: usize = 64;
14pub const DEFAULT_MAX_BODY_BYTES: usize = 1024 * 1024;
16pub const DEFAULT_MAX_RESPONSE_BYTES: usize = 4 * 1024 * 1024;
18pub const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(30);
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct ServerConfig {
24 pub max_connections: usize,
26 pub max_header_bytes: usize,
28 pub max_header_count: usize,
30 pub max_body_bytes: usize,
32 pub max_response_bytes: usize,
34 pub request_timeout: Duration,
36}
37
38impl Default for ServerConfig {
39 fn default() -> Self {
40 Self {
41 max_connections: DEFAULT_MAX_CONNECTIONS,
42 max_header_bytes: DEFAULT_MAX_HEADER_BYTES,
43 max_header_count: DEFAULT_MAX_HEADER_COUNT,
44 max_body_bytes: DEFAULT_MAX_BODY_BYTES,
45 max_response_bytes: DEFAULT_MAX_RESPONSE_BYTES,
46 request_timeout: DEFAULT_REQUEST_TIMEOUT,
47 }
48 }
49}
50
51impl ServerConfig {
52 pub fn new(
59 max_connections: usize,
60 max_header_bytes: usize,
61 max_header_count: usize,
62 max_body_bytes: usize,
63 max_response_bytes: usize,
64 request_timeout: Duration,
65 ) -> io::Result<Self> {
66 let config = Self {
67 max_connections,
68 max_header_bytes,
69 max_header_count,
70 max_body_bytes,
71 max_response_bytes,
72 request_timeout,
73 };
74 config.validate()?;
75 Ok(config)
76 }
77
78 pub fn validate(&self) -> io::Result<()> {
84 if self.max_connections == 0
85 || self.max_header_bytes == 0
86 || self.max_header_count < 2
87 || self.max_header_count > MAX_HEADER_SLOTS
88 || self.max_body_bytes == 0
89 || self.max_response_bytes == 0
90 || self.request_timeout.is_zero()
91 {
92 return Err(invalid_input(
93 "HTTP server limits and deadline must be non-zero and bounded",
94 ));
95 }
96 Ok(())
97 }
98}
99
100fn invalid_input(message: &str) -> io::Error {
101 io::Error::new(io::ErrorKind::InvalidInput, message)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn configuration_rejects_unbounded_values() {
110 assert!(ServerConfig::new(0, 1024, 4, 1024, 1024, Duration::from_secs(1)).is_err());
111 assert!(ServerConfig::new(1, 1024, 1, 1024, 1024, Duration::from_secs(1)).is_err());
112 assert!(
113 ServerConfig::new(
114 1,
115 1024,
116 MAX_HEADER_SLOTS + 1,
117 1024,
118 1024,
119 Duration::from_secs(1)
120 )
121 .is_err()
122 );
123 assert!(ServerConfig::new(1, 1024, 4, 1024, 1024, Duration::ZERO).is_err());
124 }
125}