From e7529e54873ca02ba2aa7534e60469863908cd9d Mon Sep 17 00:00:00 2001 From: Roy Hyunjin Han Date: Sun, 17 Nov 2013 13:40:36 -0800 Subject: [PATCH] Replaced secure=True with host='https://example.com' --- CHANGES.rst | 5 ++++ README.rst | 11 ++++---- TODO.goals | 3 +- TODO.log | 4 +++ setup.py | 2 +- socketIO_client/__init__.py | 52 ++++++++++++++++++++++------------- socketIO_client/transports.py | 16 +++++------ 7 files changed, 57 insertions(+), 36 deletions(-) create mode 100644 TODO.log diff --git a/CHANGES.rst b/CHANGES.rst index 5b0b164..41058f9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,8 @@ +0.5.2 +----- +- Replaced secure=True with host='https://example.com' +- Fixed sending heartbeats thanks to Travis Odom + 0.5.1 ----- - Added error handling in the event of websocket timeout diff --git a/README.rst b/README.rst index 227a7a9..22e9215 100644 --- a/README.rst +++ b/README.rst @@ -110,15 +110,13 @@ Define different namespaces on a single socket. :: news_namespace.emit('aaa') socketIO.wait(seconds=1) -Open secure websockets (HTTPS / WSS) behind a proxy. :: +Connect via SSL. :: from socketIO_client import SocketIO - SocketIO('localhost', 8000, - secure=True, - proxies={'https': 'https://proxy.example.com:8080'}) + SocketIO('https://localhost') -Specify params, headers and cookies thanks to the `requests`_ library. :: +Specify params, headers, cookies, proxies thanks to the `requests`_ library. :: from socketIO_client import SocketIO from base64 import b64encode @@ -126,7 +124,8 @@ Specify params, headers and cookies thanks to the `requests`_ library. :: SocketIO('localhost', 8000, params={'q': 'qqq'}, headers={'Authorization': 'Basic ' + b64encode('username:password')}, - cookies={'a': 'aaa'}) + cookies={'a': 'aaa'}, + proxies={'https': 'https://proxy.example.com:8080'}) License diff --git a/TODO.goals b/TODO.goals index 6721fe8..95743f6 100644 --- a/TODO.goals +++ b/TODO.goals @@ -1,2 +1 @@ -# America/Los_Angeles 11/3/2013 -Add test for server ack callback in namespace +# America/Los_Angeles 11/17/2013 \ No newline at end of file diff --git a/TODO.log b/TODO.log new file mode 100644 index 0000000..4da62af --- /dev/null +++ b/TODO.log @@ -0,0 +1,4 @@ +# UTC 11/17/2013 ++ Beware of scheme included in URL [11/17/2013] ++ Add test for server ack callback in namespace [11/17/2013] ++ Set port automatically if it is not automatically specified [11/17/2013] \ No newline at end of file diff --git a/setup.py b/setup.py index 9afabd2..507323d 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ CHANGES = open(os.path.join(here, 'CHANGES.rst')).read() setup( name='socketIO-client', - version='0.5.1', + version='0.5.2', description='A socket.io client library', long_description=README + '\n\n' + CHANGES, license='MIT', diff --git a/socketIO_client/__init__.py b/socketIO_client/__init__.py index efe9103..de37c0e 100644 --- a/socketIO_client/__init__.py +++ b/socketIO_client/__init__.py @@ -3,6 +3,7 @@ import json import requests import time from collections import namedtuple +from urlparse import urlparse from .exceptions import ConnectionError, TimeoutError, PacketError from .transports import _get_response, _negotiate_transport, TRANSPORTS @@ -105,24 +106,26 @@ class BaseNamespace(object): class SocketIO(object): + """Create a socket.io client that connects to a socket.io server + at the specified host and port. + + - Define the behavior of the client by specifying a custom Namespace. + - Prefix host with https:// to use SSL. + - Set wait_for_connection=True to block until we have a connection. + - Specify the transports you want to use. + - Pass query params, headers, cookies, proxies as keyword arguments. + + SocketIO('localhost', 8000, + params={'q': 'qqq'}, + headers={'Authorization': 'Basic ' + b64encode('username:password')}, + cookies={'a': 'aaa'}, + proxies={'https': 'https://proxy.example.com:8080'}) + """ def __init__( - self, host, port, Namespace=BaseNamespace, secure=False, + self, host, port=None, Namespace=BaseNamespace, wait_for_connection=True, transports=TRANSPORTS, **kw): - """ - Create a socket.io client that connects to a socket.io server - at the specified host and port. - - Define the behavior of the client by specifying a custom Namespace. - - Set secure=True to use HTTPS / WSS. - - Set wait_for_connection=True to block until we have a connection. - - List the transports you want to use (%s). - - Pass query params, headers, cookies, proxies as keyword arguments. - - SocketIO('localhost', 8000, proxies={ - 'https': 'https://proxy.example.com:8080'}) - """ % ', '.join(TRANSPORTS) - self.base_url = '%s:%d/socket.io/%s' % (host, port, PROTOCOL_VERSION) - self.secure = secure + self.is_secure, self.base_url = _parse_host(host, port) self.wait_for_connection = wait_for_connection self._namespace_by_path = {} self.client_supported_transports = transports @@ -222,7 +225,7 @@ class SocketIO(object): def _get_transport(self): socketIO_session = _get_socketIO_session( - self.secure, self.base_url, **self.kw) + self.is_secure, self.base_url, **self.kw) _log.debug('[transports available] %s', ' '.join( socketIO_session.server_supported_transports)) # Initialize heartbeat_pacemaker @@ -232,7 +235,7 @@ class SocketIO(object): # Negotiate transport transport = _negotiate_transport( self.client_supported_transports, socketIO_session, - self.secure, self.base_url, **self.kw) + self.is_secure, self.base_url, **self.kw) # Update namespaces for namespace in self._namespace_by_path.values(): namespace._transport = transport @@ -340,6 +343,17 @@ def find_callback(args, kw=None): return None, args +def _parse_host(host, port): + if not host.startswith('http'): + host = 'http://' + host + url_pack = urlparse(host) + is_secure = url_pack.scheme == 'https' + port = port or url_pack.port or (443 if is_secure else 80) + base_url = '%s:%d%s/socket.io/%s' % ( + url_pack.hostname, port, url_pack.path, PROTOCOL_VERSION) + return is_secure, base_url + + def _yield_warning_screen(seconds=None): last_warning = None for elapsed_time in _yield_elapsed_time(seconds): @@ -362,8 +376,8 @@ def _yield_elapsed_time(seconds=None): yield time.time() - start_time -def _get_socketIO_session(secure, base_url, **kw): - server_url = '%s://%s/' % ('https' if secure else 'http', base_url) +def _get_socketIO_session(is_secure, base_url, **kw): + server_url = '%s://%s/' % ('https' if is_secure else 'http', base_url) try: response = _get_response(requests.get, server_url, **kw) except TimeoutError as e: diff --git a/socketIO_client/transports.py b/socketIO_client/transports.py index a3469e5..758f34e 100644 --- a/socketIO_client/transports.py +++ b/socketIO_client/transports.py @@ -104,10 +104,10 @@ class _AbstractTransport(object): class _WebsocketTransport(_AbstractTransport): - def __init__(self, socketIO_session, secure, base_url, **kw): + def __init__(self, socketIO_session, is_secure, base_url, **kw): super(_WebsocketTransport, self).__init__() url = '%s://%s/websocket/%s' % ( - 'wss' if secure else 'ws', + 'wss' if is_secure else 'ws', base_url, socketIO_session.id) try: self._connection = websocket.create_connection(url) @@ -151,10 +151,10 @@ class _WebsocketTransport(_AbstractTransport): class _XHR_PollingTransport(_AbstractTransport): - def __init__(self, socketIO_session, secure, base_url, **kw): + def __init__(self, socketIO_session, is_secure, base_url, **kw): super(_XHR_PollingTransport, self).__init__() self._url = '%s://%s/xhr-polling/%s' % ( - 'https' if secure else 'http', + 'https' if is_secure else 'http', base_url, socketIO_session.id) self._connected = True self._http_session = _prepare_http_session(kw) @@ -203,10 +203,10 @@ class _JSONP_PollingTransport(_AbstractTransport): RESPONSE_PATTERN = re.compile(r'io.j\[(\d+)\]\("(.*)"\);') - def __init__(self, socketIO_session, secure, base_url, **kw): + def __init__(self, socketIO_session, is_secure, base_url, **kw): super(_JSONP_PollingTransport, self).__init__() self._url = '%s://%s/jsonp-polling/%s' % ( - 'https' if secure else 'http', + 'https' if is_secure else 'http', base_url, socketIO_session.id) self._connected = True self._http_session = _prepare_http_session(kw) @@ -264,7 +264,7 @@ class _JSONP_PollingTransport(_AbstractTransport): def _negotiate_transport( client_supported_transports, session, - secure, base_url, **kw): + is_secure, base_url, **kw): server_supported_transports = session.server_supported_transports for supported_transport in client_supported_transports: if supported_transport in server_supported_transports: @@ -273,7 +273,7 @@ def _negotiate_transport( 'websocket': _WebsocketTransport, 'xhr-polling': _XHR_PollingTransport, 'jsonp-polling': _JSONP_PollingTransport, - }[supported_transport](session, secure, base_url, **kw) + }[supported_transport](session, is_secure, base_url, **kw) raise SocketIOError(' '.join([ 'could not negotiate a transport:', 'client supports %s but' % ', '.join(client_supported_transports),