Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support SOCKS proxies in sentry_sdk #1050

Merged
merged 12 commits into from
Jun 19, 2023
19 changes: 18 additions & 1 deletion sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,24 @@ def _make_pool(
if proxy_headers:
opts["proxy_headers"] = proxy_headers

return urllib3.ProxyManager(proxy, **opts)
if proxy.startswith("socks"):
use_socks_proxy = True
try:
# Check if PySocks depencency is available
from urllib3.contrib.socks import SOCKSProxyManager
except ImportError:
use_socks_proxy = False
logger.warning(
"You have configured a SOCKS proxy (%s) but support for SOCKS proxies is not installed. Disabling proxy support. Please add `PySocks` (or `urllib3` with the `[socks]` extra) to your dependencies.",
proxy,
)

if use_socks_proxy:
return SOCKSProxyManager(proxy, **opts)
else:
return urllib3.PoolManager(**opts)
else:
return urllib3.ProxyManager(proxy, **opts)
else:
return urllib3.PoolManager(**opts)

Expand Down
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pyrsistent==0.16.0 # TODO(py3): 0.17.0 requires python3, see https://github.com/
executing
asttokens
responses
pysocks
ipdb
75 changes: 75 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,18 @@ def test_proxy(monkeypatch, testcase):
monkeypatch.setenv("HTTPS_PROXY", testcase["env_https_proxy"])
if testcase.get("env_no_proxy") is not None:
monkeypatch.setenv("NO_PROXY", testcase["env_no_proxy"])

kwargs = {}

if testcase["arg_http_proxy"] is not None:
kwargs["http_proxy"] = testcase["arg_http_proxy"]
if testcase["arg_https_proxy"] is not None:
kwargs["https_proxy"] = testcase["arg_https_proxy"]
if testcase.get("arg_proxy_headers") is not None:
kwargs["proxy_headers"] = testcase["arg_proxy_headers"]

client = Client(testcase["dsn"], **kwargs)

if testcase["expected_proxy_scheme"] is None:
assert client.transport._pool.proxy is None
else:
Expand All @@ -269,6 +273,77 @@ def test_proxy(monkeypatch, testcase):
assert client.transport._pool.proxy_headers == testcase["arg_proxy_headers"]


@pytest.mark.parametrize(
"testcase",
[
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "http://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.poolmanager.ProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks4a://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks4://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks5h://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": "socks5://localhost/123",
"arg_https_proxy": None,
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks4a://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks4://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks5h://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
{
"dsn": "https://[email protected]/123",
"arg_http_proxy": None,
"arg_https_proxy": "socks5://localhost/123",
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
},
],
)
def test_socks_proxy(testcase):
kwargs = {}

if testcase["arg_http_proxy"] is not None:
kwargs["http_proxy"] = testcase["arg_http_proxy"]
if testcase["arg_https_proxy"] is not None:
kwargs["https_proxy"] = testcase["arg_https_proxy"]

client = Client(testcase["dsn"], **kwargs)
assert str(type(client.transport._pool)) == testcase["expected_proxy_class"]


def test_simple_transport(sentry_init):
events = []
sentry_init(transport=events.append)
Expand Down