import logging from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.core.config import settings from app.core.database import init_db from app.core.logging_config import setup_logging from app.core.middleware import RequestLoggingMiddleware, ErrorLoggingMiddleware from app.api.router import api_router # Initialize logging configuration setup_logging() logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan handler.""" # Startup logger.info("Starting Patherly API server...") logger.info(f"Environment: {'Development' if settings.DEBUG else 'Production'}") logger.info(f"ALLOW_RAILWAY_ORIGINS: {settings.ALLOW_RAILWAY_ORIGINS}") # Note: In production, use Alembic migrations instead of init_db # await init_db() yield # Shutdown logger.info("Shutting down Patherly API server...") app = FastAPI( title=settings.APP_NAME, description="Patherly - Take the path MOST traveled. Guided troubleshooting with automatic documentation.", version="1.0.0", docs_url="/api/docs", redoc_url="/api/redoc", openapi_url="/api/openapi.json", lifespan=lifespan ) # Add logging middleware (BEFORE CORS to log all requests) app.add_middleware(ErrorLoggingMiddleware) app.add_middleware(RequestLoggingMiddleware) # Configure CORS # Note: When ALLOW_RAILWAY_ORIGINS is True, we use allow_origin_regex for Railway domains # PLUS the explicit allowed_origins list (for custom domains like app.patherly.com) if settings.ALLOW_RAILWAY_ORIGINS: app.add_middleware( CORSMiddleware, allow_origins=settings.allowed_origins, allow_origin_regex=r"https://.*\.up\.railway\.app", allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) else: app.add_middleware( CORSMiddleware, allow_origins=settings.allowed_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include API router app.include_router(api_router, prefix=settings.API_V1_PREFIX) @app.get("/") async def root(): """Root endpoint.""" return { "message": "Patherly API", "docs": "/api/docs", "version": "1.0.0" } @app.get("/health") async def health_check(): """Health check endpoint.""" return {"status": "healthy"} @app.get("/debug/cors") async def debug_cors(): """Debug endpoint to check CORS configuration.""" return { "allow_railway_origins": settings.ALLOW_RAILWAY_ORIGINS, "cors_mode": "regex + list" if settings.ALLOW_RAILWAY_ORIGINS else "list", "allowed_origins": settings.allowed_origins, "railway_regex": r"https://.*\.up\.railway\.app" if settings.ALLOW_RAILWAY_ORIGINS else None }