diff --git a/ChangeLog b/ChangeLog index ff1469a..f53550e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ ChangeLog - Try to get proxy info from environment if not explicitly provided (#124) - support proxy basic authenticaiton. (#125) - Fix NoneType exception at WebsocketApp.send (#126) + - not use proxy for localhost (#132) - 0.21.0 diff --git a/websocket/_app.py b/websocket/_app.py index 999a357..138fbbe 100644 --- a/websocket/_app.py +++ b/websocket/_app.py @@ -112,7 +112,7 @@ class WebSocketApp(object): self.sock.ping() def run_forever(self, sockopt=None, sslopt=None, ping_interval=0, ping_timeout=None, - http_proxy_host=None, http_proxy_port=None): + http_proxy_host=None, http_proxy_port=None, http_no_proxy=None): """ run event loop for WebSocket framework. This loop is infinite loop and is alive during websocket is available. @@ -124,6 +124,7 @@ class WebSocketApp(object): ping_timeout: timeout(second) if the pong message is not recieved. http_proxy_host: http proxy host name. http_proxy_port: http proxy port. If not set, set to 80. + http_no_proxy: host names, which doesn't use proxy. """ if not ping_timeout or ping_timeout<=0: @@ -143,6 +144,7 @@ class WebSocketApp(object): self.sock.settimeout(getdefaulttimeout()) self.sock.connect(self.url, header=self.header, cookie=self.cookie, http_proxy_host=http_proxy_host, http_proxy_port=http_proxy_port, + http_no_proxy = http_no_proxy, subprotocols=self.subprotocols) self._callback(self.on_open) diff --git a/websocket/_core.py b/websocket/_core.py index 8c056bd..1cd554b 100644 --- a/websocket/_core.py +++ b/websocket/_core.py @@ -169,20 +169,37 @@ def _parse_url(url): return (hostname, port, resource, is_secure) -def _get_proxy_info(is_secure, **options): +DEFAULT_NO_PROXY_HOST = ["localhost", "127.0.0.1"] + +def _is_no_proxy_host(hostname, no_proxy): + if not no_proxy: + v = os.environ.get("no_proxy", "").replace(" ", "") + no_proxy = v.split(",") + if not no_proxy: + no_proxy = DEFAULT_NO_PROXY_HOST + + return hostname in no_proxy + +def _get_proxy_info(hostname, is_secure, **options): """ try to retrieve proxy host and port from environment if not provided in options. result is (proxy_host, proxy_port, proxy_auth). proxy_auth is tuple of username and password of proxy authentication information. + hostname: websocket server name. + is_secure: is the connection secure? (wss) looks for "https_proxy" in env before falling back to "http_proxy" options: "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. + "http_no_proxy" - host names, which doesn't use proxy. "http_proxy_auth" - http proxy auth infomation. tuple of username and password. defualt is None """ + if _is_no_proxy_host(hostname, options.get("http_no_proxy", None)): + return None, 0, None + http_proxy_host = options.get("http_proxy_host", None) if http_proxy_host: return http_proxy_host, options.get("http_proxy_port", 0), options.get("http_proxy_auth", None) @@ -224,6 +241,7 @@ def create_connection(url, timeout=None, **options): "cookie" -> cookie value. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. + "http_no_proxy" - host names, which doesn't use proxy. "http_proxy_auth" - http proxy auth infomation. tuple of username and password. defualt is None "enable_multithread" -> enable lock for multithread. @@ -434,6 +452,7 @@ class WebSocket(object): "cookie" -> cookie value. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. + "http_no_proxy" - host names, which doesn't use proxy. "http_proxy_auth" - http proxy auth infomation. tuple of username and password. defualt is None "subprotocols" - array of available sub protocols. default is None. @@ -441,7 +460,7 @@ class WebSocket(object): """ hostname, port, resource, is_secure = _parse_url(url) - proxy_host, proxy_port, proxy_auth = _get_proxy_info(is_secure, **options) + proxy_host, proxy_port, proxy_auth = _get_proxy_info(hostname, is_secure, **options) if not proxy_host: addrinfo_list = socket.getaddrinfo(hostname, port, 0, 0, socket.SOL_TCP) else: diff --git a/websocket/tests/test_websocket.py b/websocket/tests/test_websocket.py index 0503458..9d140d0 100644 --- a/websocket/tests/test_websocket.py +++ b/websocket/tests/test_websocket.py @@ -557,60 +557,76 @@ class ProxyInfoTest(unittest.TestCase): def testProxyFromArgs(self): - self.assertEqual(_get_proxy_info(False, http_proxy_host="localhost"), ("localhost", 0, None)) - self.assertEqual(_get_proxy_info(False, http_proxy_host="localhost", http_proxy_port=3128), ("localhost", 3128, None)) - self.assertEqual(_get_proxy_info(True, http_proxy_host="localhost"), ("localhost", 0, None)) - self.assertEqual(_get_proxy_info(True, http_proxy_host="localhost", http_proxy_port=3128), ("localhost", 3128, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False, http_proxy_host="localhost"), ("localhost", 0, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False, http_proxy_host="localhost", http_proxy_port=3128), ("localhost", 3128, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost"), ("localhost", 0, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost", http_proxy_port=3128), ("localhost", 3128, None)) - self.assertEqual(_get_proxy_info(False, http_proxy_host="localhost", http_proxy_auth=("a", "b")), + self.assertEqual(_get_proxy_info("echo.websocket.org", False, http_proxy_host="localhost", http_proxy_auth=("a", "b")), ("localhost", 0, ("a", "b"))) - self.assertEqual(_get_proxy_info(False, http_proxy_host="localhost", http_proxy_port=3128, http_proxy_auth=("a", "b")), + self.assertEqual(_get_proxy_info("echo.websocket.org", False, http_proxy_host="localhost", http_proxy_port=3128, http_proxy_auth=("a", "b")), ("localhost", 3128, ("a", "b"))) - self.assertEqual(_get_proxy_info(True, http_proxy_host="localhost", http_proxy_auth=("a", "b")), + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost", http_proxy_auth=("a", "b")), ("localhost", 0, ("a", "b"))) - self.assertEqual(_get_proxy_info(True, http_proxy_host="localhost", http_proxy_port=3128, http_proxy_auth=("a", "b")), + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost", http_proxy_port=3128, http_proxy_auth=("a", "b")), ("localhost", 3128, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost", http_proxy_port=3128, http_no_proxy=["example.com"], http_proxy_auth=("a", "b")), + ("localhost", 3128, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", True, http_proxy_host="localhost", http_proxy_port=3128, http_no_proxy=["echo.websocket.org"], http_proxy_auth=("a", "b")), + (None, 0, None)) + def testProxyFromEnv(self): os.environ["http_proxy"] = "http://localhost/" - self.assertEqual(_get_proxy_info(False), ("localhost", None, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", None, None)) os.environ["http_proxy"] = "http://localhost:3128/" - self.assertEqual(_get_proxy_info(False), ("localhost", 3128, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None)) os.environ["http_proxy"] = "http://localhost/" os.environ["https_proxy"] = "http://localhost2/" - self.assertEqual(_get_proxy_info(False), ("localhost", None, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", None, None)) os.environ["http_proxy"] = "http://localhost:3128/" os.environ["https_proxy"] = "http://localhost2:3128/" - self.assertEqual(_get_proxy_info(False), ("localhost", 3128, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None)) os.environ["http_proxy"] = "http://localhost/" os.environ["https_proxy"] = "http://localhost2/" - self.assertEqual(_get_proxy_info(True), ("localhost2", None, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", True), ("localhost2", None, None)) os.environ["http_proxy"] = "http://localhost:3128/" os.environ["https_proxy"] = "http://localhost2:3128/" - self.assertEqual(_get_proxy_info(True), ("localhost2", 3128, None)) + self.assertEqual(_get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, None)) os.environ["http_proxy"] = "http://a:b@localhost/" - self.assertEqual(_get_proxy_info(False), ("localhost", None, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b"))) os.environ["http_proxy"] = "http://a:b@localhost:3128/" - self.assertEqual(_get_proxy_info(False), ("localhost", 3128, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b"))) os.environ["http_proxy"] = "http://a:b@localhost/" os.environ["https_proxy"] = "http://a:b@localhost2/" - self.assertEqual(_get_proxy_info(False), ("localhost", None, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b"))) os.environ["http_proxy"] = "http://a:b@localhost:3128/" os.environ["https_proxy"] = "http://a:b@localhost2:3128/" - self.assertEqual(_get_proxy_info(False), ("localhost", 3128, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b"))) os.environ["http_proxy"] = "http://a:b@localhost/" os.environ["https_proxy"] = "http://a:b@localhost2/" - self.assertEqual(_get_proxy_info(True), ("localhost2", None, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", True), ("localhost2", None, ("a", "b"))) os.environ["http_proxy"] = "http://a:b@localhost:3128/" os.environ["https_proxy"] = "http://a:b@localhost2:3128/" - self.assertEqual(_get_proxy_info(True), ("localhost2", 3128, ("a", "b"))) + self.assertEqual(_get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, ("a", "b"))) + + os.environ["http_proxy"] = "http://a:b@localhost/" + os.environ["https_proxy"] = "http://a:b@localhost2/" + os.environ["no_proxy"] = "example1.com,example2.com" + self.assertEqual(_get_proxy_info("example.1.com", True), ("localhost2", None, ("a", "b"))) + os.environ["http_proxy"] = "http://a:b@localhost:3128/" + os.environ["https_proxy"] = "http://a:b@localhost2:3128/" + os.environ["no_proxy"] = "example1.com,example2.com, echo.websocket.org" + self.assertEqual(_get_proxy_info("echo.websocket.org", True), (None, 0, None)) + +