diff --git a/backend/app/core/middleware.py b/backend/app/core/middleware.py index be97e452..dcd88ca6 100644 --- a/backend/app/core/middleware.py +++ b/backend/app/core/middleware.py @@ -85,8 +85,21 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware): exc_info=True ) - # Re-raise exception to be handled by FastAPI - raise + # Return a proper response so it flows through CORSMiddleware. + # Re-raising from BaseHTTPMiddleware bypasses CORS headers. + from starlette.responses import JSONResponse + from fastapi import HTTPException + if isinstance(exc, HTTPException): + return JSONResponse( + status_code=exc.status_code, + content={"detail": exc.detail}, + headers={"X-Correlation-ID": correlation_id, "X-Process-Time": f"{process_time:.3f}"}, + ) + return JSONResponse( + status_code=500, + content={"detail": "Internal server error"}, + headers={"X-Correlation-ID": correlation_id, "X-Process-Time": f"{process_time:.3f}"}, + ) class ErrorLoggingMiddleware(BaseHTTPMiddleware): @@ -95,6 +108,11 @@ class ErrorLoggingMiddleware(BaseHTTPMiddleware): Ensures all exceptions are logged before being returned to the client, providing full stack traces for debugging. + + IMPORTANT: Returns a JSONResponse instead of re-raising so the response + flows back through CORSMiddleware and gets proper CORS headers. Re-raising + exceptions from BaseHTTPMiddleware bypasses CORS, causing browsers to + report CORS errors instead of the actual error (e.g., 401). """ async def dispatch( @@ -114,5 +132,17 @@ class ErrorLoggingMiddleware(BaseHTTPMiddleware): exc_info=True ) - # Re-raise to let FastAPI handle the response - raise + # Return a proper response so it flows through CORSMiddleware. + # If we re-raise, the response never passes through CORS and + # browsers see a CORS error instead of the actual error. + from starlette.responses import JSONResponse + from fastapi import HTTPException + if isinstance(exc, HTTPException): + return JSONResponse( + status_code=exc.status_code, + content={"detail": exc.detail}, + ) + return JSONResponse( + status_code=500, + content={"detail": "Internal server error"}, + )