1#[cfg(feature = "config")]
4use std::path::Path;
5use std::time::Duration;
6
7#[cfg(feature = "config")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone)]
12#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
13pub struct TorchConfig {
14 pub server: ServerConfig,
16 pub security: SecurityConfig,
18 pub monitoring: MonitoringConfig,
20 pub performance: PerformanceConfig,
22 pub rate_limiting: RateLimitingConfig,
24 pub database: Option<DatabaseConfig>,
26 #[cfg_attr(feature = "config", serde(default))]
28 pub custom: std::collections::HashMap<String, String>,
29}
30
31#[derive(Debug, Clone)]
33#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
34pub struct ServerConfig {
35 pub host: String,
37 pub port: u16,
39 pub max_connections: usize,
41 pub request_timeout_secs: u64,
43 pub keep_alive_timeout_secs: u64,
45 pub max_body_size: usize,
47 pub worker_threads: Option<usize>,
49 pub enable_http2: bool,
51 pub enable_tls: bool,
53 pub tls_cert_path: Option<String>,
55 pub tls_key_path: Option<String>,
57 pub graceful_shutdown_timeout_secs: u64,
59}
60
61#[derive(Debug, Clone)]
63#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
64pub struct SecurityConfig {
65 pub enable_cors: bool,
67 pub cors_allowed_origins: Vec<String>,
69 pub cors_allowed_methods: Vec<String>,
71 pub cors_allowed_headers: Vec<String>,
73 pub enable_security_headers: bool,
75 pub content_security_policy: Option<String>,
77 pub enable_request_signing: bool,
79 pub signing_secret: Option<String>,
81 pub enable_ip_whitelist: bool,
83 pub ip_whitelist: Vec<String>,
85 pub enable_request_id: bool,
87 pub max_request_size: usize,
89 pub enable_input_validation: bool,
91 pub enable_sql_injection_protection: bool,
93 pub enable_xss_protection: bool,
95}
96
97#[derive(Debug, Clone)]
99#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
100pub struct MonitoringConfig {
101 pub enable_request_logging: bool,
103 pub log_level: String,
105 pub log_format: String,
107 pub log_file: Option<String>,
109 pub enable_metrics: bool,
111 pub metrics_endpoint: String,
113 pub enable_health_check: bool,
115 pub health_check_endpoint: String,
117 pub enable_performance_monitoring: bool,
119 pub slow_request_threshold_ms: u64,
121 pub enable_error_tracking: bool,
123 pub error_tracking_url: Option<String>,
125 pub enable_distributed_tracing: bool,
127 pub tracing_endpoint: Option<String>,
129}
130
131#[derive(Debug, Clone)]
133#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
134pub struct PerformanceConfig {
135 pub enable_compression: bool,
137 pub compression_level: u8,
139 pub enable_caching: bool,
141 pub cache_ttl_secs: u64,
143 pub max_cache_size_mb: usize,
145 pub enable_connection_pooling: bool,
147 pub connection_pool_size: usize,
149 pub connection_pool_timeout_secs: u64,
151 pub enable_keep_alive: bool,
153 pub keep_alive_timeout_secs: u64,
155}
156
157#[derive(Debug, Clone)]
159#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
160pub struct RateLimitingConfig {
161 pub enable_rate_limiting: bool,
163 pub global_rps_limit: Option<u32>,
165 pub per_ip_rps_limit: Option<u32>,
167 pub per_user_rps_limit: Option<u32>,
169 pub window_secs: u64,
171 pub enable_burst: bool,
173 pub burst_size: u32,
175 pub storage_backend: String,
177 pub redis_url: Option<String>,
179}
180
181#[derive(Debug, Clone)]
183#[cfg_attr(feature = "config", derive(Serialize, Deserialize))]
184pub struct DatabaseConfig {
185 pub url: String,
187 pub max_connections: u32,
189 pub min_connections: u32,
191 pub connect_timeout_secs: u64,
193 pub query_timeout_secs: u64,
195 pub enable_pooling: bool,
197 pub enable_query_logging: bool,
199 pub enable_migrations: bool,
201 pub migrations_dir: Option<String>,
203}
204
205impl Default for TorchConfig {
206 fn default() -> Self {
207 Self {
208 server: ServerConfig::default(),
209 security: SecurityConfig::default(),
210 monitoring: MonitoringConfig::default(),
211 performance: PerformanceConfig::default(),
212 rate_limiting: RateLimitingConfig::default(),
213 database: None,
214 custom: std::collections::HashMap::new(),
215 }
216 }
217}
218
219impl Default for ServerConfig {
220 fn default() -> Self {
221 Self {
222 host: "127.0.0.1".to_string(),
223 port: 3000,
224 max_connections: 10_000,
225 request_timeout_secs: 30,
226 keep_alive_timeout_secs: 60,
227 max_body_size: 16 * 1024 * 1024, worker_threads: None,
229 enable_http2: true,
230 enable_tls: false,
231 tls_cert_path: None,
232 tls_key_path: None,
233 graceful_shutdown_timeout_secs: 30,
234 }
235 }
236}
237
238impl Default for SecurityConfig {
239 fn default() -> Self {
240 Self {
241 enable_cors: true,
242 cors_allowed_origins: vec!["*".to_string()],
243 cors_allowed_methods: vec![
244 "GET".to_string(),
245 "POST".to_string(),
246 "PUT".to_string(),
247 "DELETE".to_string(),
248 "OPTIONS".to_string(),
249 ],
250 cors_allowed_headers: vec![
251 "Content-Type".to_string(),
252 "Authorization".to_string(),
253 "X-Requested-With".to_string(),
254 ],
255 enable_security_headers: true,
256 content_security_policy: Some(
257 "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
258 .to_string(),
259 ),
260 enable_request_signing: false,
261 signing_secret: None,
262 enable_ip_whitelist: false,
263 ip_whitelist: Vec::new(),
264 enable_request_id: true,
265 max_request_size: 16 * 1024 * 1024, enable_input_validation: true,
267 enable_sql_injection_protection: true,
268 enable_xss_protection: true,
269 }
270 }
271}
272
273impl Default for MonitoringConfig {
274 fn default() -> Self {
275 Self {
276 enable_request_logging: true,
277 log_level: "info".to_string(),
278 log_format: "json".to_string(),
279 log_file: None,
280 enable_metrics: true,
281 metrics_endpoint: "/metrics".to_string(),
282 enable_health_check: true,
283 health_check_endpoint: "/health".to_string(),
284 enable_performance_monitoring: true,
285 slow_request_threshold_ms: 1000,
286 enable_error_tracking: true,
287 error_tracking_url: None,
288 enable_distributed_tracing: false,
289 tracing_endpoint: None,
290 }
291 }
292}
293
294impl Default for PerformanceConfig {
295 fn default() -> Self {
296 Self {
297 enable_compression: true,
298 compression_level: 6,
299 enable_caching: true,
300 cache_ttl_secs: 300, max_cache_size_mb: 100,
302 enable_connection_pooling: true,
303 connection_pool_size: 100,
304 connection_pool_timeout_secs: 30,
305 enable_keep_alive: true,
306 keep_alive_timeout_secs: 60,
307 }
308 }
309}
310
311impl Default for RateLimitingConfig {
312 fn default() -> Self {
313 Self {
314 enable_rate_limiting: true,
315 global_rps_limit: Some(10_000),
316 per_ip_rps_limit: Some(100),
317 per_user_rps_limit: Some(1000),
318 window_secs: 60,
319 enable_burst: true,
320 burst_size: 10,
321 storage_backend: "memory".to_string(),
322 redis_url: None,
323 }
324 }
325}
326
327impl TorchConfig {
328 #[cfg(feature = "config")]
330 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
331 let content = std::fs::read_to_string(path)?;
332 let config: TorchConfig = toml::from_str(&content)?;
333 Ok(config)
334 }
335
336 #[cfg(feature = "config")]
338 pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Box<dyn std::error::Error>> {
339 let content = toml::to_string_pretty(self)?;
340 std::fs::write(path, content)?;
341 Ok(())
342 }
343
344 pub fn from_env() -> Self {
346 let mut config = Self::default();
347
348 if let Ok(host) = std::env::var("TORCH_HOST") {
350 config.server.host = host;
351 }
352 if let Ok(port) = std::env::var("TORCH_PORT") {
353 if let Ok(port) = port.parse() {
354 config.server.port = port;
355 }
356 }
357 if let Ok(max_conn) = std::env::var("TORCH_MAX_CONNECTIONS") {
358 if let Ok(max_conn) = max_conn.parse() {
359 config.server.max_connections = max_conn;
360 }
361 }
362
363 if let Ok(enable_cors) = std::env::var("TORCH_ENABLE_CORS") {
365 config.security.enable_cors = enable_cors.parse().unwrap_or(true);
366 }
367 if let Ok(secret) = std::env::var("TORCH_SIGNING_SECRET") {
368 config.security.signing_secret = Some(secret);
369 config.security.enable_request_signing = true;
370 }
371
372 config
375 }
376
377 pub fn server_address(&self) -> String {
379 format!("{}:{}", self.server.host, self.server.port)
380 }
381
382 pub fn request_timeout(&self) -> Duration {
384 Duration::from_secs(self.server.request_timeout_secs)
385 }
386
387 pub fn keep_alive_timeout(&self) -> Duration {
389 Duration::from_secs(self.server.keep_alive_timeout_secs)
390 }
391
392 pub fn graceful_shutdown_timeout(&self) -> Duration {
394 Duration::from_secs(self.server.graceful_shutdown_timeout_secs)
395 }
396}