test(proxy): regression tests for NO_PROXY bypass on keepalive client

Pin the behaviour added in the preceding commit — `_get_proxy_for_base_url()`
must return None for hosts covered by NO_PROXY and the HTTPS_PROXY otherwise,
and the full `_create_openai_client()` path must NOT mount HTTPProxy for a
NO_PROXY host.

Refs: #14966
This commit is contained in:
Teknium 2026-04-24 02:59:19 -07:00 committed by Teknium
parent cbc39a8672
commit 166b960fe4

View file

@ -22,7 +22,7 @@ from unittest.mock import patch
import httpx import httpx
from run_agent import AIAgent, _get_proxy_from_env from run_agent import AIAgent, _get_proxy_from_env, _get_proxy_for_base_url
def _make_agent(): def _make_agent():
@ -143,3 +143,78 @@ def test_create_openai_client_no_proxy_when_env_unset(mock_openai, monkeypatch):
"pools were %r" % (pool_types,) "pools were %r" % (pool_types,)
) )
http_client.close() http_client.close()
def test_get_proxy_for_base_url_returns_none_when_host_bypassed(monkeypatch):
"""NO_PROXY must suppress the proxy for matching base_urls.
Regression for #14966: users running a local inference endpoint
(Ollama, LM Studio, llama.cpp) with a global HTTPS_PROXY would see
the keepalive client route loopback traffic through the proxy, which
typically answers 502 for local hosts. NO_PROXY should opt those
hosts out via stdlib ``urllib.request.proxy_bypass_environment``.
"""
for key in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY",
"https_proxy", "http_proxy", "all_proxy",
"NO_PROXY", "no_proxy"):
monkeypatch.delenv(key, raising=False)
monkeypatch.setenv("HTTPS_PROXY", "http://127.0.0.1:7897")
monkeypatch.setenv("NO_PROXY", "localhost,127.0.0.1,192.168.0.0/16")
# Local endpoint — must bypass the proxy.
assert _get_proxy_for_base_url("http://127.0.0.1:11434/v1") is None
assert _get_proxy_for_base_url("http://localhost:1234/v1") is None
# Non-local endpoint — proxy still applies.
assert _get_proxy_for_base_url("https://api.openai.com/v1") == "http://127.0.0.1:7897"
def test_get_proxy_for_base_url_returns_proxy_when_no_proxy_unset(monkeypatch):
for key in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY",
"https_proxy", "http_proxy", "all_proxy",
"NO_PROXY", "no_proxy"):
monkeypatch.delenv(key, raising=False)
monkeypatch.setenv("HTTPS_PROXY", "http://corp:8080")
assert _get_proxy_for_base_url("http://127.0.0.1:11434/v1") == "http://corp:8080"
def test_get_proxy_for_base_url_returns_none_when_proxy_unset(monkeypatch):
for key in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY",
"https_proxy", "http_proxy", "all_proxy",
"NO_PROXY", "no_proxy"):
monkeypatch.delenv(key, raising=False)
monkeypatch.setenv("NO_PROXY", "localhost,127.0.0.1")
assert _get_proxy_for_base_url("http://127.0.0.1:11434/v1") is None
assert _get_proxy_for_base_url("https://api.openai.com/v1") is None
@patch("run_agent.OpenAI")
def test_create_openai_client_bypasses_proxy_for_no_proxy_host(mock_openai, monkeypatch):
"""E2E: with HTTPS_PROXY + NO_PROXY=localhost, a local base_url gets a
keepalive client with NO HTTPProxy mount."""
for key in ("HTTPS_PROXY", "HTTP_PROXY", "ALL_PROXY",
"https_proxy", "http_proxy", "all_proxy",
"NO_PROXY", "no_proxy"):
monkeypatch.delenv(key, raising=False)
monkeypatch.setenv("HTTPS_PROXY", "http://127.0.0.1:7897")
monkeypatch.setenv("NO_PROXY", "localhost,127.0.0.1")
agent = _make_agent()
kwargs = {
"api_key": "***",
"base_url": "http://127.0.0.1:11434/v1",
}
agent._create_openai_client(kwargs, reason="test", shared=False)
forwarded = mock_openai.call_args.kwargs
http_client = _extract_http_client(forwarded)
assert isinstance(http_client, httpx.Client)
pool_types = [
type(mount._pool).__name__
for mount in http_client._mounts.values()
if mount is not None and hasattr(mount, "_pool")
]
assert "HTTPProxy" not in pool_types, (
"NO_PROXY host must not route through HTTPProxy; pools were %r" % (pool_types,)
)
http_client.close()