From 49a49983e4e2be017c378dbf25ad1ea854fcecf8 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sat, 28 Mar 2026 14:00:03 -0700 Subject: [PATCH] feat(api-server): add Access-Control-Max-Age to CORS preflight responses (#3580) Adds Access-Control-Max-Age: 600 to CORS preflight responses, telling browsers to cache the preflight for 10 minutes. Reduces redundant OPTIONS requests and improves perceived latency for browser-based API clients. Salvaged from PR #3514 by aydnOktay. Co-authored-by: aydnOktay --- gateway/platforms/api_server.py | 2 ++ tests/gateway/test_api_server.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/gateway/platforms/api_server.py b/gateway/platforms/api_server.py index f0dfc6466f..a7776c0c3c 100644 --- a/gateway/platforms/api_server.py +++ b/gateway/platforms/api_server.py @@ -307,6 +307,7 @@ class APIServerAdapter(BasePlatformAdapter): if "*" in self._cors_origins: headers = dict(_CORS_HEADERS) headers["Access-Control-Allow-Origin"] = "*" + headers["Access-Control-Max-Age"] = "600" return headers if origin not in self._cors_origins: @@ -315,6 +316,7 @@ class APIServerAdapter(BasePlatformAdapter): headers = dict(_CORS_HEADERS) headers["Access-Control-Allow-Origin"] = origin headers["Vary"] = "Origin" + headers["Access-Control-Max-Age"] = "600" return headers def _origin_allowed(self, origin: str) -> bool: diff --git a/tests/gateway/test_api_server.py b/tests/gateway/test_api_server.py index 9f5eb0baf1..e40902a587 100644 --- a/tests/gateway/test_api_server.py +++ b/tests/gateway/test_api_server.py @@ -1356,6 +1356,21 @@ class TestCORS: assert "Authorization" in resp.headers.get("Access-Control-Allow-Headers", "") + @pytest.mark.asyncio + async def test_cors_preflight_sets_max_age(self): + adapter = _make_adapter(cors_origins=["http://localhost:3000"]) + app = _create_app(adapter) + async with TestClient(TestServer(app)) as cli: + resp = await cli.options( + "/v1/chat/completions", + headers={ + "Origin": "http://localhost:3000", + "Access-Control-Request-Method": "POST", + "Access-Control-Request-Headers": "Authorization, Content-Type", + }, + ) + assert resp.status == 200 + assert resp.headers.get("Access-Control-Max-Age") == "600" # --------------------------------------------------------------------------- # Conversation parameter # ---------------------------------------------------------------------------