1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use uuid::Uuid;
6
7#[derive(Clone, Debug, Serialize, Deserialize, Default)]
9pub struct ProxyConfig {
10 #[serde(default)]
12 pub server: ServerConfig,
13
14 #[serde(default)]
16 pub tls: TlsConfig,
17
18 #[serde(default)]
20 pub rate_limit: RateLimitDefaults,
21
22 #[serde(default)]
24 pub routes: Vec<Route>,
25
26 #[serde(default)]
28 pub upstreams: Vec<Upstream>,
29}
30
31#[derive(Clone, Debug, Serialize, Deserialize)]
33pub struct ServerConfig {
34 #[serde(default = "default_http_host")]
36 pub http_host: String,
37
38 #[serde(default = "default_http_port")]
40 pub http_port: u16,
41
42 #[serde(default = "default_https_host")]
44 pub https_host: String,
45
46 #[serde(default = "default_https_port")]
48 pub https_port: u16,
49
50 #[serde(default)]
52 pub https_enabled: bool,
53
54 #[serde(default = "default_true")]
56 pub database_config: bool,
57
58 pub config_file: Option<String>,
60
61 #[serde(default)]
63 pub watch_config_file: bool,
64}
65
66impl Default for ServerConfig {
67 fn default() -> Self {
68 Self {
69 http_host: default_http_host(),
70 http_port: default_http_port(),
71 https_host: default_https_host(),
72 https_port: default_https_port(),
73 https_enabled: false,
74 database_config: true,
75 config_file: None,
76 watch_config_file: false,
77 }
78 }
79}
80
81#[derive(Clone, Debug, Serialize, Deserialize)]
83pub struct TlsConfig {
84 #[serde(default)]
86 pub acme_enabled: bool,
87
88 #[serde(default = "default_acme_directory")]
90 pub acme_directory: String,
91
92 pub acme_email: Option<String>,
94
95 #[serde(default = "default_cert_dir")]
97 pub cert_dir: String,
98
99 #[serde(default)]
101 pub acme_staging: bool,
102}
103
104impl Default for TlsConfig {
105 fn default() -> Self {
106 Self {
107 acme_enabled: false,
108 acme_directory: default_acme_directory(),
109 acme_email: None,
110 cert_dir: default_cert_dir(),
111 acme_staging: false,
112 }
113 }
114}
115
116#[derive(Clone, Debug, Serialize, Deserialize)]
118pub struct RateLimitDefaults {
119 #[serde(default = "default_rate_limit_requests")]
121 pub requests: u32,
122
123 #[serde(default = "default_rate_limit_window")]
125 pub window_secs: u32,
126
127 #[serde(default = "default_burst")]
129 pub burst: u32,
130}
131
132impl Default for RateLimitDefaults {
133 fn default() -> Self {
134 Self {
135 requests: default_rate_limit_requests(),
136 window_secs: default_rate_limit_window(),
137 burst: default_burst(),
138 }
139 }
140}
141
142#[derive(Clone, Debug, Serialize, Deserialize)]
144pub struct Route {
145 pub id: Option<Uuid>,
147
148 pub name: String,
150
151 pub description: Option<String>,
153
154 #[serde(default, rename = "match")]
156 pub match_: RouteMatch,
157
158 #[serde(default = "default_priority")]
160 pub priority: i32,
161
162 pub upstream: String,
164
165 #[serde(default)]
167 pub strip_path: bool,
168
169 #[serde(default)]
171 pub add_headers: HashMap<String, String>,
172
173 #[serde(default)]
175 pub remove_headers: Vec<String>,
176
177 pub rate_limit: Option<RouteRateLimit>,
179
180 #[serde(default = "default_timeout")]
182 pub timeout_secs: u32,
183
184 #[serde(default)]
186 pub retry_count: u32,
187
188 #[serde(default = "default_true")]
190 pub enabled: bool,
191}
192
193#[derive(Clone, Debug, Default, Serialize, Deserialize)]
195pub struct RouteMatch {
196 pub host: Option<String>,
198
199 pub path: Option<String>,
201
202 #[serde(default)]
204 pub path_type: PathMatchType,
205
206 #[serde(default)]
208 pub headers: HashMap<String, String>,
209
210 pub methods: Option<Vec<String>>,
212}
213
214#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
216#[serde(rename_all = "lowercase")]
217pub enum PathMatchType {
218 #[default]
220 Prefix,
221 Exact,
223 Regex,
225}
226
227#[derive(Clone, Debug, Serialize, Deserialize)]
229pub struct RouteRateLimit {
230 pub requests: u32,
232 pub window_secs: u32,
234 #[serde(default)]
236 pub key: RateLimitKey,
237}
238
239#[derive(Clone, Debug, Default, Serialize, Deserialize)]
241#[serde(rename_all = "snake_case")]
242pub enum RateLimitKey {
243 #[default]
245 ClientIp,
246 Header(String),
248 Route,
250}
251
252#[derive(Clone, Debug, Serialize, Deserialize)]
254pub struct Upstream {
255 pub id: Option<Uuid>,
257
258 pub name: String,
260
261 pub description: Option<String>,
263
264 #[serde(default)]
266 pub lb_strategy: LoadBalanceStrategy,
267
268 #[serde(default)]
270 pub backends: Vec<Backend>,
271
272 #[serde(default)]
274 pub health_check: HealthCheckConfig,
275
276 #[serde(default = "default_true")]
278 pub enabled: bool,
279}
280
281#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
283#[serde(rename_all = "snake_case")]
284pub enum LoadBalanceStrategy {
285 #[default]
287 RoundRobin,
288 LeastConnections,
290 Weighted,
292 Random,
294 Sticky,
296}
297
298#[derive(Clone, Debug, Serialize, Deserialize)]
300pub struct Backend {
301 pub id: Option<Uuid>,
303
304 pub address: String,
306
307 #[serde(default = "default_scheme")]
309 pub scheme: String,
310
311 #[serde(default = "default_weight")]
313 pub weight: u32,
314
315 #[serde(default = "default_true")]
317 pub enabled: bool,
318}
319
320#[derive(Clone, Debug, Serialize, Deserialize)]
322pub struct HealthCheckConfig {
323 #[serde(default = "default_true")]
325 pub enabled: bool,
326
327 #[serde(default = "default_health_path")]
329 pub path: String,
330
331 #[serde(default = "default_health_interval")]
333 pub interval_secs: u32,
334
335 #[serde(default = "default_health_timeout")]
337 pub timeout_secs: u32,
338
339 #[serde(default = "default_healthy_threshold")]
341 pub healthy_threshold: u32,
342
343 #[serde(default = "default_unhealthy_threshold")]
345 pub unhealthy_threshold: u32,
346}
347
348impl Default for HealthCheckConfig {
349 fn default() -> Self {
350 Self {
351 enabled: true,
352 path: default_health_path(),
353 interval_secs: default_health_interval(),
354 timeout_secs: default_health_timeout(),
355 healthy_threshold: default_healthy_threshold(),
356 unhealthy_threshold: default_unhealthy_threshold(),
357 }
358 }
359}
360
361fn default_http_host() -> String {
363 "0.0.0.0".into()
364}
365fn default_http_port() -> u16 {
366 8080
367}
368fn default_https_host() -> String {
369 "0.0.0.0".into()
370}
371fn default_https_port() -> u16 {
372 8443
373}
374fn default_true() -> bool {
375 true
376}
377fn default_acme_directory() -> String {
378 "https://acme-v02.api.letsencrypt.org/directory".into()
379}
380fn default_cert_dir() -> String {
381 "./certs".into()
382}
383fn default_rate_limit_requests() -> u32 {
384 1000
385}
386fn default_rate_limit_window() -> u32 {
387 60
388}
389fn default_burst() -> u32 {
390 50
391}
392fn default_priority() -> i32 {
393 100
394}
395fn default_timeout() -> u32 {
396 30
397}
398fn default_scheme() -> String {
399 "http".into()
400}
401fn default_weight() -> u32 {
402 100
403}
404fn default_health_path() -> String {
405 "/health".into()
406}
407fn default_health_interval() -> u32 {
408 10
409}
410fn default_health_timeout() -> u32 {
411 5
412}
413fn default_healthy_threshold() -> u32 {
414 2
415}
416fn default_unhealthy_threshold() -> u32 {
417 3
418}
419
420#[derive(Clone, Debug, Serialize, Deserialize, Default)]
422pub struct AcmeConfig {
423 #[serde(default)]
425 pub enabled: bool,
426
427 pub email: Option<String>,
429
430 #[serde(default)]
432 pub staging: bool,
433
434 #[serde(default)]
436 pub domains: Vec<String>,
437}