""" API Gateway - Central entry point for all microservices Handles routing, authentication, rate limiting, and cross-cutting concerns """ import asyncio import logging from fastapi import FastAPI, Request, HTTPException, Depends from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse import httpx import time from typing import Dict, Any from app.core.config import settings from app.core.service_discovery import ServiceDiscovery from app.middleware.auth import auth_middleware from app.middleware.logging import logging_middleware from app.middleware.rate_limit import rate_limit_middleware from app.routes import auth, training, forecasting, data, tenant, notification from shared.monitoring.logging import setup_logging from shared.monitoring.metrics import MetricsCollector # Setup logging setup_logging("gateway", settings.LOG_LEVEL) logger = logging.getLogger(__name__) # Create FastAPI app app = FastAPI( title="Bakery Forecasting API Gateway", description="Central API Gateway for bakery forecasting microservices", version="1.0.0", docs_url="/docs", redoc_url="/redoc" ) # Initialize metrics collector metrics_collector = MetricsCollector("gateway") # Service discovery service_discovery = ServiceDiscovery() # CORS middleware - FIXED: Use the parsed list property app.add_middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS_LIST, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Custom middleware app.add_middleware(auth_middleware) app.add_middleware(logging_middleware) app.add_middleware(rate_limit_middleware) # Include routers app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) app.include_router(training.router, prefix="/api/v1/training", tags=["training"]) app.include_router(forecasting.router, prefix="/api/v1/forecasting", tags=["forecasting"]) app.include_router(data.router, prefix="/api/v1/data", tags=["data"]) app.include_router(tenant.router, prefix="/api/v1/tenants", tags=["tenants"]) app.include_router(notification.router, prefix="/api/v1/notifications", tags=["notifications"]) @app.on_event("startup") async def startup_event(): """Application startup""" logger.info("Starting API Gateway") # Start metrics server metrics_collector.start_metrics_server(8080) # Initialize service discovery await service_discovery.initialize() logger.info("API Gateway started successfully") @app.on_event("shutdown") async def shutdown_event(): """Application shutdown""" logger.info("Shutting down API Gateway") # Clean up service discovery await service_discovery.cleanup() logger.info("API Gateway shutdown complete") @app.get("/health") async def health_check(): """Health check endpoint""" healthy_services = await service_discovery.get_healthy_services() return { "status": "healthy", "service": "gateway", "version": "1.0.0", "healthy_services": healthy_services, "total_services": len(settings.SERVICES), "timestamp": time.time() } @app.get("/metrics") async def get_metrics(): """Get basic metrics""" return { "service": "gateway", "uptime": time.time() - app.state.start_time if hasattr(app.state, 'start_time') else 0, "healthy_services": await service_discovery.get_healthy_services() } @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): """Handle HTTP exceptions""" logger.error(f"HTTP {exc.status_code}: {exc.detail}") return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail, "service": "gateway"} ) @app.exception_handler(Exception) async def general_exception_handler(request: Request, exc: Exception): """Handle general exceptions""" logger.error(f"Unhandled exception: {exc}", exc_info=True) return JSONResponse( status_code=500, content={"detail": "Internal server error", "service": "gateway"} ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)