I'm implementing a FastAPI backend where I want to allow CORS requests only from a predefined list of default origins and dynamically loaded origins stored in the database. However, when the frontend tries to call a GET API, the browser first sends an OPTIONS preflight request (as expected for CORS). The problem is: The OPTIONS request fails due to a CORS error. As a result, the actual GET request is never made. This issue suggests that the CORS middleware is not properly handling the dynamic origins, especially during the OPTIONS preflight phase. from fastapi.security import HTTPBasic, HTTPBasicCredentials from starlette.middleware.base import BaseHTTPMiddleware,RequestResponseEndpoint origins = [ "http://localhost:3000", "http://localhost:3001", "http://localhost:8006", ] class DynamicCORSMiddleware(BaseHTTPMiddleware): def __init__(self, app: ASGIApp): super().__init__(app) async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: origin = request.headers.get("origin") ic(origin) ic(request.method) # Preflight request if request.method == "OPTIONS": response = JSONResponse(content={"status": "ok"}) else: response = await call_next(request) # If no Origin header, skip CORS (non-browser requests) if not origin: return response if origin in origins: ic("Origin in default origins") response.headers["Access-Control-Allow-Origin"] = origin response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Allow-Headers"] = "*" response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" response.headers["Vary"] = "Origin" return response # Extract domain (remove protocol and port) ic(origin) domain = origin.replace("https://", "").replace("http://", "") ic(domain) # Check if domain exists in database domain_exists = domain_collection.find_one({"$or": [{"domain.main_domain": domain}, {"domain.sub_domain": domain}]}) if not domain_exists: raise HTTPException( status_code=403, detail=f"Domain {domain} not authorized" ) ic(domain_exists) # Process request response = await call_next(request) response.headers["Access-Control-Allow-Origin"] = origin response.headers["Access-Control-Allow-Credentials"] = "true" response.headers["Access-Control-Allow-Headers"] = "*" response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" response.headers["Vary"] = "Origin" ic(response) return response enter code here app = FastAPI( title="API", description="API documentation for backend", version="1.0.0", docs_url=None, # Disable the default docs URL redoc_url=None # Disable the default redoc URL ) app.add_middleware(DynamicCORSMiddleware) Continue reading...