Skip to content

Commit 44a91a7

Browse files
authored
SNOW-810810: Fix 'SOCKSProxyManager' object has no attribute 'proxy_headers' error (#1551)
1 parent 9b586d4 commit 44a91a7

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

DESCRIPTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
1212

1313
- Fixed a bug in retry logic for okta authentication to refresh token.
1414
- Support `RSAPublicKey` when constructing `AuthByKeyPair` in addition to raw bytes.
15+
- Fixed a bug when connecting through SOCKS5 proxy, the attribute `proxy_header` is missing on `SOCKSProxyManager`.
1516

1617
- v3.1.0(July 31,2023)
1718

src/snowflake/connector/network.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
)
112112
from .vendored.requests.utils import prepend_scheme_if_needed, select_proxy
113113
from .vendored.urllib3.exceptions import ProtocolError
114+
from .vendored.urllib3.poolmanager import ProxyManager
114115
from .vendored.urllib3.util.url import parse_url
115116

116117
if TYPE_CHECKING:
@@ -268,8 +269,14 @@ def get_connection(
268269
)
269270
proxy_manager = self.proxy_manager_for(proxy)
270271

271-
# Add Host to proxy header SNOW-232777
272-
proxy_manager.proxy_headers["Host"] = parsed_url.hostname
272+
if isinstance(proxy_manager, ProxyManager):
273+
# Add Host to proxy header SNOW-232777
274+
proxy_manager.proxy_headers["Host"] = parsed_url.hostname
275+
else:
276+
logger.debug(
277+
f"Unable to set 'Host' to proxy manager of type {type(proxy_manager)} as"
278+
f" it does not have attribute 'proxy_headers'."
279+
)
273280
conn = proxy_manager.connection_from_url(url)
274281
else:
275282
# Only scheme should be lower case

test/unit/test_proxies.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@
55

66
from __future__ import annotations
77

8+
import logging
89
import os
10+
import unittest.mock
11+
12+
import pytest
13+
14+
import snowflake.connector
15+
from snowflake.connector.errors import OperationalError
916

1017

1118
def test_set_proxies():
@@ -31,3 +38,60 @@ def test_set_proxies():
3138
# NOTE environment variable is set if the proxy parameter is specified.
3239
del os.environ["HTTP_PROXY"]
3340
del os.environ["HTTPS_PROXY"]
41+
42+
43+
@pytest.mark.skipolddriver
44+
def test_socks_5_proxy_missing_proxy_header_attribute(caplog):
45+
from snowflake.connector.vendored.urllib3.poolmanager import ProxyManager
46+
47+
os.environ["HTTPS_PROXY"] = "socks5://localhost:8080"
48+
49+
class MockSOCKSProxyManager:
50+
def __init__(self):
51+
pass
52+
53+
def connection_from_url(self, url):
54+
pass
55+
56+
def mock_proxy_manager_for_url_no_header(*args, **kwargs):
57+
return MockSOCKSProxyManager()
58+
59+
def mock_proxy_manager_for_url_wiht_header(*args, **kwargs):
60+
return ProxyManager("testurl")
61+
62+
# connection
63+
caplog.set_level(logging.DEBUG, "snowflake.connector")
64+
65+
# bad path
66+
with unittest.mock.patch(
67+
"snowflake.connector.network.ProxySupportAdapter.proxy_manager_for",
68+
mock_proxy_manager_for_url_no_header,
69+
):
70+
with pytest.raises(OperationalError):
71+
snowflake.connector.connect(
72+
account="testaccount",
73+
user="testuser",
74+
password="testpassword",
75+
database="TESTDB",
76+
warehouse="TESTWH",
77+
)
78+
assert "Unable to set 'Host' to proxy manager of type" in caplog.text
79+
80+
caplog.clear()
81+
82+
# happy path
83+
with unittest.mock.patch(
84+
"snowflake.connector.network.ProxySupportAdapter.proxy_manager_for",
85+
mock_proxy_manager_for_url_wiht_header,
86+
):
87+
with pytest.raises(OperationalError):
88+
snowflake.connector.connect(
89+
account="testaccount",
90+
user="testuser",
91+
password="testpassword",
92+
database="TESTDB",
93+
warehouse="TESTWH",
94+
)
95+
assert "Unable to set 'Host' to proxy manager of type" not in caplog.text
96+
97+
del os.environ["HTTPS_PROXY"]

0 commit comments

Comments
 (0)