CORS Preflight Fix - Final Implementation
Issue
OPTIONS preflight requests were returning 401 Unauthorized, causing:
Access to fetch at 'https://api.engram.work/api/v1/memory/episodes/...'
from origin 'https://engram.work' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Root Cause
The CORSPreflightMiddleware was passing through to call_next(), which allowed authentication dependencies to be evaluated before CORS headers could be set. Even though FastAPI’s CORSMiddleware should handle OPTIONS automatically, route dependencies (like get_current_user) were being evaluated, causing 401 errors.
Solution
Updated CORSPreflightMiddleware to:
- Return immediately for OPTIONS requests (don’t call
call_next()) - Validate origin against allowed origins list
- Set CORS headers directly in the response
- Bypass authentication completely for OPTIONS
Implementation
async def dispatch(self, request: Request, call_next):
if request.method == "OPTIONS":
origin = request.headers.get("origin")
# Validate origin
allowed_origins = self.settings.cors_origins
is_allowed = origin in allowed_origins or "*" in allowed_origins
# Create response with CORS headers
response = Response(status_code=200)
if is_allowed and origin:
response.headers["Access-Control-Allow-Origin"] = origin
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Allow-Methods"] = "..."
response.headers["Access-Control-Allow-Headers"] = "..."
return response # Return immediately, bypassing authentication
response = await call_next(request)
return response
Middleware Order
In FastAPI, middleware runs in reverse order of addition:
- CORSMiddleware (added first) → runs LAST
- CORSPreflightMiddleware (added second) → runs BEFORE CORSMiddleware
This means CORSPreflightMiddleware intercepts OPTIONS first and returns immediately, preventing authentication from being evaluated.
Testing
After deployment, test with:
curl -v -X OPTIONS \
-H "Origin: https://engram.work" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: authorization" \
https://api.engram.work/api/v1/memory/episodes/session-test
Expected: 200 OK with Access-Control-Allow-Origin: https://engram.work
Status
✅ Fix committed: 851e66be2
⏳ Waiting for deployment to complete
📝 Will test after deployment