Skip to content

Commit 0792db2

Browse files
support SOCKS proxies in sentry_sdk (#1050)
* support SOCKS proxies in sentry_sdk --------- Co-authored-by: Anton Pirker <[email protected]>
1 parent 4f0ab40 commit 0792db2

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

sentry_sdk/transport.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,24 @@ def _make_pool(
441441
if proxy_headers:
442442
opts["proxy_headers"] = proxy_headers
443443

444-
return urllib3.ProxyManager(proxy, **opts)
444+
if proxy.startswith("socks"):
445+
use_socks_proxy = True
446+
try:
447+
# Check if PySocks depencency is available
448+
from urllib3.contrib.socks import SOCKSProxyManager
449+
except ImportError:
450+
use_socks_proxy = False
451+
logger.warning(
452+
"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.",
453+
proxy,
454+
)
455+
456+
if use_socks_proxy:
457+
return SOCKSProxyManager(proxy, **opts)
458+
else:
459+
return urllib3.PoolManager(**opts)
460+
else:
461+
return urllib3.ProxyManager(proxy, **opts)
445462
else:
446463
return urllib3.PoolManager(**opts)
447464

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ pyrsistent==0.16.0 # TODO(py3): 0.17.0 requires python3, see https://github.com/
1111
executing
1212
asttokens
1313
responses
14+
pysocks
1415
ipdb

tests/test_client.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,18 @@ def test_proxy(monkeypatch, testcase):
252252
monkeypatch.setenv("HTTPS_PROXY", testcase["env_https_proxy"])
253253
if testcase.get("env_no_proxy") is not None:
254254
monkeypatch.setenv("NO_PROXY", testcase["env_no_proxy"])
255+
255256
kwargs = {}
257+
256258
if testcase["arg_http_proxy"] is not None:
257259
kwargs["http_proxy"] = testcase["arg_http_proxy"]
258260
if testcase["arg_https_proxy"] is not None:
259261
kwargs["https_proxy"] = testcase["arg_https_proxy"]
260262
if testcase.get("arg_proxy_headers") is not None:
261263
kwargs["proxy_headers"] = testcase["arg_proxy_headers"]
264+
262265
client = Client(testcase["dsn"], **kwargs)
266+
263267
if testcase["expected_proxy_scheme"] is None:
264268
assert client.transport._pool.proxy is None
265269
else:
@@ -269,6 +273,77 @@ def test_proxy(monkeypatch, testcase):
269273
assert client.transport._pool.proxy_headers == testcase["arg_proxy_headers"]
270274

271275

276+
@pytest.mark.parametrize(
277+
"testcase",
278+
[
279+
{
280+
"dsn": "https://[email protected]/123",
281+
"arg_http_proxy": "http://localhost/123",
282+
"arg_https_proxy": None,
283+
"expected_proxy_class": "<class 'urllib3.poolmanager.ProxyManager'>",
284+
},
285+
{
286+
"dsn": "https://[email protected]/123",
287+
"arg_http_proxy": "socks4a://localhost/123",
288+
"arg_https_proxy": None,
289+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
290+
},
291+
{
292+
"dsn": "https://[email protected]/123",
293+
"arg_http_proxy": "socks4://localhost/123",
294+
"arg_https_proxy": None,
295+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
296+
},
297+
{
298+
"dsn": "https://[email protected]/123",
299+
"arg_http_proxy": "socks5h://localhost/123",
300+
"arg_https_proxy": None,
301+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
302+
},
303+
{
304+
"dsn": "https://[email protected]/123",
305+
"arg_http_proxy": "socks5://localhost/123",
306+
"arg_https_proxy": None,
307+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
308+
},
309+
{
310+
"dsn": "https://[email protected]/123",
311+
"arg_http_proxy": None,
312+
"arg_https_proxy": "socks4a://localhost/123",
313+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
314+
},
315+
{
316+
"dsn": "https://[email protected]/123",
317+
"arg_http_proxy": None,
318+
"arg_https_proxy": "socks4://localhost/123",
319+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
320+
},
321+
{
322+
"dsn": "https://[email protected]/123",
323+
"arg_http_proxy": None,
324+
"arg_https_proxy": "socks5h://localhost/123",
325+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
326+
},
327+
{
328+
"dsn": "https://[email protected]/123",
329+
"arg_http_proxy": None,
330+
"arg_https_proxy": "socks5://localhost/123",
331+
"expected_proxy_class": "<class 'urllib3.contrib.socks.SOCKSProxyManager'>",
332+
},
333+
],
334+
)
335+
def test_socks_proxy(testcase):
336+
kwargs = {}
337+
338+
if testcase["arg_http_proxy"] is not None:
339+
kwargs["http_proxy"] = testcase["arg_http_proxy"]
340+
if testcase["arg_https_proxy"] is not None:
341+
kwargs["https_proxy"] = testcase["arg_https_proxy"]
342+
343+
client = Client(testcase["dsn"], **kwargs)
344+
assert str(type(client.transport._pool)) == testcase["expected_proxy_class"]
345+
346+
272347
def test_simple_transport(sentry_init):
273348
events = []
274349
sentry_init(transport=events.append)

0 commit comments

Comments
 (0)