feat(settings): add CorsSettings struct for CORS configuration
Implements CorsSettings struct with validation and deserialization support for configuring Cross-Origin Resource Sharing in the application settings. Ref: T010 (specs/001-modbus-relay-control)
This commit is contained in:
@@ -24,6 +24,7 @@ poem = { version = "3.1.12", default-features = false, features = ["csrf", "rust
|
||||
poem-openapi = { version = "5.1.16", features = ["chrono", "swagger-ui"] }
|
||||
serde = "1.0.228"
|
||||
serde_json = "1.0.148"
|
||||
serde_yaml = "0.9.34"
|
||||
sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite", "derive", "migrate"] }
|
||||
thiserror = "2.0.17"
|
||||
tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread"] }
|
||||
|
||||
@@ -25,6 +25,9 @@ pub struct Settings {
|
||||
pub modbus: ModbusSettings,
|
||||
/// Relay configuration
|
||||
pub relay: RelaySettings,
|
||||
/// CORS configuration
|
||||
#[serde(default)]
|
||||
pub cors: CorsSettings,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
@@ -211,6 +214,54 @@ impl Default for RelaySettings {
|
||||
}
|
||||
}
|
||||
|
||||
/// Default value for CORS max age in seconds (1 hour).
|
||||
const fn default_max_age_secs() -> i32 {
|
||||
3600
|
||||
}
|
||||
|
||||
/// CORS (Cross-Origin Resource Sharing) configuration for the HTTP API.
|
||||
///
|
||||
/// Controls which origins can access the API from browsers. In development,
|
||||
/// use permissive settings (`allowed_origins: ["*"]`). In production, use
|
||||
/// restrictive settings with specific origins.
|
||||
///
|
||||
/// # Security Constraint
|
||||
///
|
||||
/// When `allow_credentials` is `true`, `allowed_origins` MUST NOT contain
|
||||
/// wildcard `"*"`. This is enforced by browser security policy and will be
|
||||
/// validated by the `build_cors()` function.
|
||||
#[derive(Debug, serde::Deserialize, Clone)]
|
||||
pub struct CorsSettings {
|
||||
/// List of allowed origin URLs (e.g., `["https://sta.example.com"]`).
|
||||
///
|
||||
/// Use `["*"]` for development to allow all origins.
|
||||
/// In production, specify exact origins to prevent unauthorized access.
|
||||
#[serde(default)]
|
||||
pub allowed_origins: Vec<String>,
|
||||
/// Whether to allow credentials (cookies, authorization headers) in CORS requests.
|
||||
///
|
||||
/// Set to `true` in production when using Authelia authentication.
|
||||
/// MUST be `false` when using wildcard `"*"` in `allowed_origins`.
|
||||
#[serde(default)]
|
||||
pub allow_credentials: bool,
|
||||
/// Duration in seconds that browsers can cache CORS preflight responses.
|
||||
///
|
||||
/// Typical value: `3600` (1 hour). Higher values reduce preflight requests
|
||||
/// but delay policy changes from taking effect.
|
||||
#[serde(default = "default_max_age_secs")]
|
||||
pub max_age_secs: i32,
|
||||
}
|
||||
|
||||
impl Default for CorsSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
allowed_origins: vec![],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 3600,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -181,8 +181,7 @@ mod tests {
|
||||
burst_size: 100,
|
||||
per_seconds: 60,
|
||||
},
|
||||
modbus: crate::settings::ModbusSettings::default(),
|
||||
relay: crate::settings::RelaySettings::default(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user