Skip to content

Commit af377a5

Browse files
authored
Merge pull request #715 from seratch/issue-714
Fix #714 by adding proxy support for sync WebClient
2 parents 2b937e4 + d02beb5 commit af377a5

File tree

4 files changed

+106
-1
lines changed

4 files changed

+106
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ For sync requests, see the [urllib SSL documentation](https://docs.python.org/3/
276276

277277
A proxy is supported when making async requests, pass the `proxy` option, supported by both the RTM and the Web client.
278278

279-
For more information, see [AIOHttp Proxy documentation](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support).
279+
For async requests, see [AIOHttp Proxy documentation](https://docs.aiohttp.org/en/stable/client_advanced.html#proxy-support).
280+
281+
For sync requests, setting either `HTTPS_PROXY` env variable or the `proxy` option works.
280282

281283
#### DNS performance
282284

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# ------------------
2+
# Only for running this script here
3+
import asyncio
4+
import logging
5+
import sys
6+
from os.path import dirname
7+
8+
sys.path.insert(1, f"{dirname(__file__)}/../../..")
9+
logging.basicConfig(level=logging.DEBUG)
10+
# ------------------
11+
12+
logger = logging.getLogger(__name__)
13+
14+
import os
15+
from slack import WebClient
16+
17+
# export HTTPS_PROXY=http://localhost:9000
18+
client = WebClient(token=os.environ["SLACK_API_TOKEN"])
19+
response = client.auth_test()
20+
logger.info(f"HTTPS_PROXY response: {response}")
21+
22+
client = WebClient(
23+
token=os.environ["SLACK_API_TOKEN"],
24+
proxy="http://localhost:9000"
25+
)
26+
response = client.auth_test()
27+
logger.info(f"sync response: {response}")
28+
29+
client = WebClient(
30+
token=os.environ["SLACK_API_TOKEN"],
31+
proxy="localhost:9000"
32+
)
33+
response = client.auth_test()
34+
logger.info(f"sync response: {response}")
35+
36+
async def async_call():
37+
client = WebClient(
38+
token=os.environ["SLACK_API_TOKEN"],
39+
proxy="http://localhost:9000",
40+
run_async=True
41+
)
42+
response = await client.auth_test()
43+
logger.info(f"async response: {response}")
44+
45+
asyncio.run(async_call())
46+
47+
# Terminal A:
48+
# pip3 install proxy.py
49+
# proxy --port 9000 --log-level d
50+
51+
# Terminal B:
52+
# export SLACK_API_TOKEN=xoxb-***
53+
# python3 integration_tests/samples/issues/issue_714.py
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import asyncio
2+
import os
3+
import unittest
4+
from urllib.error import URLError
5+
6+
from aiohttp import ClientConnectorError
7+
8+
from integration_tests.env_variable_names import SLACK_SDK_TEST_BOT_TOKEN
9+
from integration_tests.helpers import async_test
10+
from slack import WebClient
11+
12+
13+
class TestWebClient(unittest.TestCase):
14+
15+
def setUp(self):
16+
self.proxy = "http://invalid-host:9999"
17+
self.bot_token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
18+
19+
def tearDown(self):
20+
pass
21+
22+
def test_proxy_failure(self):
23+
client: WebClient = WebClient(
24+
token=self.bot_token,
25+
run_async=False,
26+
proxy=self.proxy,
27+
loop=asyncio.new_event_loop())
28+
with self.assertRaises(URLError):
29+
client.auth_test()
30+
31+
@async_test
32+
async def test_proxy_failure_async(self):
33+
client: WebClient = WebClient(
34+
token=self.bot_token,
35+
proxy=self.proxy,
36+
run_async=True
37+
)
38+
with self.assertRaises(ClientConnectorError):
39+
await client.auth_test()

slack/web/base_client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import logging
1010
import mimetypes
1111
import os
12+
import re
1213
import uuid
1314
import warnings
1415
from http.client import HTTPResponse
@@ -547,6 +548,16 @@ def _perform_urllib_http_request(
547548
# which might be a security risk if the URL to open can be manipulated by an external user.
548549
if url.lower().startswith("http"):
549550
req = Request(method="POST", url=url, data=body, headers=headers)
551+
if self.proxy is not None:
552+
if isinstance(self.proxy, str):
553+
host = re.sub("^https?://", "", self.proxy)
554+
req.set_proxy(host, "http")
555+
req.set_proxy(host, "https")
556+
else:
557+
raise SlackRequestError(
558+
f"Invalid proxy detected: {self.proxy} must be a str value"
559+
)
560+
550561
resp: HTTPResponse = urlopen(req, context=self.ssl)
551562
charset = resp.headers.get_content_charset()
552563
body: str = resp.read().decode(charset) # read the response body here

0 commit comments

Comments
 (0)