|
| 1 | +"""Tests for SOCKS proxy support (OpenHands/OpenHands-CLI#632). |
| 2 | +
|
| 3 | +When a user has SOCKS proxy env vars set (e.g. all_proxy=socks5://...), |
| 4 | +httpx needs the socksio package to handle SOCKS proxy connections. |
| 5 | +Without it, importing litellm (which creates an httpx.Client at module |
| 6 | +level) crashes at startup with ImportError. |
| 7 | +""" |
| 8 | + |
| 9 | +import os |
| 10 | +import subprocess |
| 11 | +import sys |
| 12 | + |
| 13 | + |
| 14 | +def test_socksio_is_installed(): |
| 15 | + """Verify that socksio is installed as part of httpx[socks].""" |
| 16 | + import socksio # noqa: F401 |
| 17 | + |
| 18 | + |
| 19 | +def test_httpx_socks_extra_available(): |
| 20 | + """Verify httpx can create a client when SOCKS proxy env vars are set.""" |
| 21 | + import httpx |
| 22 | + |
| 23 | + # Simulate a SOCKS proxy env var; the Client constructor should not raise |
| 24 | + # ImportError for socksio. We use a non-routable address so no real |
| 25 | + # connection is attempted. |
| 26 | + client = httpx.Client(proxy="socks5://127.0.0.1:19999") |
| 27 | + client.close() |
| 28 | + |
| 29 | + |
| 30 | +def test_import_with_socks_proxy_env(): |
| 31 | + """Ensure httpx can be imported and used when all_proxy is set to socks5.""" |
| 32 | + env = os.environ.copy() |
| 33 | + env["all_proxy"] = "socks5://127.0.0.1:19999" |
| 34 | + env["https_proxy"] = "socks5://127.0.0.1:19999" |
| 35 | + |
| 36 | + result = subprocess.run( |
| 37 | + [ |
| 38 | + sys.executable, |
| 39 | + "-c", |
| 40 | + "import httpx; c = httpx.Client(); c.close(); print('ok')", |
| 41 | + ], |
| 42 | + capture_output=True, |
| 43 | + text=True, |
| 44 | + env=env, |
| 45 | + ) |
| 46 | + assert result.returncode == 0, ( |
| 47 | + f"Import failed with SOCKS proxy env vars set:\n{result.stderr}" |
| 48 | + ) |
| 49 | + assert "ok" in result.stdout |
0 commit comments