diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | ChangeLog | 4 | ||||
-rwxr-xr-x | bin/wsdump.py | 24 | ||||
-rw-r--r-- | websocket/__init__.py | 2 | ||||
-rw-r--r-- | websocket/_app.py | 8 | ||||
-rw-r--r-- | websocket/_core.py | 3 | ||||
-rw-r--r-- | websocket/_handshake.py | 14 | ||||
-rw-r--r-- | websocket/_http.py | 9 | ||||
-rw-r--r-- | websocket/_logging.py | 6 | ||||
-rw-r--r-- | websocket/_ssl_compat.py | 2 |
10 files changed, 52 insertions, 22 deletions
@@ -9,3 +9,5 @@ dist .cache/ compliance/reports/ +.eggs +.vscode
\ No newline at end of file @@ -1,6 +1,10 @@ ChangeLog ============ +- 0.57.0 + - wsdump: Fix --headers option (#589) + - Fix getting 400 bad request with long proxy authorization string (#587) + - 0.56.0 - Don't retry sockets with timeout set to 0(#536) diff --git a/bin/wsdump.py b/bin/wsdump.py index bc07246..d16d361 100755 --- a/bin/wsdump.py +++ b/bin/wsdump.py @@ -6,6 +6,8 @@ import sys import threading import time import ssl +import gzip +import zlib import six from six.moves.urllib.parse import urlparse @@ -130,7 +132,7 @@ def main(): if args.nocert: opts = {"cert_reqs": ssl.CERT_NONE, "check_hostname": False} if args.headers: - options['header'] = map(str.strip, args.headers.split(',')) + options['header'] = list(map(str.strip, args.headers.split(','))) ws = websocket.create_connection(args.url, sslopt=opts, **options) if args.raw: console = NonInteractive() @@ -162,10 +164,24 @@ def main(): msg = None if six.PY3 and opcode == websocket.ABNF.OPCODE_TEXT and isinstance(data, bytes): data = str(data, "utf-8") - if not args.verbose and opcode in OPCODE_DATA: - msg = data - elif args.verbose: + if isinstance(data, bytes) and len(data)>2 and data[:2] == b'\037\213': # gzip magick + try: + data = "[gzip] " + str(gzip.decompress(data), "utf-8") + except: + pass + elif isinstance(data, bytes): + try: + data = "[zlib] " + str(zlib.decompress(data, -zlib.MAX_WBITS), "utf-8") + except: + pass + + if isinstance(data, bytes): + data = repr(data) + + if args.verbose: msg = "%s: %s" % (websocket.ABNF.OPCODE_MAP.get(opcode), data) + else: + msg = data if msg is not None: if args.timings: diff --git a/websocket/__init__.py b/websocket/__init__.py index 15c74ce..605f76c 100644 --- a/websocket/__init__.py +++ b/websocket/__init__.py @@ -26,4 +26,4 @@ from ._exceptions import * from ._logging import * from ._socket import * -__version__ = "0.56.0" +__version__ = "0.57.0" diff --git a/websocket/_app.py b/websocket/_app.py index 81aa1fc..2710ef8 100644 --- a/websocket/_app.py +++ b/websocket/_app.py @@ -46,7 +46,7 @@ class Dispatcher: self.ping_timeout = ping_timeout def read(self, sock, read_callback, check_callback): - while self.app.sock.connected: + while self.app.keep_running: r, w, e = select.select( (self.app.sock.sock, ), (), (), self.ping_timeout) if r: @@ -54,13 +54,13 @@ class Dispatcher: break check_callback() -class SSLDispacther: +class SSLDispatcher: def __init__(self, app, ping_timeout): self.app = app self.ping_timeout = ping_timeout def read(self, sock, read_callback, check_callback): - while self.app.sock.connected: + while self.app.keep_running: r = self.select() if r: if not read_callback(): @@ -314,7 +314,7 @@ class WebSocketApp(object): def create_dispatcher(self, ping_timeout): timeout = ping_timeout or 10 if self.sock.is_ssl(): - return SSLDispacther(self, timeout) + return SSLDispatcher(self, timeout) return Dispatcher(self, timeout) diff --git a/websocket/_core.py b/websocket/_core.py index 0f914c2..418aafc 100644 --- a/websocket/_core.py +++ b/websocket/_core.py @@ -271,7 +271,8 @@ class WebSocket(object): frame.get_mask_key = self.get_mask_key data = frame.format() length = len(data) - trace("send: " + repr(data)) + if (isEnabledForTrace()): + trace("send: " + repr(data)) with self.lock: while data: diff --git a/websocket/_handshake.py b/websocket/_handshake.py index 809a8c9..4650c55 100644 --- a/websocket/_handshake.py +++ b/websocket/_handshake.py @@ -55,7 +55,8 @@ else: # websocket supported version. VERSION = 13 -SUPPORTED_REDIRECT_STATUSES = [HTTPStatus.MOVED_PERMANENTLY, HTTPStatus.FOUND, HTTPStatus.SEE_OTHER] +SUPPORTED_REDIRECT_STATUSES = (HTTPStatus.MOVED_PERMANENTLY, HTTPStatus.FOUND, HTTPStatus.SEE_OTHER,) +SUCCESS_STATUSES = SUPPORTED_REDIRECT_STATUSES + (HTTPStatus.SWITCHING_PROTOCOLS,) CookieJar = SimpleCookieJar() @@ -95,14 +96,12 @@ def _pack_hostname(hostname): def _get_handshake_headers(resource, host, port, options): headers = [ "GET %s HTTP/1.1" % resource, - "Upgrade: websocket", - "Connection: Upgrade" + "Upgrade: websocket" ] if port == 80 or port == 443: hostport = _pack_hostname(host) else: hostport = "%s:%d" % (_pack_hostname(host), port) - if "host" in options and options["host"] is not None: headers.append("Host: %s" % options["host"]) else: @@ -126,6 +125,11 @@ def _get_handshake_headers(resource, host, port, options): if not 'header' in options or 'Sec-WebSocket-Version' not in options['header']: headers.append("Sec-WebSocket-Version: %s" % VERSION) + if not 'connection' in options or options['connection'] is None: + headers.append('Connection: upgrade') + else: + headers.append(options['connection']) + subprotocols = options.get("subprotocols") if subprotocols: headers.append("Sec-WebSocket-Protocol: %s" % ",".join(subprotocols)) @@ -154,7 +158,7 @@ def _get_handshake_headers(resource, host, port, options): return headers, key -def _get_resp_headers(sock, success_statuses=(101, 301, 302, 303)): +def _get_resp_headers(sock, success_statuses=SUCCESS_STATUSES): status, resp_headers, status_message = read_headers(sock) if status not in success_statuses: raise WebSocketBadStatusException("Handshake status %d %s", status, status_message, resp_headers) diff --git a/websocket/_http.py b/websocket/_http.py index c642c28..29a699c 100644 --- a/websocket/_http.py +++ b/websocket/_http.py @@ -138,16 +138,15 @@ def _get_addrinfo_list(hostname, port, is_secure, proxy): phost, pport, pauth = get_proxy_info( hostname, is_secure, proxy.host, proxy.port, proxy.auth, proxy.no_proxy) try: + # when running on windows 10, getaddrinfo without socktype returns a socktype 0. + # This generates an error exception: `_on_error: exception Socket type must be stream or datagram, not 0` + # or `OSError: [Errno 22] Invalid argument` when creating socket. Force the socket type to SOCK_STREAM. if not phost: addrinfo_list = socket.getaddrinfo( hostname, port, 0, socket.SOCK_STREAM, socket.SOL_TCP) return addrinfo_list, False, None else: pport = pport and pport or 80 - # when running on windows 10, the getaddrinfo used above - # returns a socktype 0. This generates an error exception: - #_on_error: exception Socket type must be stream or datagram, not 0 - # Force the socket type to SOCK_STREAM addrinfo_list = socket.getaddrinfo(phost, pport, 0, socket.SOCK_STREAM, socket.SOL_TCP) return addrinfo_list, True, pauth except socket.gaierror as e: @@ -276,7 +275,7 @@ def _tunnel(sock, host, port, auth): auth_str = auth[0] if auth[1]: auth_str += ":" + auth[1] - encoded_str = base64encode(auth_str.encode()).strip().decode() + encoded_str = base64encode(auth_str.encode()).strip().decode().replace('\n', '') connect_header += "Proxy-Authorization: Basic %s\r\n" % encoded_str connect_header += "\r\n" dump("request header", connect_header) diff --git a/websocket/_logging.py b/websocket/_logging.py index 70a6271..c947778 100644 --- a/websocket/_logging.py +++ b/websocket/_logging.py @@ -34,7 +34,7 @@ _logger.addHandler(NullHandler()) _traceEnabled = False __all__ = ["enableTrace", "dump", "error", "warning", "debug", "trace", - "isEnabledForError", "isEnabledForDebug"] + "isEnabledForError", "isEnabledForDebug", "isEnabledForTrace"] def enableTrace(traceable, handler = logging.StreamHandler()): @@ -49,7 +49,6 @@ def enableTrace(traceable, handler = logging.StreamHandler()): _logger.addHandler(handler) _logger.setLevel(logging.DEBUG) - def dump(title, message): if _traceEnabled: _logger.debug("--- " + title + " ---") @@ -80,3 +79,6 @@ def isEnabledForError(): def isEnabledForDebug(): return _logger.isEnabledFor(logging.DEBUG) + +def isEnabledForTrace(): + return _traceEnabled diff --git a/websocket/_ssl_compat.py b/websocket/_ssl_compat.py index 5b3c413..96cd173 100644 --- a/websocket/_ssl_compat.py +++ b/websocket/_ssl_compat.py @@ -49,4 +49,6 @@ except ImportError: class SSLWantWriteError(Exception): pass + ssl = lambda: None + HAVE_SSL = False |