config.rs (2828B)
1 use anyhow::Result; 2 use serde::Deserialize; 3 use std::path::Path; 4 5 /// Application configuration loaded from config.toml 6 #[derive(Debug, Clone, Deserialize)] 7 pub struct Config { 8 pub server: ServerConfig, 9 pub database: DatabaseConfig, 10 pub services: ServicesConfig, 11 pub http_client: HttpClientConfig, 12 pub session: SessionConfig, 13 } 14 15 /// Server configuration 16 #[derive(Debug, Clone, Deserialize)] 17 pub struct ServerConfig { 18 pub port: u16, 19 pub static_dir: String, 20 } 21 22 /// Database configuration 23 #[derive(Debug, Clone, Deserialize)] 24 pub struct DatabaseConfig { 25 pub url: String, 26 pub max_connections: u32, 27 } 28 29 /// Microservices configuration 30 #[derive(Debug, Clone, Deserialize)] 31 pub struct ServicesConfig { 32 pub products_host: String, 33 pub products_port: u16, 34 pub inventory_host: String, 35 pub inventory_port: u16, 36 pub orders_host: String, 37 pub orders_port: u16, 38 pub checkout_host: String, 39 pub checkout_port: u16, 40 pub inventory_service_url: String, 41 pub orders_service_url: String, 42 } 43 44 impl ServicesConfig { 45 /// Get the full products service URL 46 pub fn products_service_url(&self) -> String { 47 format!("http://{}:{}", self.products_host, self.products_port) 48 } 49 50 /// Get the full inventory service URL 51 pub fn inventory_service_url_computed(&self) -> String { 52 format!("http://{}:{}", self.inventory_host, self.inventory_port) 53 } 54 55 /// Get the full orders service URL 56 pub fn orders_service_url_computed(&self) -> String { 57 format!("http://{}:{}", self.orders_host, self.orders_port) 58 } 59 60 /// Get the full checkout service URL 61 pub fn checkout_service_url(&self) -> String { 62 format!("http://{}:{}", self.checkout_host, self.checkout_port) 63 } 64 } 65 66 /// HTTP client configuration 67 #[derive(Debug, Clone, Deserialize)] 68 pub struct HttpClientConfig { 69 pub timeout_secs: u64, 70 } 71 72 /// Session configuration 73 #[derive(Debug, Clone, Deserialize)] 74 pub struct SessionConfig { 75 pub expiration_days: i64, 76 } 77 78 impl Config { 79 /// Load configuration from a TOML file with environment variable overrides 80 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> { 81 let config = config::Config::builder() 82 .add_source(config::File::from(path.as_ref())) 83 // Allow environment variables to override config file values 84 // Using __ as separator for nested fields: APP_SERVICES__PRODUCTS_HOST 85 .add_source( 86 config::Environment::with_prefix("APP") 87 .separator("__") 88 .try_parsing(true) 89 ) 90 .build()?; 91 92 Ok(config.try_deserialize()?) 93 } 94 95 /// Load configuration from default location (./config.toml) 96 pub fn load() -> Result<Self> { 97 Self::from_file("config.toml") 98 } 99 }