1use serde::{Deserialize, Serialize};
6use std::net::SocketAddr;
7use std::path::PathBuf;
8use std::time::Duration;
9
10#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12pub struct ProxyConfig {
13 #[serde(default)]
15 pub server: ServerConfig,
16
17 #[serde(default)]
19 pub tls: Option<TlsConfig>,
20
21 #[serde(default)]
23 pub pool: PoolConfig,
24
25 #[serde(default)]
27 pub timeouts: TimeoutConfig,
28
29 #[serde(default)]
31 pub headers: HeaderConfig,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ServerConfig {
37 #[serde(default = "default_http_addr")]
39 pub http_addr: SocketAddr,
40
41 #[serde(default = "default_https_addr")]
43 pub https_addr: SocketAddr,
44
45 #[serde(default = "default_http2_enabled")]
47 pub http2_enabled: bool,
48
49 #[serde(default = "default_max_connections")]
51 pub max_connections: usize,
52}
53
54fn default_http_addr() -> SocketAddr {
55 "0.0.0.0:80".parse().unwrap()
56}
57
58fn default_https_addr() -> SocketAddr {
59 "0.0.0.0:443".parse().unwrap()
60}
61
62fn default_http2_enabled() -> bool {
63 true
64}
65
66fn default_max_connections() -> usize {
67 10000
68}
69
70impl Default for ServerConfig {
71 fn default() -> Self {
72 Self {
73 http_addr: default_http_addr(),
74 https_addr: default_https_addr(),
75 http2_enabled: default_http2_enabled(),
76 max_connections: default_max_connections(),
77 }
78 }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct TlsConfig {
84 pub cert_path: PathBuf,
86
87 pub key_path: PathBuf,
89
90 #[serde(default = "default_min_tls_version")]
92 pub min_version: TlsVersion,
93
94 #[serde(default = "default_true")]
96 pub alpn_h2: bool,
97}
98
99fn default_min_tls_version() -> TlsVersion {
100 TlsVersion::Tls12
101}
102
103fn default_true() -> bool {
104 true
105}
106
107#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
109pub enum TlsVersion {
110 #[serde(rename = "1.2")]
111 Tls12,
112 #[serde(rename = "1.3")]
113 Tls13,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct PoolConfig {
119 #[serde(default = "default_max_idle")]
121 pub max_idle_per_backend: usize,
122
123 #[serde(default = "default_idle_timeout")]
125 pub idle_timeout: Duration,
126}
127
128fn default_max_idle() -> usize {
129 32
130}
131
132fn default_idle_timeout() -> Duration {
133 Duration::from_secs(90)
134}
135
136impl Default for PoolConfig {
137 fn default() -> Self {
138 Self {
139 max_idle_per_backend: default_max_idle(),
140 idle_timeout: default_idle_timeout(),
141 }
142 }
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct TimeoutConfig {
148 #[serde(default = "default_connect_timeout")]
150 pub connect: Duration,
151
152 #[serde(default = "default_request_timeout")]
154 pub request: Duration,
155
156 #[serde(default = "default_read_timeout")]
158 pub read: Duration,
159
160 #[serde(default = "default_write_timeout")]
162 pub write: Duration,
163}
164
165fn default_connect_timeout() -> Duration {
166 Duration::from_secs(5)
167}
168
169fn default_request_timeout() -> Duration {
170 Duration::from_secs(30)
171}
172
173fn default_read_timeout() -> Duration {
174 Duration::from_secs(30)
175}
176
177fn default_write_timeout() -> Duration {
178 Duration::from_secs(30)
179}
180
181impl Default for TimeoutConfig {
182 fn default() -> Self {
183 Self {
184 connect: default_connect_timeout(),
185 request: default_request_timeout(),
186 read: default_read_timeout(),
187 write: default_write_timeout(),
188 }
189 }
190}
191
192#[allow(clippy::struct_excessive_bools)]
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct HeaderConfig {
196 #[serde(default = "default_true")]
198 pub x_forwarded_for: bool,
199
200 #[serde(default = "default_true")]
202 pub x_forwarded_proto: bool,
203
204 #[serde(default = "default_true")]
206 pub x_forwarded_host: bool,
207
208 #[serde(default = "default_true")]
210 pub x_real_ip: bool,
211
212 #[serde(default = "default_true")]
214 pub via: bool,
215
216 #[serde(default = "default_server_name")]
218 pub server_name: String,
219
220 #[serde(default = "default_true")]
222 pub hsts: bool,
223
224 #[serde(default = "default_hsts_max_age")]
226 pub hsts_max_age: u64,
227
228 #[serde(default = "default_true")]
230 pub hsts_subdomains: bool,
231}
232
233fn default_server_name() -> String {
234 "zlayer-proxy".to_string()
235}
236
237fn default_hsts_max_age() -> u64 {
238 31_536_000 }
240
241impl Default for HeaderConfig {
242 fn default() -> Self {
243 Self {
244 x_forwarded_for: true,
245 x_forwarded_proto: true,
246 x_forwarded_host: true,
247 x_real_ip: true,
248 via: true,
249 server_name: default_server_name(),
250 hsts: true,
251 hsts_max_age: default_hsts_max_age(),
252 hsts_subdomains: true,
253 }
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260
261 #[test]
262 fn test_default_config() {
263 let config = ProxyConfig::default();
264 assert_eq!(
265 config.server.http_addr,
266 "0.0.0.0:80".parse::<SocketAddr>().unwrap()
267 );
268 assert!(config.server.http2_enabled);
269 assert!(config.tls.is_none());
270 assert_eq!(config.timeouts.connect, Duration::from_secs(5));
271 }
272
273 #[test]
274 fn test_config_serialization() {
275 let config = ProxyConfig::default();
276 let json = serde_json::to_string(&config).unwrap();
277 let parsed: ProxyConfig = serde_json::from_str(&json).unwrap();
278 assert_eq!(parsed.server.http_addr, config.server.http_addr);
279 }
280}