diff --git a/web-gateway/src/auth/middleware.rs b/web-gateway/src/auth/middleware.rs index 3239b9fba..20b06fd4c 100644 --- a/web-gateway/src/auth/middleware.rs +++ b/web-gateway/src/auth/middleware.rs @@ -41,7 +41,6 @@ mod tests { use axum::body::Body; use axum::http::{Request as HttpRequest, StatusCode}; use axum::middleware; - use axum::response::IntoResponse; use axum::routing::get; use axum::Router; use jsonwebtoken::{encode, EncodingKey, Header}; diff --git a/web-gateway/src/main.rs b/web-gateway/src/main.rs index f2e203961..ae77b8714 100644 --- a/web-gateway/src/main.rs +++ b/web-gateway/src/main.rs @@ -1,5 +1,6 @@ use anyhow::Result; -use tower_http::cors::{Any, CorsLayer}; +use axum::http::HeaderValue; +use tower_http::cors::CorsLayer; use tower_http::trace::TraceLayer; use tracing::info; @@ -19,16 +20,23 @@ async fn main() -> Result<()> { info!(" Trading service: {}", config.trading_service_url); info!(" Backtesting service: {}", config.backtesting_service_url); info!(" ML Training service: {}", config.ml_training_service_url); + info!(" CORS origins: {:?}", config.cors_origins); - let state = AppState::new(config).await?; + let state = AppState::new(config.clone()).await?; // Start gRPC stream bridge tasks (forward gRPC streams to WebSocket broadcast) start_grpc_stream_bridges(state.trading_channel.clone(), state.ws_broadcast.clone()); + // Build CORS from configured origins + let origins: Vec = config + .cors_origins + .iter() + .filter_map(|o| o.parse().ok()) + .collect(); let cors = CorsLayer::new() - .allow_origin(Any) - .allow_methods(Any) - .allow_headers(Any); + .allow_origin(origins) + .allow_methods(tower_http::cors::Any) + .allow_headers(tower_http::cors::Any); let app = create_router(state) .layer(cors) diff --git a/web-gateway/src/routes/mod.rs b/web-gateway/src/routes/mod.rs index c563f4376..1b3cbd765 100644 --- a/web-gateway/src/routes/mod.rs +++ b/web-gateway/src/routes/mod.rs @@ -1,4 +1,5 @@ -use axum::{middleware, routing, Router}; +use axum::{middleware, routing, Json, Router}; +use serde_json::json; use crate::auth::middleware::auth_middleware; use crate::state::AppState; @@ -36,9 +37,30 @@ pub fn create_router(state: AppState) -> Router { // WebSocket endpoint validates JWT via query param (no middleware layer) let ws_route = Router::new().route("/ws", routing::get(ws_handler)); + // Health/readiness probes (public, no auth) + let health = Router::new() + .route("/health", routing::get(health_check)) + .route("/ready", routing::get(readiness_check)); + Router::new() .nest("/api", rest_api) .nest("/api", public_api) .nest("/api", ws_route) + .merge(health) .with_state(state) } + +async fn health_check() -> Json { + Json(json!({ "status": "ok" })) +} + +async fn readiness_check( + axum::extract::State(state): axum::extract::State, +) -> Json { + Json(json!({ + "status": "ok", + "trading_service": state.trading_channel.is_some(), + "backtesting_service": state.backtesting_channel.is_some(), + "ml_training_service": state.ml_training_channel.is_some(), + })) +}