diff --git a/functions-python/operations_api/function_config.json b/functions-python/operations_api/function_config.json index f8ef7b007..d38687046 100644 --- a/functions-python/operations_api/function_config.json +++ b/functions-python/operations_api/function_config.json @@ -10,6 +10,9 @@ "environment_variables": [ { "key": "GOOGLE_CLIENT_ID" + }, + { + "key": "CORS_ALLOWED_ORIGINS" } ], "secret_environment_variables": [ diff --git a/functions-python/operations_api/src/main.py b/functions-python/operations_api/src/main.py index 8f6b51610..8d9cd8ff7 100644 --- a/functions-python/operations_api/src/main.py +++ b/functions-python/operations_api/src/main.py @@ -14,8 +14,11 @@ # limitations under the License. # +import os + from flask import Request, Response from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware from feeds_gen.apis.operations_api import router as FeedsApiRouter from feeds_gen.apis.licenses_api import router as LicenseApiRouter from feeds_gen.apis.users_api import router as UsersApiRouter @@ -35,6 +38,21 @@ # Add here middlewares that should be applied to all routes. app.add_middleware(RequestContextMiddleware) +# Added last so it becomes the outermost ASGI layer (Starlette middlewares wrap +# in reverse order of registration) and can answer CORS preflight OPTIONS +# requests before they ever reach RequestContextMiddleware's auth check, which +# would otherwise 401 every preflight since browsers never send Authorization +# on an OPTIONS request. +app.add_middleware( + CORSMiddleware, + allow_origins=[ + origin.strip() + for origin in os.getenv("CORS_ALLOWED_ORIGINS", "*").split(",") + if origin.strip() + ], + allow_methods=["*"], + allow_headers=["*"], +) app.include_router(FeedsApiRouter) app.include_router(LicenseApiRouter) app.include_router(UsersApiRouter)