use serde::{Deserialize, Serialize}; use crate::config::settings::{ Validate, ValidationError, cert::CertificateSettings, cors::CorsSettings, }; /// HTTP server settings #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ServerSettings { #[serde(default = "default_server_bind_address")] pub bind_address: String, #[serde(default = "default_server_port")] pub port: u16, #[serde(default)] pub certificate: CertificateSettings, #[serde(default)] pub cors: Option, } impl Validate for ServerSettings { fn validate(&self) -> Result<(), ValidationError> { if self.bind_address.is_empty() { return Err("Server bind address cannot be empty".into()); } if self.port == 0 { return Err("Server port must be greater than 0".into()); } self.certificate.validate()?; if let Some(cors) = &self.cors { cors.validate()?; } Ok(()) } } fn default_server_bind_address() -> String { "0.0.0.0".into() } fn default_server_port() -> u16 { 8080 } #[cfg(test)] mod tests { use std::{ fs, path::PathBuf, time::{SystemTime, UNIX_EPOCH}, }; use rcgen::string::Ia5String; use super::*; #[test] fn test_esnure_send_and_sync() { fn assert_send_sync() {} assert_send_sync::(); } fn make_temp_dir(prefix: &str) -> PathBuf { let ts = SystemTime::now().duration_since(UNIX_EPOCH); assert!(ts.is_ok()); let ts = ts.unwrap_or_default(); let path = std::env::temp_dir().join(format!( "{}_{}_{}", prefix, std::process::id(), ts.as_nanos() )); let created = fs::create_dir_all(&path); assert!(created.is_ok()); path } #[test] fn server_validate_fails_for_zero_port() { let cert_dir = make_temp_dir("nxmesh-master-server-validate"); let san = Ia5String::try_from("localhost".to_string()); assert!(san.is_ok()); let san = san.unwrap_or_else(|_| unreachable!()); let server = ServerSettings { bind_address: "0.0.0.0".to_string(), port: 0, certificate: CertificateSettings { cert_dir: cert_dir.to_string_lossy().to_string(), san_dns: vec![san], san_ip: Vec::new(), cert_path: None, key_path: None, }, cors: None, }; let result = server.validate(); assert!(result.is_err()); let msg = result.err().unwrap_or_default(); assert!(msg.contains("Server port must be greater than 0")); let _ = fs::remove_dir_all(&cert_dir); } }