Merge pull request #1491 from croneter/update-websockets
Update websocket client to 0.59.0. Fix threading issues and AttributeErrors
This commit is contained in:
commit
166b94c4cd
20 changed files with 741 additions and 335 deletions
|
@ -25,4 +25,4 @@ from ._exceptions import *
|
|||
from ._logging import *
|
||||
from ._socket import *
|
||||
|
||||
__version__ = "0.58.0"
|
||||
__version__ = "0.59.0"
|
||||
|
|
|
@ -228,9 +228,9 @@ class ABNF(object):
|
|||
if length >= ABNF.LENGTH_63:
|
||||
raise ValueError("data is too long")
|
||||
|
||||
frame_header = chr(self.fin << 7
|
||||
| self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4
|
||||
| self.opcode)
|
||||
frame_header = chr(self.fin << 7 |
|
||||
self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4 |
|
||||
self.opcode)
|
||||
if length < ABNF.LENGTH_7:
|
||||
frame_header += chr(self.mask << 7 | length)
|
||||
frame_header = six.b(frame_header)
|
||||
|
|
|
@ -39,6 +39,7 @@ from . import _logging
|
|||
|
||||
__all__ = ["WebSocketApp"]
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
"""
|
||||
Dispatcher
|
||||
|
@ -56,6 +57,7 @@ class Dispatcher:
|
|||
break
|
||||
check_callback()
|
||||
|
||||
|
||||
class SSLDispatcher:
|
||||
"""
|
||||
SSLDispatcher
|
||||
|
@ -190,23 +192,25 @@ class WebSocketApp(object):
|
|||
self.sock.close(**kwargs)
|
||||
self.sock = None
|
||||
|
||||
def _send_ping(self, interval, event):
|
||||
def _send_ping(self, interval, event, payload):
|
||||
while not event.wait(interval):
|
||||
self.last_ping_tm = time.time()
|
||||
if self.sock:
|
||||
try:
|
||||
self.sock.ping()
|
||||
self.sock.ping(payload)
|
||||
except Exception as ex:
|
||||
_logging.warning("send_ping routine terminated: {}".format(ex))
|
||||
break
|
||||
|
||||
def run_forever(self, sockopt=None, sslopt=None,
|
||||
ping_interval=0, ping_timeout=None,
|
||||
ping_payload="",
|
||||
http_proxy_host=None, http_proxy_port=None,
|
||||
http_no_proxy=None, http_proxy_auth=None,
|
||||
skip_utf8_validation=False,
|
||||
host=None, origin=None, dispatcher=None,
|
||||
suppress_origin=False, proxy_type=None):
|
||||
suppress_origin=False, proxy_type=None,
|
||||
enable_multithread=True):
|
||||
"""
|
||||
Run event loop for WebSocket framework.
|
||||
|
||||
|
@ -226,6 +230,8 @@ class WebSocketApp(object):
|
|||
if set to 0, not send automatically.
|
||||
ping_timeout: int or float
|
||||
timeout (in seconds) if the pong message is not received.
|
||||
ping_payload: str
|
||||
payload message to send with each ping.
|
||||
http_proxy_host: <type>
|
||||
http proxy host name.
|
||||
http_proxy_port: <type>
|
||||
|
@ -287,7 +293,7 @@ class WebSocketApp(object):
|
|||
self.get_mask_key, sockopt=sockopt, sslopt=sslopt,
|
||||
fire_cont_frame=self.on_cont_message is not None,
|
||||
skip_utf8_validation=skip_utf8_validation,
|
||||
enable_multithread=True if ping_interval else False)
|
||||
enable_multithread=enable_multithread)
|
||||
self.sock.settimeout(getdefaulttimeout())
|
||||
self.sock.connect(
|
||||
self.url, header=self.header, cookie=self.cookie,
|
||||
|
@ -304,8 +310,8 @@ class WebSocketApp(object):
|
|||
if ping_interval:
|
||||
event = threading.Event()
|
||||
thread = threading.Thread(
|
||||
target=self._send_ping, args=(ping_interval, event))
|
||||
thread.setDaemon(True)
|
||||
target=self._send_ping, args=(ping_interval, event, ping_payload))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
def read():
|
||||
|
@ -340,9 +346,9 @@ class WebSocketApp(object):
|
|||
has_pong_not_arrived_after_last_ping = self.last_pong_tm - self.last_ping_tm < 0
|
||||
has_pong_arrived_too_late = self.last_pong_tm - self.last_ping_tm > ping_timeout
|
||||
|
||||
if (self.last_ping_tm
|
||||
and has_timeout_expired
|
||||
and (has_pong_not_arrived_after_last_ping or has_pong_arrived_too_late)):
|
||||
if (self.last_ping_tm and
|
||||
has_timeout_expired and
|
||||
(has_pong_not_arrived_after_last_ping or has_pong_arrived_too_late)):
|
||||
raise WebSocketTimeoutException("ping/pong timed out")
|
||||
return True
|
||||
|
||||
|
|
|
@ -72,5 +72,7 @@ class SimpleCookieJar(object):
|
|||
if host.endswith(domain) or host == domain[1:]:
|
||||
cookies.append(self.jar.get(domain))
|
||||
|
||||
return "; ".join(filter(None, ["%s=%s" % (k, v.value) for cookie in filter(None, sorted(cookies)) for k, v in
|
||||
sorted(cookie.items())]))
|
||||
return "; ".join(filter(
|
||||
None, sorted(
|
||||
["%s=%s" % (k, v.value) for cookie in filter(None, cookies) for k, v in cookie.items()]
|
||||
)))
|
||||
|
|
|
@ -44,6 +44,7 @@ from ._utils import *
|
|||
|
||||
__all__ = ['WebSocket', 'create_connection']
|
||||
|
||||
|
||||
class WebSocket(object):
|
||||
"""
|
||||
Low level WebSocket interface.
|
||||
|
@ -466,8 +467,7 @@ class WebSocket(object):
|
|||
|
||||
try:
|
||||
self.connected = False
|
||||
self.send(struct.pack('!H', status) +
|
||||
reason, ABNF.OPCODE_CLOSE)
|
||||
self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
|
||||
sock_timeout = self.sock.gettimeout()
|
||||
self.sock.settimeout(timeout)
|
||||
start_time = time.time()
|
||||
|
|
|
@ -23,6 +23,7 @@ Copyright (C) 2010 Hiroki Ohtani(liris)
|
|||
|
||||
"""
|
||||
|
||||
|
||||
class WebSocketException(Exception):
|
||||
"""
|
||||
WebSocket exception class.
|
||||
|
|
|
@ -93,6 +93,7 @@ def _pack_hostname(hostname):
|
|||
|
||||
return hostname
|
||||
|
||||
|
||||
def _get_handshake_headers(resource, host, port, options):
|
||||
headers = [
|
||||
"GET %s HTTP/1.1" % resource,
|
||||
|
@ -116,16 +117,16 @@ def _get_handshake_headers(resource, host, port, options):
|
|||
key = _create_sec_websocket_key()
|
||||
|
||||
# Append Sec-WebSocket-Key & Sec-WebSocket-Version if not manually specified
|
||||
if not 'header' in options or 'Sec-WebSocket-Key' not in options['header']:
|
||||
if 'header' not in options or 'Sec-WebSocket-Key' not in options['header']:
|
||||
key = _create_sec_websocket_key()
|
||||
headers.append("Sec-WebSocket-Key: %s" % key)
|
||||
else:
|
||||
key = options['header']['Sec-WebSocket-Key']
|
||||
|
||||
if not 'header' in options or 'Sec-WebSocket-Version' not in options['header']:
|
||||
if 'header' not 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:
|
||||
if 'connection' not in options or options['connection'] is None:
|
||||
headers.append('Connection: Upgrade')
|
||||
else:
|
||||
headers.append(options['connection'])
|
||||
|
@ -177,8 +178,8 @@ def _validate(headers, key, subprotocols):
|
|||
r = headers.get(k, None)
|
||||
if not r:
|
||||
return False, None
|
||||
r = r.lower()
|
||||
if v != r:
|
||||
r = [x.strip().lower() for x in r.split(',')]
|
||||
if v not in r:
|
||||
return False, None
|
||||
|
||||
if subprotocols:
|
||||
|
|
|
@ -47,6 +47,7 @@ except:
|
|||
pass
|
||||
HAS_PYSOCKS = False
|
||||
|
||||
|
||||
class proxy_info(object):
|
||||
|
||||
def __init__(self, **options):
|
||||
|
@ -81,14 +82,14 @@ def _open_proxied_socket(url, options, proxy):
|
|||
|
||||
sock = socks.create_connection(
|
||||
(hostname, port),
|
||||
proxy_type = ptype,
|
||||
proxy_addr = proxy.host,
|
||||
proxy_port = proxy.port,
|
||||
proxy_rdns = rdns,
|
||||
proxy_username = proxy.auth[0] if proxy.auth else None,
|
||||
proxy_password = proxy.auth[1] if proxy.auth else None,
|
||||
timeout = options.timeout,
|
||||
socket_options = DEFAULT_SOCKET_OPTION + options.sockopt
|
||||
proxy_type=ptype,
|
||||
proxy_addr=proxy.host,
|
||||
proxy_port=proxy.port,
|
||||
proxy_rdns=rdns,
|
||||
proxy_username=proxy.auth[0] if proxy.auth else None,
|
||||
proxy_password=proxy.auth[1] if proxy.auth else None,
|
||||
timeout=options.timeout,
|
||||
socket_options=DEFAULT_SOCKET_OPTION + options.sockopt
|
||||
)
|
||||
|
||||
if is_secure:
|
||||
|
@ -273,7 +274,9 @@ def _ssl_socket(sock, user_sslopt, hostname):
|
|||
|
||||
def _tunnel(sock, host, port, auth):
|
||||
debug("Connecting proxy...")
|
||||
connect_header = "CONNECT %s:%d HTTP/1.0\r\n" % (host, port)
|
||||
connect_header = "CONNECT %s:%d HTTP/1.1\r\n" % (host, port)
|
||||
connect_header += "Host: %s:%d\r\n" % (host, port)
|
||||
|
||||
# TODO: support digest auth.
|
||||
if auth and auth[0]:
|
||||
auth_str = auth[0]
|
||||
|
@ -320,6 +323,9 @@ def read_headers(sock):
|
|||
kv = line.split(":", 1)
|
||||
if len(kv) == 2:
|
||||
key, value = kv
|
||||
if key.lower() == "set-cookie" and headers.get("set-cookie"):
|
||||
headers["set-cookie"] = headers.get("set-cookie") + "; " + value.strip()
|
||||
else:
|
||||
headers[key.lower()] = value.strip()
|
||||
else:
|
||||
raise WebSocketException("Invalid header")
|
||||
|
|
|
@ -40,7 +40,7 @@ __all__ = ["enableTrace", "dump", "error", "warning", "debug", "trace",
|
|||
"isEnabledForError", "isEnabledForDebug", "isEnabledForTrace"]
|
||||
|
||||
|
||||
def enableTrace(traceable, handler = logging.StreamHandler()):
|
||||
def enableTrace(traceable, handler=logging.StreamHandler()):
|
||||
"""
|
||||
Turn on/off the traceability.
|
||||
|
||||
|
@ -55,6 +55,7 @@ def enableTrace(traceable, handler = logging.StreamHandler()):
|
|||
_logger.addHandler(handler)
|
||||
_logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def dump(title, message):
|
||||
if _traceEnabled:
|
||||
_logger.debug("--- " + title + " ---")
|
||||
|
@ -86,5 +87,6 @@ def isEnabledForError():
|
|||
def isEnabledForDebug():
|
||||
return _logger.isEnabledFor(logging.DEBUG)
|
||||
|
||||
|
||||
def isEnabledForTrace():
|
||||
return _traceEnabled
|
||||
|
|
|
@ -27,7 +27,6 @@ import select
|
|||
import socket
|
||||
|
||||
import six
|
||||
import sys
|
||||
|
||||
from ._exceptions import *
|
||||
from ._ssl_compat import *
|
||||
|
|
|
@ -48,6 +48,6 @@ except ImportError:
|
|||
class SSLWantWriteError(Exception):
|
||||
pass
|
||||
|
||||
ssl = lambda: None
|
||||
ssl = None
|
||||
|
||||
HAVE_SSL = False
|
||||
|
|
|
@ -47,7 +47,7 @@ def parse_url(url):
|
|||
|
||||
scheme, url = url.split(":", 1)
|
||||
|
||||
parsed = urlparse(url, scheme="ws")
|
||||
parsed = urlparse(url, scheme="http")
|
||||
if parsed.hostname:
|
||||
hostname = parsed.hostname
|
||||
else:
|
||||
|
@ -99,10 +99,12 @@ def _is_subnet_address(hostname):
|
|||
|
||||
|
||||
def _is_address_in_network(ip, net):
|
||||
ipaddr = struct.unpack('I', socket.inet_aton(ip))[0]
|
||||
netaddr, bits = net.split('/')
|
||||
netmask = struct.unpack('I', socket.inet_aton(netaddr))[0] & ((2 << int(bits) - 1) - 1)
|
||||
return ipaddr & netmask == netmask
|
||||
ipaddr = struct.unpack('!I', socket.inet_aton(ip))[0]
|
||||
netaddr, netmask = net.split('/')
|
||||
netaddr = struct.unpack('!I', socket.inet_aton(netaddr))[0]
|
||||
|
||||
netmask = (0xFFFFFFFF << (32 - int(netmask))) & 0xFFFFFFFF
|
||||
return ipaddr & netmask == netaddr
|
||||
|
||||
|
||||
def _is_no_proxy_host(hostname, no_proxy):
|
||||
|
@ -113,11 +115,15 @@ def _is_no_proxy_host(hostname, no_proxy):
|
|||
if not no_proxy:
|
||||
no_proxy = DEFAULT_NO_PROXY_HOST
|
||||
|
||||
if '*' in no_proxy:
|
||||
return True
|
||||
if hostname in no_proxy:
|
||||
return True
|
||||
elif _is_ip_address(hostname):
|
||||
if _is_ip_address(hostname):
|
||||
return any([_is_address_in_network(hostname, subnet) for subnet in no_proxy if _is_subnet_address(subnet)])
|
||||
|
||||
for domain in [domain for domain in no_proxy if domain.startswith('.')]:
|
||||
if hostname.endswith(domain):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
|
6
resources/lib/websocket/tests/data/header03.txt
Normal file
6
resources/lib/websocket/tests/data/header03.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
HTTP/1.1 101 WebSocket Protocol Handshake
|
||||
Connection: Upgrade, Keep-Alive
|
||||
Upgrade: WebSocket
|
||||
Sec-WebSocket-Accept: Kxep+hNu9n51529fGidYu7a3wO0=
|
||||
some_header: something
|
||||
|
77
resources/lib/websocket/tests/test_abnf.py
Normal file
77
resources/lib/websocket/tests/test_abnf.py
Normal file
|
@ -0,0 +1,77 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
"""
|
||||
websocket - WebSocket client library for Python
|
||||
|
||||
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import websocket as ws
|
||||
from websocket._abnf import *
|
||||
import sys
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
|
||||
class ABNFTest(unittest.TestCase):
|
||||
|
||||
def testInit(self):
|
||||
a = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||
self.assertEqual(a.fin, 0)
|
||||
self.assertEqual(a.rsv1, 0)
|
||||
self.assertEqual(a.rsv2, 0)
|
||||
self.assertEqual(a.rsv3, 0)
|
||||
self.assertEqual(a.opcode, 9)
|
||||
self.assertEqual(a.data, '')
|
||||
a_bad = ABNF(0,1,0,0, opcode=77)
|
||||
self.assertEqual(a_bad.rsv1, 1)
|
||||
self.assertEqual(a_bad.opcode, 77)
|
||||
|
||||
def testValidate(self):
|
||||
a = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||
self.assertRaises(ws.WebSocketProtocolException, a.validate)
|
||||
a_bad = ABNF(0,1,0,0, opcode=77)
|
||||
self.assertRaises(ws.WebSocketProtocolException, a_bad.validate)
|
||||
a_close = ABNF(0,1,0,0, opcode=ABNF.OPCODE_CLOSE, data="abcdefgh1234567890abcdefgh1234567890abcdefgh1234567890abcdefgh1234567890")
|
||||
self.assertRaises(ws.WebSocketProtocolException, a_close.validate)
|
||||
|
||||
# This caused an error in the Python 2.7 Github Actions build
|
||||
# Uncomment test case when Python 2 support no longer wanted
|
||||
# def testMask(self):
|
||||
# ab = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||
# bytes_val = bytes("aaaa", 'utf-8')
|
||||
# self.assertEqual(ab._get_masked(bytes_val), bytes_val)
|
||||
|
||||
def testFrameBuffer(self):
|
||||
fb = frame_buffer(0, True)
|
||||
self.assertEqual(fb.recv, 0)
|
||||
self.assertEqual(fb.skip_utf8_validation, True)
|
||||
fb.clear
|
||||
self.assertEqual(fb.header, None)
|
||||
self.assertEqual(fb.length, None)
|
||||
self.assertEqual(fb.mask, None)
|
||||
self.assertEqual(fb.has_mask(), False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
137
resources/lib/websocket/tests/test_app.py
Normal file
137
resources/lib/websocket/tests/test_app.py
Normal file
|
@ -0,0 +1,137 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
"""
|
||||
websocket - WebSocket client library for Python
|
||||
|
||||
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import websocket as ws
|
||||
import sys
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
try:
|
||||
import ssl
|
||||
except ImportError:
|
||||
HAVE_SSL = False
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
# Skip test to access the internet.
|
||||
TEST_WITH_INTERNET = os.environ.get('TEST_WITH_INTERNET', '0') == '1'
|
||||
TRACEABLE = True
|
||||
|
||||
|
||||
class WebSocketAppTest(unittest.TestCase):
|
||||
|
||||
class NotSetYet(object):
|
||||
""" A marker class for signalling that a value hasn't been set yet.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
ws.enableTrace(TRACEABLE)
|
||||
|
||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||
|
||||
def tearDown(self):
|
||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testKeepRunning(self):
|
||||
""" A WebSocketApp should keep running as long as its self.keep_running
|
||||
is not False (in the boolean context).
|
||||
"""
|
||||
|
||||
def on_open(self, *args, **kwargs):
|
||||
""" Set the keep_running flag for later inspection and immediately
|
||||
close the connection.
|
||||
"""
|
||||
WebSocketAppTest.keep_running_open = self.keep_running
|
||||
|
||||
self.close()
|
||||
|
||||
def on_close(self, *args, **kwargs):
|
||||
""" Set the keep_running flag for the test to use.
|
||||
"""
|
||||
WebSocketAppTest.keep_running_close = self.keep_running
|
||||
|
||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, on_close=on_close)
|
||||
app.run_forever()
|
||||
|
||||
# if numpy is installed, this assertion fail
|
||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_open,
|
||||
# WebSocketAppTest.NotSetYet))
|
||||
|
||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_close,
|
||||
# WebSocketAppTest.NotSetYet))
|
||||
|
||||
# self.assertEqual(True, WebSocketAppTest.keep_running_open)
|
||||
# self.assertEqual(False, WebSocketAppTest.keep_running_close)
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testSockMaskKey(self):
|
||||
""" A WebSocketApp should forward the received mask_key function down
|
||||
to the actual socket.
|
||||
"""
|
||||
|
||||
def my_mask_key_func():
|
||||
pass
|
||||
|
||||
def on_open(self, *args, **kwargs):
|
||||
""" Set the value so the test can use it later on and immediately
|
||||
close the connection.
|
||||
"""
|
||||
WebSocketAppTest.get_mask_key_id = id(self.get_mask_key)
|
||||
self.close()
|
||||
|
||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, get_mask_key=my_mask_key_func)
|
||||
app.run_forever()
|
||||
|
||||
# if numpy is installed, this assertion fail
|
||||
# Note: We can't use 'is' for comparing the functions directly, need to use 'id'.
|
||||
# self.assertEqual(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func))
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testPingInterval(self):
|
||||
""" A WebSocketApp should ping regularly
|
||||
"""
|
||||
|
||||
def on_ping(app, msg):
|
||||
print("Got a ping!")
|
||||
app.close()
|
||||
|
||||
def on_pong(app, msg):
|
||||
print("Got a pong! No need to respond")
|
||||
app.close()
|
||||
|
||||
app = ws.WebSocketApp('wss://api-pub.bitfinex.com/ws/1', on_ping=on_ping, on_pong=on_pong)
|
||||
app.run_forever(ping_interval=2, ping_timeout=1) # , sslopt={"cert_reqs": ssl.CERT_NONE}
|
||||
self.assertRaises(ws.WebSocketException, app.run_forever, ping_interval=2, ping_timeout=3, sslopt={"cert_reqs": ssl.CERT_NONE})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -26,11 +26,6 @@ import unittest
|
|||
|
||||
from websocket._cookiejar import SimpleCookieJar
|
||||
|
||||
try:
|
||||
import Cookie
|
||||
except:
|
||||
import http.cookies as Cookie
|
||||
|
||||
|
||||
class CookieJarTest(unittest.TestCase):
|
||||
def testAdd(self):
|
||||
|
|
109
resources/lib/websocket/tests/test_http.py
Normal file
109
resources/lib/websocket/tests/test_http.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
"""
|
||||
websocket - WebSocket client library for Python
|
||||
|
||||
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import websocket as ws
|
||||
from websocket._http import proxy_info, read_headers, _open_proxied_socket, _tunnel
|
||||
import sys
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
|
||||
|
||||
class SockMock(object):
|
||||
def __init__(self):
|
||||
self.data = []
|
||||
self.sent = []
|
||||
|
||||
def add_packet(self, data):
|
||||
self.data.append(data)
|
||||
|
||||
def gettimeout(self):
|
||||
return None
|
||||
|
||||
def recv(self, bufsize):
|
||||
if self.data:
|
||||
e = self.data.pop(0)
|
||||
if isinstance(e, Exception):
|
||||
raise e
|
||||
if len(e) > bufsize:
|
||||
self.data.insert(0, e[bufsize:])
|
||||
return e[:bufsize]
|
||||
|
||||
def send(self, data):
|
||||
self.sent.append(data)
|
||||
return len(data)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
class HeaderSockMock(SockMock):
|
||||
|
||||
def __init__(self, fname):
|
||||
SockMock.__init__(self)
|
||||
path = os.path.join(os.path.dirname(__file__), fname)
|
||||
with open(path, "rb") as f:
|
||||
self.add_packet(f.read())
|
||||
|
||||
|
||||
class OptsList():
|
||||
|
||||
def __init__(self):
|
||||
self.timeout = 0
|
||||
self.sockopt = []
|
||||
|
||||
|
||||
class HttpTest(unittest.TestCase):
|
||||
|
||||
def testReadHeader(self):
|
||||
status, header, status_message = read_headers(HeaderSockMock("data/header01.txt"))
|
||||
self.assertEqual(status, 101)
|
||||
self.assertEqual(header["connection"], "Upgrade")
|
||||
# header02.txt is intentionally malformed
|
||||
self.assertRaises(ws.WebSocketException, read_headers, HeaderSockMock("data/header02.txt"))
|
||||
|
||||
def testTunnel(self):
|
||||
self.assertRaises(ws.WebSocketProxyException, _tunnel, HeaderSockMock("data/header01.txt"), "example.com", 80, ("username", "password"))
|
||||
self.assertRaises(ws.WebSocketProxyException, _tunnel, HeaderSockMock("data/header02.txt"), "example.com", 80, ("username", "password"))
|
||||
|
||||
def testConnect(self):
|
||||
# Not currently testing an actual proxy connection, so just check whether TypeError is raised
|
||||
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="http"))
|
||||
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="socks4"))
|
||||
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="socks5h"))
|
||||
|
||||
def testProxyInfo(self):
|
||||
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").type, "http")
|
||||
self.assertRaises(ValueError, proxy_info, http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="badval")
|
||||
self.assertEqual(proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="http").host, "example.com")
|
||||
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").port, "8080")
|
||||
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").auth, None)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
309
resources/lib/websocket/tests/test_url.py
Normal file
309
resources/lib/websocket/tests/test_url.py
Normal file
|
@ -0,0 +1,309 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
"""
|
||||
websocket - WebSocket client library for Python
|
||||
|
||||
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from websocket._url import get_proxy_info, parse_url, _is_address_in_network, _is_no_proxy_host
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
|
||||
class UrlTest(unittest.TestCase):
|
||||
|
||||
def test_address_in_network(self):
|
||||
self.assertTrue(_is_address_in_network('127.0.0.1', '127.0.0.0/8'))
|
||||
self.assertTrue(_is_address_in_network('127.1.0.1', '127.0.0.0/8'))
|
||||
self.assertFalse(_is_address_in_network('127.1.0.1', '127.0.0.0/24'))
|
||||
|
||||
def testParseUrl(self):
|
||||
p = parse_url("ws://www.example.com/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com/r/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("wss://www.example.com:8080/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
p = parse_url("wss://www.example.com:8080/r?key=value")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r?key=value")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
self.assertRaises(ValueError, parse_url, "http://www.example.com/r")
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
return
|
||||
|
||||
p = parse_url("ws://[2a03:4000:123:83::3]/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://[2a03:4000:123:83::3]:8080/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("wss://[2a03:4000:123:83::3]/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 443)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
p = parse_url("wss://[2a03:4000:123:83::3]:8080/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
|
||||
class IsNoProxyHostTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.no_proxy = os.environ.get("no_proxy", None)
|
||||
if "no_proxy" in os.environ:
|
||||
del os.environ["no_proxy"]
|
||||
|
||||
def tearDown(self):
|
||||
if self.no_proxy:
|
||||
os.environ["no_proxy"] = self.no_proxy
|
||||
elif "no_proxy" in os.environ:
|
||||
del os.environ["no_proxy"]
|
||||
|
||||
def testMatchAll(self):
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['*']))
|
||||
self.assertTrue(_is_no_proxy_host("192.168.0.1", ['*']))
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['other.websocket.org', '*']))
|
||||
os.environ['no_proxy'] = '*'
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||
self.assertTrue(_is_no_proxy_host("192.168.0.1", None))
|
||||
os.environ['no_proxy'] = 'other.websocket.org, *'
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||
|
||||
def testIpAddress(self):
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['127.0.0.1']))
|
||||
self.assertFalse(_is_no_proxy_host("127.0.0.2", ['127.0.0.1']))
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['other.websocket.org', '127.0.0.1']))
|
||||
self.assertFalse(_is_no_proxy_host("127.0.0.2", ['other.websocket.org', '127.0.0.1']))
|
||||
os.environ['no_proxy'] = '127.0.0.1'
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||
self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
|
||||
os.environ['no_proxy'] = 'other.websocket.org, 127.0.0.1'
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||
self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
|
||||
|
||||
def testIpAddressInRange(self):
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['127.0.0.0/8']))
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.2", ['127.0.0.0/8']))
|
||||
self.assertFalse(_is_no_proxy_host("127.1.0.1", ['127.0.0.0/24']))
|
||||
os.environ['no_proxy'] = '127.0.0.0/8'
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||
self.assertTrue(_is_no_proxy_host("127.0.0.2", None))
|
||||
os.environ['no_proxy'] = '127.0.0.0/24'
|
||||
self.assertFalse(_is_no_proxy_host("127.1.0.1", None))
|
||||
|
||||
def testHostnameMatch(self):
|
||||
self.assertTrue(_is_no_proxy_host("my.websocket.org", ['my.websocket.org']))
|
||||
self.assertTrue(_is_no_proxy_host("my.websocket.org", ['other.websocket.org', 'my.websocket.org']))
|
||||
self.assertFalse(_is_no_proxy_host("my.websocket.org", ['other.websocket.org']))
|
||||
os.environ['no_proxy'] = 'my.websocket.org'
|
||||
self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
|
||||
self.assertFalse(_is_no_proxy_host("other.websocket.org", None))
|
||||
os.environ['no_proxy'] = 'other.websocket.org, my.websocket.org'
|
||||
self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
|
||||
|
||||
def testHostnameMatchDomain(self):
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['.websocket.org']))
|
||||
self.assertTrue(_is_no_proxy_host("my.other.websocket.org", ['.websocket.org']))
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['my.websocket.org', '.websocket.org']))
|
||||
self.assertFalse(_is_no_proxy_host("any.websocket.com", ['.websocket.org']))
|
||||
os.environ['no_proxy'] = '.websocket.org'
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||
self.assertTrue(_is_no_proxy_host("my.other.websocket.org", None))
|
||||
self.assertFalse(_is_no_proxy_host("any.websocket.com", None))
|
||||
os.environ['no_proxy'] = 'my.websocket.org, .websocket.org'
|
||||
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||
|
||||
|
||||
class ProxyInfoTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.http_proxy = os.environ.get("http_proxy", None)
|
||||
self.https_proxy = os.environ.get("https_proxy", None)
|
||||
self.no_proxy = os.environ.get("no_proxy", None)
|
||||
if "http_proxy" in os.environ:
|
||||
del os.environ["http_proxy"]
|
||||
if "https_proxy" in os.environ:
|
||||
del os.environ["https_proxy"]
|
||||
if "no_proxy" in os.environ:
|
||||
del os.environ["no_proxy"]
|
||||
|
||||
def tearDown(self):
|
||||
if self.http_proxy:
|
||||
os.environ["http_proxy"] = self.http_proxy
|
||||
elif "http_proxy" in os.environ:
|
||||
del os.environ["http_proxy"]
|
||||
|
||||
if self.https_proxy:
|
||||
os.environ["https_proxy"] = self.https_proxy
|
||||
elif "https_proxy" in os.environ:
|
||||
del os.environ["https_proxy"]
|
||||
|
||||
if self.no_proxy:
|
||||
os.environ["no_proxy"] = self.no_proxy
|
||||
elif "no_proxy" in os.environ:
|
||||
del os.environ["no_proxy"]
|
||||
|
||||
def testProxyFromArgs(self):
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost"), ("localhost", 0, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128),
|
||||
("localhost", 3128, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost"), ("localhost", 0, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128),
|
||||
("localhost", 3128, None))
|
||||
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||
("localhost", 0, ("a", "b")))
|
||||
self.assertEqual(
|
||||
get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||
("localhost", 0, ("a", "b")))
|
||||
self.assertEqual(
|
||||
get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128,
|
||||
no_proxy=["example.com"], proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128,
|
||||
no_proxy=["echo.websocket.org"], proxy_auth=("a", "b")),
|
||||
(None, 0, None))
|
||||
|
||||
def testProxyFromEnv(self):
|
||||
os.environ["http_proxy"] = "http://localhost/"
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
||||
os.environ["http_proxy"] = "http://localhost:3128/"
|
||||
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("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("echo.websocket.org", False), ("localhost", 3128, None))
|
||||
|
||||
os.environ["http_proxy"] = "http://localhost/"
|
||||
os.environ["https_proxy"] = "http://localhost2/"
|
||||
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("echo.websocket.org", True), ("localhost2", 3128, None))
|
||||
|
||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||
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("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("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("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("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("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))
|
||||
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, .websocket.org"
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), (None, 0, None))
|
||||
|
||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||
os.environ["no_proxy"] = "127.0.0.0/8, 192.168.0.0/16"
|
||||
self.assertEqual(get_proxy_info("127.0.0.1", False), (None, 0, None))
|
||||
self.assertEqual(get_proxy_info("192.168.1.1", False), (None, 0, None))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -39,7 +39,6 @@ import websocket as ws
|
|||
from websocket._handshake import _create_sec_websocket_key, \
|
||||
_validate as _validate_header
|
||||
from websocket._http import read_headers
|
||||
from websocket._url import get_proxy_info, parse_url
|
||||
from websocket._utils import validate_utf8
|
||||
|
||||
if six.PY3:
|
||||
|
@ -61,9 +60,6 @@ except ImportError:
|
|||
|
||||
# Skip test to access the internet.
|
||||
TEST_WITH_INTERNET = os.environ.get('TEST_WITH_INTERNET', '0') == '1'
|
||||
|
||||
# Skip Secure WebSocket test.
|
||||
TEST_SECURE_WS = True
|
||||
TRACEABLE = True
|
||||
|
||||
|
||||
|
@ -121,102 +117,24 @@ class WebSocketTest(unittest.TestCase):
|
|||
self.assertEqual(ws.getdefaulttimeout(), 10)
|
||||
ws.setdefaulttimeout(None)
|
||||
|
||||
def testParseUrl(self):
|
||||
p = parse_url("ws://www.example.com/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com/r/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080/")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://www.example.com:8080")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("wss://www.example.com:8080/r")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
p = parse_url("wss://www.example.com:8080/r?key=value")
|
||||
self.assertEqual(p[0], "www.example.com")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r?key=value")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
self.assertRaises(ValueError, parse_url, "http://www.example.com/r")
|
||||
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||
return
|
||||
|
||||
p = parse_url("ws://[2a03:4000:123:83::3]/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 80)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("ws://[2a03:4000:123:83::3]:8080/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], False)
|
||||
|
||||
p = parse_url("wss://[2a03:4000:123:83::3]/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 443)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
p = parse_url("wss://[2a03:4000:123:83::3]:8080/r")
|
||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||
self.assertEqual(p[1], 8080)
|
||||
self.assertEqual(p[2], "/r")
|
||||
self.assertEqual(p[3], True)
|
||||
|
||||
def testWSKey(self):
|
||||
key = _create_sec_websocket_key()
|
||||
self.assertTrue(key != 24)
|
||||
self.assertTrue(six.u("¥n") not in key)
|
||||
|
||||
def testNonce(self):
|
||||
""" WebSocket key should be a random 16-byte nonce.
|
||||
"""
|
||||
key = _create_sec_websocket_key()
|
||||
nonce = base64decode(key.encode("utf-8"))
|
||||
self.assertEqual(16, len(nonce))
|
||||
|
||||
def testWsUtils(self):
|
||||
key = "c6b8hTg4EeGb2gQMztV1/g=="
|
||||
required_header = {
|
||||
"upgrade": "websocket",
|
||||
"connection": "upgrade",
|
||||
"sec-websocket-accept": "Kxep+hNu9n51529fGidYu7a3wO0=",
|
||||
}
|
||||
"sec-websocket-accept": "Kxep+hNu9n51529fGidYu7a3wO0="}
|
||||
self.assertEqual(_validate_header(required_header, key, None), (True, None))
|
||||
|
||||
header = required_header.copy()
|
||||
|
@ -254,6 +172,10 @@ class WebSocketTest(unittest.TestCase):
|
|||
self.assertEqual(status, 101)
|
||||
self.assertEqual(header["connection"], "Upgrade")
|
||||
|
||||
status, header, status_message = read_headers(HeaderSockMock("data/header03.txt"))
|
||||
self.assertEqual(status, 101)
|
||||
self.assertEqual(header["connection"], "Upgrade, Keep-Alive")
|
||||
|
||||
HeaderSockMock("data/header02.txt")
|
||||
self.assertRaises(ws.WebSocketException, read_headers, HeaderSockMock("data/header02.txt"))
|
||||
|
||||
|
@ -271,7 +193,10 @@ class WebSocketTest(unittest.TestCase):
|
|||
sock.send(u"こんにちは")
|
||||
self.assertEqual(s.sent[1], six.b("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc"))
|
||||
|
||||
sock.send("x" * 127)
|
||||
# sock.send("x" * 5000)
|
||||
# self.assertEqual(s.sent[1], six.b("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc"))
|
||||
|
||||
self.assertEqual(sock.send_binary(b'1111111111101'), 19)
|
||||
|
||||
def testRecv(self):
|
||||
# TODO: add longer frame data
|
||||
|
@ -444,6 +369,7 @@ class WebSocketTest(unittest.TestCase):
|
|||
s.send(u"こにゃにゃちは、世界")
|
||||
result = s.recv()
|
||||
self.assertEqual(result, "こにゃにゃちは、世界")
|
||||
self.assertRaises(ValueError, s.send_close, -1, "")
|
||||
s.close()
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
|
@ -455,22 +381,14 @@ class WebSocketTest(unittest.TestCase):
|
|||
s.close()
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
@unittest.skipUnless(TEST_SECURE_WS, "wss://echo.websocket.org doesn't work well.")
|
||||
def testSecureWebSocket(self):
|
||||
if 1:
|
||||
import ssl
|
||||
s = ws.create_connection("wss://echo.websocket.org/")
|
||||
s = ws.create_connection("wss://api.bitfinex.com/ws/2")
|
||||
self.assertNotEqual(s, None)
|
||||
self.assertTrue(isinstance(s.sock, ssl.SSLSocket))
|
||||
s.send("Hello, World")
|
||||
result = s.recv()
|
||||
self.assertEqual(result, "Hello, World")
|
||||
s.send(u"こにゃにゃちは、世界")
|
||||
result = s.recv()
|
||||
self.assertEqual(result, "こにゃにゃちは、世界")
|
||||
self.assertEqual(s.getstatus(), 101)
|
||||
self.assertNotEqual(s.getheaders(), None)
|
||||
s.close()
|
||||
#except:
|
||||
# pass
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testWebSocketWithCustomHeader(self):
|
||||
|
@ -480,6 +398,7 @@ class WebSocketTest(unittest.TestCase):
|
|||
s.send("Hello, World")
|
||||
result = s.recv()
|
||||
self.assertEqual(result, "Hello, World")
|
||||
self.assertRaises(ValueError, s.close, -1, "")
|
||||
s.close()
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
|
@ -490,87 +409,6 @@ class WebSocketTest(unittest.TestCase):
|
|||
self.assertRaises(ws.WebSocketConnectionClosedException, s.send, "Hello")
|
||||
self.assertRaises(ws.WebSocketConnectionClosedException, s.recv)
|
||||
|
||||
def testNonce(self):
|
||||
""" WebSocket key should be a random 16-byte nonce.
|
||||
"""
|
||||
key = _create_sec_websocket_key()
|
||||
nonce = base64decode(key.encode("utf-8"))
|
||||
self.assertEqual(16, len(nonce))
|
||||
|
||||
|
||||
class WebSocketAppTest(unittest.TestCase):
|
||||
|
||||
class NotSetYet(object):
|
||||
""" A marker class for signalling that a value hasn't been set yet.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
ws.enableTrace(TRACEABLE)
|
||||
|
||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||
|
||||
def tearDown(self):
|
||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testKeepRunning(self):
|
||||
""" A WebSocketApp should keep running as long as its self.keep_running
|
||||
is not False (in the boolean context).
|
||||
"""
|
||||
|
||||
def on_open(self, *args, **kwargs):
|
||||
""" Set the keep_running flag for later inspection and immediately
|
||||
close the connection.
|
||||
"""
|
||||
WebSocketAppTest.keep_running_open = self.keep_running
|
||||
|
||||
self.close()
|
||||
|
||||
def on_close(self, *args, **kwargs):
|
||||
""" Set the keep_running flag for the test to use.
|
||||
"""
|
||||
WebSocketAppTest.keep_running_close = self.keep_running
|
||||
|
||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, on_close=on_close)
|
||||
app.run_forever()
|
||||
|
||||
# if numpy is installed, this assertion fail
|
||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_open,
|
||||
# WebSocketAppTest.NotSetYet))
|
||||
|
||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_close,
|
||||
# WebSocketAppTest.NotSetYet))
|
||||
|
||||
# self.assertEqual(True, WebSocketAppTest.keep_running_open)
|
||||
# self.assertEqual(False, WebSocketAppTest.keep_running_close)
|
||||
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
def testSockMaskKey(self):
|
||||
""" A WebSocketApp should forward the received mask_key function down
|
||||
to the actual socket.
|
||||
"""
|
||||
|
||||
def my_mask_key_func():
|
||||
pass
|
||||
|
||||
def on_open(self, *args, **kwargs):
|
||||
""" Set the value so the test can use it later on and immediately
|
||||
close the connection.
|
||||
"""
|
||||
WebSocketAppTest.get_mask_key_id = id(self.get_mask_key)
|
||||
self.close()
|
||||
|
||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, get_mask_key=my_mask_key_func)
|
||||
app.run_forever()
|
||||
|
||||
# if numpu is installed, this assertion fail
|
||||
# Note: We can't use 'is' for comparing the functions directly, need to use 'id'.
|
||||
# self.assertEqual(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func))
|
||||
|
||||
|
||||
class SockOptTest(unittest.TestCase):
|
||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||
|
@ -591,101 +429,5 @@ class UtilsTest(unittest.TestCase):
|
|||
self.assertEqual(state, True)
|
||||
|
||||
|
||||
class ProxyInfoTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.http_proxy = os.environ.get("http_proxy", None)
|
||||
self.https_proxy = os.environ.get("https_proxy", None)
|
||||
if "http_proxy" in os.environ:
|
||||
del os.environ["http_proxy"]
|
||||
if "https_proxy" in os.environ:
|
||||
del os.environ["https_proxy"]
|
||||
|
||||
def tearDown(self):
|
||||
if self.http_proxy:
|
||||
os.environ["http_proxy"] = self.http_proxy
|
||||
elif "http_proxy" in os.environ:
|
||||
del os.environ["http_proxy"]
|
||||
|
||||
if self.https_proxy:
|
||||
os.environ["https_proxy"] = self.https_proxy
|
||||
elif "https_proxy" in os.environ:
|
||||
del os.environ["https_proxy"]
|
||||
|
||||
def testProxyFromArgs(self):
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost"), ("localhost", 0, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128), ("localhost", 3128, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost"), ("localhost", 0, None))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128), ("localhost", 3128, None))
|
||||
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||
("localhost", 0, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||
("localhost", 0, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, no_proxy=["example.com"], proxy_auth=("a", "b")),
|
||||
("localhost", 3128, ("a", "b")))
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, no_proxy=["echo.websocket.org"], proxy_auth=("a", "b")),
|
||||
(None, 0, None))
|
||||
|
||||
def testProxyFromEnv(self):
|
||||
os.environ["http_proxy"] = "http://localhost/"
|
||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
||||
os.environ["http_proxy"] = "http://localhost:3128/"
|
||||
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("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("echo.websocket.org", False), ("localhost", 3128, None))
|
||||
|
||||
os.environ["http_proxy"] = "http://localhost/"
|
||||
os.environ["https_proxy"] = "http://localhost2/"
|
||||
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("echo.websocket.org", True), ("localhost2", 3128, None))
|
||||
|
||||
|
||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||
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("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("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("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("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("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))
|
||||
|
||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||
os.environ["no_proxy"] = "127.0.0.0/8, 192.168.0.0/16"
|
||||
self.assertEqual(get_proxy_info("127.0.0.1", False), (None, 0, None))
|
||||
self.assertEqual(get_proxy_info("192.168.1.1", False), (None, 0, None))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -164,6 +164,14 @@ class PlexWebSocketApp(websocket.WebSocketApp,
|
|||
if self.sleeptime < 6:
|
||||
self.sleeptime += 1
|
||||
|
||||
def close(self, **kwargs):
|
||||
"""websocket.WebSocketApp is not yet thread-safe. close() might
|
||||
encounter websockets that have already been closed"""
|
||||
try:
|
||||
websocket.WebSocketApp.close(self, **kwargs)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def suspend(self, block=False, timeout=None):
|
||||
"""
|
||||
Call this method from another thread to suspend this websocket thread
|
||||
|
|
Loading…
Reference in a new issue