Files
foxhunt/web-gateway/src/config.rs
jgrusewski a132bb6ead test(web-gateway): add 26 unit tests for error, config, auth, websocket
- error.rs: 10 tests for HTTP status code mapping (AppError → StatusCode)
- config.rs: 7 tests for defaults and from_env() fallback behavior
- claims.rs: 3 tests for JWT Claims serde round-trip
- messages.rs: 6 tests for WebSocket message serialization and topic()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:32:40 +01:00

111 lines
3.7 KiB
Rust

use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct GatewayConfig {
/// HTTP listen address (default: 0.0.0.0:3000)
pub listen_addr: String,
/// gRPC trading service endpoint
pub trading_service_url: String,
/// gRPC backtesting service endpoint
pub backtesting_service_url: String,
/// gRPC ML training service endpoint
pub ml_training_service_url: String,
/// CORS allowed origins (comma-separated)
pub cors_origins: Vec<String>,
/// JWT secret for token validation
pub jwt_secret: String,
}
impl Default for GatewayConfig {
fn default() -> Self {
Self {
listen_addr: "0.0.0.0:3000".to_owned(),
trading_service_url: "https://localhost:50051".to_owned(),
backtesting_service_url: "https://localhost:50052".to_owned(),
ml_training_service_url: "https://localhost:50053".to_owned(),
cors_origins: vec!["http://localhost:5173".to_owned()],
jwt_secret: String::new(),
}
}
}
impl GatewayConfig {
pub fn from_env() -> Self {
Self {
listen_addr: std::env::var("GATEWAY_LISTEN_ADDR")
.unwrap_or_else(|_| "0.0.0.0:3000".to_owned()),
trading_service_url: std::env::var("TRADING_SERVICE_URL")
.unwrap_or_else(|_| "https://localhost:50051".to_owned()),
backtesting_service_url: std::env::var("BACKTESTING_SERVICE_URL")
.unwrap_or_else(|_| "https://localhost:50052".to_owned()),
ml_training_service_url: std::env::var("ML_TRAINING_SERVICE_URL")
.unwrap_or_else(|_| "https://localhost:50053".to_owned()),
cors_origins: std::env::var("CORS_ORIGINS")
.unwrap_or_else(|_| "http://localhost:5173".to_owned())
.split(',')
.map(|s| s.trim().to_owned())
.collect(),
jwt_secret: std::env::var("JWT_SECRET").unwrap_or_default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_listen_addr() {
let cfg = GatewayConfig::default();
assert_eq!(cfg.listen_addr, "0.0.0.0:3000");
}
#[test]
fn test_default_trading_service_url() {
let cfg = GatewayConfig::default();
assert_eq!(cfg.trading_service_url, "https://localhost:50051");
}
#[test]
fn test_default_backtesting_service_url() {
let cfg = GatewayConfig::default();
assert_eq!(cfg.backtesting_service_url, "https://localhost:50052");
}
#[test]
fn test_default_ml_training_service_url() {
let cfg = GatewayConfig::default();
assert_eq!(cfg.ml_training_service_url, "https://localhost:50053");
}
#[test]
fn test_default_cors_origins() {
let cfg = GatewayConfig::default();
assert_eq!(cfg.cors_origins, vec!["http://localhost:5173"]);
}
#[test]
fn test_default_jwt_secret_is_empty() {
let cfg = GatewayConfig::default();
assert!(cfg.jwt_secret.is_empty());
}
#[test]
fn test_from_env_falls_back_to_defaults() {
// When env vars are not set, from_env() should match default()
let from_env = GatewayConfig::from_env();
let default = GatewayConfig::default();
assert_eq!(from_env.listen_addr, default.listen_addr);
assert_eq!(from_env.trading_service_url, default.trading_service_url);
assert_eq!(
from_env.backtesting_service_url,
default.backtesting_service_url
);
assert_eq!(
from_env.ml_training_service_url,
default.ml_training_service_url
);
assert_eq!(from_env.cors_origins, default.cors_origins);
}
}