import logging import os from fastapi.responses import JSONResponse from fastapi import FastAPI, Depends, Request, status from fastapi.exceptions import RequestValidationError from fastapi.encoders import jsonable_encoder from starlette.exceptions import HTTPException as StarletteHTTPException from mangum import Mangum from backend.app.portfolio import router as portfolio_router from backend.app.whlg import router as whlg_router from backend.app.plan import router as plan_router from backend.app.tasks import router as tasks_router from backend.app.bulk_uploads import router as bulk_uploads_router from backend.app.dependencies import validate_api_key from backend.app.config import get_settings logger = logging.getLogger("uvicorn.error") logging.basicConfig(level=logging.INFO) if get_settings().ENVIRONMENT == "local": app = FastAPI() else: app = FastAPI(dependencies=[Depends(validate_api_key)]) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): logger.error(f"422 Validation Error at {request.url}") logger.error(f"Body: {exc.body}") logger.error(f"Validation Errors: {exc.errors()}") return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), ) @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request: Request, exc: StarletteHTTPException): logger.warning(f"{exc.status_code} Error at {request.url} - Detail: {exc.detail}") return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, ) @app.middleware("http") async def log_requests(request: Request, call_next): logger.info(f"Incoming request: {request.method} {request.url}") response = await call_next(request) logger.info(f"Response status: {response.status_code}") return response @app.get("/health") async def health(): return {"status": "ok", "sha": os.getenv("GITHUB_SHA", "unknown")} app.include_router(tasks_router.router, prefix="/v1") app.include_router(portfolio_router.router, prefix="/v1") app.include_router(plan_router.router, prefix="/v1") app.include_router(whlg_router.router, prefix="/v1") app.include_router(bulk_uploads_router.router, prefix="/v1") if get_settings().ENVIRONMENT == "local": from backend.app.local import router as local_router app.include_router(local_router.router) handler = Mangum(app)