diff --git a/server/src/config.rs b/server/src/config.rs new file mode 100644 index 0000000..fb6628a --- /dev/null +++ b/server/src/config.rs @@ -0,0 +1,51 @@ +use std::env; + +/// Server configuration loaded from environment variables with sensible defaults. +#[derive(Debug, Clone)] +pub struct Config { + /// Bind address (default: 0.0.0.0) + pub host: String, + /// Bind port (default: 8080) + pub port: u16, + /// Allowed CORS origins. "*" permits everything (dev mode). + pub cors_origins: Vec, + /// Maximum concurrent sessions (default: 100) + pub max_sessions: usize, + /// Seconds before an idle session is reaped (default: 300) + pub idle_timeout_secs: u64, + /// Max display-frame buffer depth per session (default: 60 ≈ 2 s @ 30 fps) + pub frame_buffer_size: usize, +} + +impl Config { + /// Build configuration from `BUTTERFLY_*` env vars, falling back to defaults. + pub fn from_env() -> Self { + Self { + host: env::var("BUTTERFLY_HOST").unwrap_or_else(|_| "0.0.0.0".into()), + port: env::var("BUTTERFLY_PORT") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(8080), + cors_origins: env::var("BUTTERFLY_CORS_ORIGINS") + .map(|v| v.split(',').map(|s| s.trim().to_string()).collect()) + .unwrap_or_else(|_| vec!["*".into()]), + max_sessions: env::var("BUTTERFLY_MAX_SESSIONS") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(100), + idle_timeout_secs: env::var("BUTTERFLY_IDLE_TIMEOUT") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(300), + frame_buffer_size: env::var("BUTTERFLY_FRAME_BUFFER") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(60), + } + } + + /// Address string suitable for `bind()`, e.g. "0.0.0.0:8080". + pub fn bind_addr(&self) -> String { + format!("{}:{}", self.host, self.port) + } +}