use std::net::IpAddr; use config::{Config, ConfigError}; use tracing::warn; use crate::configs::key::{SERVER_CORS_ALLOWED_ORIGINS_KEY, SERVER_SERVE_OPENAPI_KEY}; use super::{ FromConfig, key::{SERVER_ADDRESS_KEY, SERVER_PORT_KEY}, }; #[derive(Debug, Clone)] pub struct ServerSettings { pub address: IpAddr, pub port: u16, pub serve_openapi: bool, pub cors: CORSSettings, } #[derive(Debug, Clone)] pub struct CORSSettings { pub allowed_origins: Vec, } impl FromConfig for ServerSettings { fn from_config(_config: &Config) -> Result { Ok(ServerSettings { address: _config .get_string(SERVER_ADDRESS_KEY) .unwrap_or_else(|err| { const DEFAULT_ADDRESS: &str = "0.0.0.0"; match err { ConfigError::NotFound(_) => {} _ => { warn!( "Failed to read {} from configuration, defaulting to {}. Error: {}", SERVER_ADDRESS_KEY, DEFAULT_ADDRESS, err ); } }; DEFAULT_ADDRESS.to_string() }) .parse() .map_err(|e| format!("Invalid {} in configuration: {}", SERVER_ADDRESS_KEY, e))?, port: _config.get_int(SERVER_PORT_KEY).unwrap_or_else(|err| { const DEFAULT_PORT: i64 = 8080; warn!( "{} not set or invalid in configuration, defaulting to {}. Error: {}", SERVER_PORT_KEY, DEFAULT_PORT, err ); DEFAULT_PORT }) as u16, serve_openapi: _config .get_bool(SERVER_SERVE_OPENAPI_KEY) .unwrap_or_else(|err| { const DEFAULT_SERVE_OPENAPI: bool = false; warn!( "{} not set or invalid in configuration, defaulting to {}. Error: {}", SERVER_SERVE_OPENAPI_KEY, DEFAULT_SERVE_OPENAPI, err ); DEFAULT_SERVE_OPENAPI }), cors: CORSSettings { allowed_origins: _config .get_array(SERVER_CORS_ALLOWED_ORIGINS_KEY) .unwrap_or_else(|_| vec![]) .into_iter() .filter_map(|val| match val.into_string() { Ok(s) => Some(s), Err(e) => { warn!( "Invalid origin in {} configuration: {}", SERVER_CORS_ALLOWED_ORIGINS_KEY, e ); None } }) .collect(), }, }) } fn validate(&self) -> Result<(), String> { #[allow(clippy::absurd_extreme_comparisons, unused_comparisons)] if self.port == 0 || self.port > 65535 { return Err("Server port must be between 1 and 65535".into()); } Ok(()) } }