feat: FlowPilot AI — Phases 4 & 5 (Gallery, Export, Responsive, Enterprise, Analytics) #116

Merged
chihlasm merged 66 commits from feat/flowpilot-ai-session into main 2026-03-21 05:15:51 +00:00
Showing only changes of commit 7518fe643b - Show all commits

View File

@@ -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"},
)