use std::time::Duration; pub const MIN_HEARTBEAT_INTERVAL: Duration = Duration::from_secs(30); pub const MAX_HEARTBEAT_GAP: Duration = Duration::from_secs(60); pub const DEFAULT_HEARTBEAT_TIMEOUT: Duration = Duration::from_secs(30); pub const DEFAULT_AUTH_TIMEOUT: Duration = Duration::from_secs(5); pub const DEFAULT_MAX_PAYLOAD: usize = 1_000_000; /// 浏览器握手带不了 `Authorization`,所以允许从会话 cookie 取同一个 access token。 pub const DEFAULT_SESSION_COOKIE: &str = "gitdata_session"; #[derive(Debug, Clone)] pub struct SocketOptions { pub heartbeat_interval: Duration, pub heartbeat_timeout: Duration, pub auth_timeout: Duration, pub max_payload: usize, /// 承载 KenApi 会话键的 cookie 名(与平台 `session.cookie_name` 一致)。 pub session_cookie: String, } impl Default for SocketOptions { fn default() -> Self { Self { heartbeat_interval: MIN_HEARTBEAT_INTERVAL, heartbeat_timeout: DEFAULT_HEARTBEAT_TIMEOUT, auth_timeout: DEFAULT_AUTH_TIMEOUT, max_payload: DEFAULT_MAX_PAYLOAD, session_cookie: DEFAULT_SESSION_COOKIE.to_string(), } } } impl SocketOptions { pub fn validate(&self) -> Result<(), String> { if self.heartbeat_interval < MIN_HEARTBEAT_INTERVAL { return Err("socket.heartbeat_interval must be at least 30 seconds".to_string()); } if self.heartbeat_timeout.is_zero() { return Err("socket.heartbeat_timeout must be greater than zero".to_string()); } let gap = self .heartbeat_interval .checked_add(self.heartbeat_timeout) .ok_or_else(|| "socket heartbeat durations overflow".to_string())?; if gap > MAX_HEARTBEAT_GAP { return Err( "socket heartbeat interval and timeout must not exceed 60 seconds".to_string(), ); } if self.auth_timeout.is_zero() { return Err("socket.auth_timeout must be greater than zero".to_string()); } if self.max_payload == 0 { return Err("socket.max_payload must be greater than zero".to_string()); } if self.session_cookie.trim().is_empty() { return Err("socket.session_cookie must not be blank".to_string()); } Ok(()) } } impl From<&config::event::socket::SocketConfig> for SocketOptions { fn from(config: &config::event::socket::SocketConfig) -> Self { Self { heartbeat_interval: config.heartbeat_interval(), heartbeat_timeout: config.heartbeat_timeout(), auth_timeout: config.auth_timeout(), max_payload: config.max_payload, session_cookie: config.session_cookie.clone(), } } }