Description
In Backend/main.py, the middleware is added in this order:
app.add_middleware(SecurityHeadersMiddleware) # 1st added = outermost
app.add_middleware(APIKeyScrubMiddleware) # 2nd
app.add_middleware(RateLimitMiddleware, ...) # 3rd
app.add_middleware(CORSMiddleware, ...) # 4th added = innermost
In Starlette/FastAPI, middleware executes in reverse order of add_middleware calls (LIFO). So the actual request flow is:
Request → CORS → RateLimit → APIKeyScrub → SecurityHeaders → Route
When RateLimitMiddleware returns a 429 response directly (without calling call_next), the response bypasses CORSMiddleware's response processing. This means the 429 response is missing CORS headers (Access-Control-Allow-Origin, etc.).
Impact
- Frontend receives a 429 rate-limit response but the browser blocks it due to CORS
- The user sees a cryptic "CORS error" in the console instead of a helpful "rate limit exceeded" message
- Makes it impossible for the frontend to show a proper rate-limit notification
Steps to Reproduce
- Hit the API rapidly to trigger rate limiting
- Observe in browser dev tools: the 429 response is blocked by CORS
- Frontend sees a network error instead of the 429 status + JSON body
Expected Behavior
The CORS middleware should be the outermost middleware so its headers are always applied, even on short-circuit responses from inner middleware. Move CORSMiddleware to be added first:
app.add_middleware(CORSMiddleware, ...) # Add first = outermost
app.add_middleware(SecurityHeadersMiddleware)
app.add_middleware(APIKeyScrubMiddleware)
app.add_middleware(RateLimitMiddleware, ...)
Description
In
Backend/main.py, the middleware is added in this order:In Starlette/FastAPI, middleware executes in reverse order of
add_middlewarecalls (LIFO). So the actual request flow is:When
RateLimitMiddlewarereturns a 429 response directly (without callingcall_next), the response bypasses CORSMiddleware's response processing. This means the 429 response is missing CORS headers (Access-Control-Allow-Origin, etc.).Impact
Steps to Reproduce
Expected Behavior
The CORS middleware should be the outermost middleware so its headers are always applied, even on short-circuit responses from inner middleware. Move
CORSMiddlewareto be added first: