1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::path::PathBuf;
9use validator::Validate;
10
11use sentinel_common::types::{HealthCheckType, LoadBalancingAlgorithm};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
19#[serde(rename_all = "lowercase")]
20pub enum SameSitePolicy {
21 #[default]
23 Lax,
24 Strict,
26 None,
28}
29
30impl std::fmt::Display for SameSitePolicy {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 match self {
33 SameSitePolicy::Lax => write!(f, "Lax"),
34 SameSitePolicy::Strict => write!(f, "Strict"),
35 SameSitePolicy::None => write!(f, "None"),
36 }
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct StickySessionConfig {
46 pub cookie_name: String,
48
49 pub cookie_ttl_secs: u64,
51
52 #[serde(default = "default_cookie_path")]
54 pub cookie_path: String,
55
56 #[serde(default = "default_cookie_secure")]
58 pub cookie_secure: bool,
59
60 #[serde(default)]
62 pub cookie_same_site: SameSitePolicy,
63
64 #[serde(default = "default_sticky_fallback")]
66 pub fallback: LoadBalancingAlgorithm,
67}
68
69fn default_cookie_path() -> String {
70 "/".to_string()
71}
72
73fn default_cookie_secure() -> bool {
74 true
75}
76
77fn default_sticky_fallback() -> LoadBalancingAlgorithm {
78 LoadBalancingAlgorithm::RoundRobin
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
87pub struct UpstreamConfig {
88 pub id: String,
90
91 #[validate(length(min = 1, message = "At least one target is required"))]
93 pub targets: Vec<UpstreamTarget>,
94
95 #[serde(default = "default_lb_algorithm")]
97 pub load_balancing: LoadBalancingAlgorithm,
98
99 pub sticky_session: Option<StickySessionConfig>,
101
102 pub health_check: Option<HealthCheck>,
104
105 #[serde(default)]
107 pub connection_pool: ConnectionPoolConfig,
108
109 #[serde(default)]
111 pub timeouts: UpstreamTimeouts,
112
113 pub tls: Option<UpstreamTlsConfig>,
115
116 #[serde(default)]
118 pub http_version: HttpVersionConfig,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct HttpVersionConfig {
124 #[serde(default = "default_min_http_version")]
126 pub min_version: u8,
127
128 #[serde(default = "default_max_http_version")]
130 pub max_version: u8,
131
132 #[serde(default)]
134 pub h2_ping_interval_secs: u64,
135
136 #[serde(default = "default_max_h2_streams")]
138 pub max_h2_streams: usize,
139}
140
141impl Default for HttpVersionConfig {
142 fn default() -> Self {
143 Self {
144 min_version: default_min_http_version(),
145 max_version: default_max_http_version(),
146 h2_ping_interval_secs: 0,
147 max_h2_streams: default_max_h2_streams(),
148 }
149 }
150}
151
152fn default_min_http_version() -> u8 {
153 1
154}
155
156fn default_max_http_version() -> u8 {
157 2 }
159
160fn default_max_h2_streams() -> usize {
161 100
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
166pub struct UpstreamTarget {
167 pub address: String,
169
170 #[serde(default = "default_weight")]
172 pub weight: u32,
173
174 pub max_requests: Option<u32>,
176
177 #[serde(default)]
179 pub metadata: HashMap<String, String>,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct HealthCheck {
189 #[serde(rename = "type")]
191 pub check_type: HealthCheckType,
192
193 #[serde(default = "default_health_check_interval")]
195 pub interval_secs: u64,
196
197 #[serde(default = "default_health_check_timeout")]
199 pub timeout_secs: u64,
200
201 #[serde(default = "default_healthy_threshold")]
203 pub healthy_threshold: u32,
204
205 #[serde(default = "default_unhealthy_threshold")]
207 pub unhealthy_threshold: u32,
208}
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct ConnectionPoolConfig {
217 #[serde(default = "default_max_connections_per_target")]
219 pub max_connections: usize,
220
221 #[serde(default = "default_max_idle_connections")]
223 pub max_idle: usize,
224
225 #[serde(default = "default_idle_timeout")]
227 pub idle_timeout_secs: u64,
228
229 pub max_lifetime_secs: Option<u64>,
231}
232
233impl Default for ConnectionPoolConfig {
234 fn default() -> Self {
235 Self {
236 max_connections: default_max_connections_per_target(),
237 max_idle: default_max_idle_connections(),
238 idle_timeout_secs: default_idle_timeout(),
239 max_lifetime_secs: None,
240 }
241 }
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct UpstreamTimeouts {
251 #[serde(default = "default_connect_timeout")]
253 pub connect_secs: u64,
254
255 #[serde(default = "default_upstream_request_timeout")]
257 pub request_secs: u64,
258
259 #[serde(default = "default_read_timeout")]
261 pub read_secs: u64,
262
263 #[serde(default = "default_write_timeout")]
265 pub write_secs: u64,
266}
267
268impl Default for UpstreamTimeouts {
269 fn default() -> Self {
270 Self {
271 connect_secs: default_connect_timeout(),
272 request_secs: default_upstream_request_timeout(),
273 read_secs: default_read_timeout(),
274 write_secs: default_write_timeout(),
275 }
276 }
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct UpstreamTlsConfig {
286 pub sni: Option<String>,
288
289 #[serde(default)]
291 pub insecure_skip_verify: bool,
292
293 pub client_cert: Option<PathBuf>,
295
296 pub client_key: Option<PathBuf>,
298
299 pub ca_cert: Option<PathBuf>,
301}
302
303#[derive(Debug, Clone)]
309pub struct UpstreamPeer {
310 pub address: String,
311 pub tls: bool,
312 pub host: String,
313 pub connect_timeout_secs: u64,
314 pub read_timeout_secs: u64,
315 pub write_timeout_secs: u64,
316}
317
318fn default_lb_algorithm() -> LoadBalancingAlgorithm {
323 LoadBalancingAlgorithm::RoundRobin
324}
325
326fn default_weight() -> u32 {
327 1
328}
329
330fn default_health_check_interval() -> u64 {
331 10
332}
333
334fn default_health_check_timeout() -> u64 {
335 5
336}
337
338fn default_healthy_threshold() -> u32 {
339 2
340}
341
342fn default_unhealthy_threshold() -> u32 {
343 3
344}
345
346fn default_max_connections_per_target() -> usize {
347 100
348}
349
350fn default_max_idle_connections() -> usize {
351 20
352}
353
354fn default_idle_timeout() -> u64 {
355 60
356}
357
358pub(crate) fn default_connect_timeout() -> u64 {
359 10
360}
361
362fn default_upstream_request_timeout() -> u64 {
363 60
364}
365
366pub(crate) fn default_read_timeout() -> u64 {
367 30
368}
369
370pub(crate) fn default_write_timeout() -> u64 {
371 30
372}