fix(config): accept placeholder base_url in custom provider validation

_normalize_custom_provider_entry() ran urlparse() on base_url and dropped
any entry whose value was an un-expanded placeholder, so a caller reaching
the normalizer with raw config (e.g. the Dockerized gateway path) silently
skipped the provider with a 'not a valid URL' warning. Skip URL validation
when the candidate contains a placeholder token — both ${ENV_VAR} env-refs
and bare {region}-style templates — since those are expanded at runtime.

Closes #14457
This commit is contained in:
ms-alan 2026-06-27 04:01:16 -07:00 committed by Teknium
parent b34771fc06
commit 16192103f4
2 changed files with 54 additions and 0 deletions

View file

@ -4269,6 +4269,14 @@ def _normalize_custom_provider_entry(
raw_url = entry.get(url_key)
if isinstance(raw_url, str) and raw_url.strip():
candidate = raw_url.strip()
# Accept URLs containing unresolved placeholder tokens — both
# ``${ENV_VAR}`` env-refs and bare ``{region}``-style templates —
# without URL validation. They are expanded at runtime, so a
# caller reaching this normalizer with raw (un-expanded) config
# would otherwise see the provider silently dropped (#14457).
if re.search(r"\{[^}]+\}", candidate):
base_url = candidate
break
parsed = urlparse(candidate)
if parsed.scheme and parsed.netloc:
base_url = candidate

View file

@ -191,3 +191,49 @@ class TestNormalizeCustomProviderEntry:
result = _normalize_custom_provider_entry(entry)
assert result is not None
assert "models" not in result
def test_env_var_placeholder_in_base_url_not_rejected(self):
"""A base_url that is an un-expanded ${ENV_VAR} placeholder must not be
rejected as an invalid URL it is expanded at runtime, so a caller
reaching this normalizer with raw config would otherwise see the
provider silently dropped. Regression test for #14457."""
entry = {
"name": "PROVIDER_A",
"base_url": "${PROVIDER_A_BASE_URL}",
"key_env": "PROVIDER_A_API_KEY",
}
result = _normalize_custom_provider_entry(entry, provider_key="PROVIDER_A")
assert result is not None
assert result["base_url"] == "${PROVIDER_A_BASE_URL}"
def test_multiple_env_vars_in_base_url(self):
"""base_url with multiple ${VAR} placeholders is accepted verbatim."""
entry = {
"name": "multi-var-provider",
"base_url": "${SCHEME}://${HOST}:${PORT}/v1",
}
result = _normalize_custom_provider_entry(entry)
assert result is not None
assert result["base_url"] == "${SCHEME}://${HOST}:${PORT}/v1"
def test_bare_brace_region_placeholder_accepted(self):
"""A bare {region}-style template token (not an env-ref) is also
accepted without validation, supporting region-substitution URLs."""
entry = {
"name": "regional",
"base_url": "https://{region}.api.example.com/v1",
}
result = _normalize_custom_provider_entry(entry, provider_key="regional")
assert result is not None
assert result["base_url"] == "https://{region}.api.example.com/v1"
def test_invalid_url_without_placeholder_still_rejected(self):
"""A malformed URL with no scheme/host AND no placeholder token is
still rejected the placeholder bypass must not weaken validation of
ordinary literal URLs."""
entry = {
"name": "bad",
"base_url": "not-a-url",
}
result = _normalize_custom_provider_entry(entry, provider_key="bad")
assert result is None