1use std::net::SocketAddr;
2use std::path::PathBuf;
3use std::time::Duration;
4
5use ipnet::IpNet;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
30#[serde(default)]
31pub struct HttpConfig {
32 pub listen: SocketAddr,
34 #[serde(with = "humantime_serde")]
36 pub read_timeout: Duration,
37 #[serde(with = "humantime_serde")]
39 pub write_timeout: Duration,
40 #[serde(with = "human_bytes")]
43 pub max_request_size: usize,
44 pub access_log: bool,
46 #[serde(default)]
50 pub trusted_proxies: Vec<IpNet>,
51 #[serde(default)]
54 pub tls: Option<TlsConfig>,
55 #[serde(default)]
57 pub h2c: bool,
58 #[serde(default)]
60 pub compression: CompressionConfig,
61 #[serde(default)]
63 pub hooks: Vec<HookConfig>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct TlsConfig {
69 pub cert: PathBuf,
71 pub key: PathBuf,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77#[serde(default)]
78pub struct CompressionConfig {
79 pub enabled: bool,
81 pub algorithms: Vec<CompressionAlgorithm>,
84 #[serde(with = "human_bytes")]
86 pub min_size: usize,
87}
88
89impl Default for CompressionConfig {
90 fn default() -> Self {
91 Self {
92 enabled: false,
93 algorithms: vec![
94 CompressionAlgorithm::Gzip,
95 CompressionAlgorithm::Br,
96 CompressionAlgorithm::Zstd,
97 ],
98 min_size: 256,
99 }
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
104#[serde(rename_all = "lowercase")]
105pub enum CompressionAlgorithm {
106 Gzip,
107 Br,
108 Zstd,
109 Deflate,
110}
111
112impl Default for HttpConfig {
113 fn default() -> Self {
114 Self {
115 listen: "0.0.0.0:8080".parse().unwrap(),
116 read_timeout: Duration::from_secs(10),
117 write_timeout: Duration::from_secs(30),
118 max_request_size: 10 * 1024 * 1024, access_log: false,
120 trusted_proxies: Vec::new(),
121 tls: None,
122 h2c: false,
123 compression: CompressionConfig::default(),
124 hooks: Vec::new(),
125 }
126 }
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(rename_all = "snake_case")]
135pub enum HookMode {
136 Sync,
137 Async,
138}
139
140#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
142#[serde(rename_all = "snake_case")]
143pub enum HookErrorBehavior {
144 #[default]
146 FailOpen,
147 FailClosed,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct HookConfig {
154 pub event: String,
157 pub lua: PathBuf,
159 #[serde(default = "default_hook_mode")]
161 pub mode: HookMode,
162 #[serde(default = "default_timeout_ms")]
164 pub timeout_ms: u64,
165 #[serde(default)]
167 pub on_error: HookErrorBehavior,
168 #[serde(default)]
172 pub required: bool,
173}
174
175fn default_hook_mode() -> HookMode {
176 HookMode::Sync
177}
178
179fn default_timeout_ms() -> u64 {
180 5
181}
182
183pub fn parse_byte_size(s: &str) -> Result<usize, String> {
188 let s = s.trim().to_lowercase();
189
190 if let Ok(n) = s.parse::<usize>() {
192 return Ok(n);
193 }
194
195 let (num_part, multiplier) = if let Some(n) = s.strip_suffix("gib") {
196 (n, 1024 * 1024 * 1024)
197 } else if let Some(n) = s.strip_suffix("gb") {
198 (n, 1024 * 1024 * 1024)
199 } else if let Some(n) = s.strip_suffix("mib") {
200 (n, 1024 * 1024)
201 } else if let Some(n) = s.strip_suffix("mb") {
202 (n, 1024 * 1024)
203 } else if let Some(n) = s.strip_suffix("kib") {
204 (n, 1024)
205 } else if let Some(n) = s.strip_suffix("kb") {
206 (n, 1024)
207 } else if let Some(n) = s.strip_suffix("b") {
208 (n, 1)
209 } else {
210 return Err(format!("invalid byte size: {s:?}"));
211 };
212
213 let num: usize = num_part
214 .trim()
215 .parse()
216 .map_err(|_| format!("invalid byte size number: {num_part:?}"))?;
217
218 Ok(num * multiplier)
219}
220
221mod human_bytes {
222 use serde::{Deserialize, Deserializer, Serializer, de};
223
224 pub fn serialize<S: Serializer>(value: &usize, ser: S) -> Result<S::Ok, S::Error> {
225 ser.serialize_u64(*value as u64)
226 }
227
228 pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<usize, D::Error> {
229 #[derive(Deserialize)]
230 #[serde(untagged)]
231 enum ByteSize {
232 Str(String),
233 Num(usize),
234 }
235
236 match ByteSize::deserialize(de)? {
237 ByteSize::Num(n) => Ok(n),
238 ByteSize::Str(s) => super::parse_byte_size(&s).map_err(de::Error::custom),
239 }
240 }
241}