- 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>
111 lines
3.7 KiB
Rust
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);
|
|
}
|
|
}
|