Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion gateway/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2011,7 +2011,19 @@ def _enable_from_env(platform: Platform) -> PlatformConfig:
if api_server_enabled or api_server_key:
if Platform.API_SERVER not in config.platforms:
config.platforms[Platform.API_SERVER] = PlatformConfig()
config.platforms[Platform.API_SERVER].enabled = True
# Respect an explicit ``enabled: false`` in config.yaml (flagged by
# ``_enabled_explicit``). In multiplex mode a secondary profile's
# config.yaml pins ``platforms.api_server.enabled: false`` so it shares
# the default profile's listener instead of binding its own port. That
# profile still inherits the process-level env (including
# ``API_SERVER_KEY``); without this guard the env-var presence would
# force-enable the listener and trip the MultiplexConfigError check.
# Pop (don't read) the marker — the api_server branch is terminal (no
# later registry pass re-enables it), so this both consumes the flag and
# avoids reading it twice, matching the pop convention used elsewhere.
api_server_explicit = config.platforms[Platform.API_SERVER].extra.pop("_enabled_explicit", False)
if not api_server_explicit or config.platforms[Platform.API_SERVER].enabled:
config.platforms[Platform.API_SERVER].enabled = True
if api_server_key:
config.platforms[Platform.API_SERVER].extra["key"] = api_server_key
if api_server_cors_origins:
Expand Down
33 changes: 33 additions & 0 deletions tests/gateway/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2117,3 +2117,36 @@ def test_multiplex_profiles_explicit_top_level_false_not_consulting_nested(
"Explicit top-level false was overridden by nested true — "
"loader must respect top-level precedence when key is present"
)


class TestApiServerEnvOverride:
def test_env_key_does_not_reenable_explicitly_disabled_api_server(self):
"""An explicit ``platforms.api_server.enabled: false`` must survive
_apply_env_overrides() even when API_SERVER_KEY is present in the env.

Regression: _apply_env_overrides() force-set api_server.enabled = True
whenever API_SERVER_KEY (or API_SERVER_ENABLED) was set. In multiplex
mode a secondary profile pins ``api_server.enabled: false`` so it shares
the default profile's listener instead of binding its own port, but it
still inherits the process-level API_SERVER_KEY. The unconditional
re-enable flipped it back on and tripped the MultiplexConfigError check.

The fix honors the explicit disable, flagged by ``_enabled_explicit`` in
the platform's extra (set when the config.yaml pins enabled).
"""
config = GatewayConfig(
platforms={
Platform.API_SERVER: PlatformConfig(
enabled=False,
extra={"_enabled_explicit": True},
),
},
)

with patch.dict(os.environ, {"API_SERVER_KEY": "secret-key"}, clear=True):
_apply_env_overrides(config)

# Explicit disable wins over the env-var presence.
assert config.platforms[Platform.API_SERVER].enabled is False
# The key is still wired through for the shared listener.
assert config.platforms[Platform.API_SERVER].extra.get("key") == "secret-key"
Loading