+2009-10-26 Yuzo Fujishima <yuzo@google.com>
+
+ Reviewed by Eric Seidel.
+
+ Upgrade pywebsocket to 0.4.1. This will make reusing LayoutTests/fast/js/resources easier, for example.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30763
+
+ * pywebsocket/mod_pywebsocket/__init__.py:
+ * pywebsocket/mod_pywebsocket/dispatch.py:
+ * pywebsocket/mod_pywebsocket/headerparserhandler.py:
+ * pywebsocket/mod_pywebsocket/standalone.py:
+ * pywebsocket/setup.py:
+ * pywebsocket/test/test_dispatch.py:
+
2009-10-26 Carol Szabo <carol.szabo@nokia.com>
Reviewed by David Levin.
PythonOption mod_pywebsocket.handler_root <websock_handlers>
PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+ To limit the search for Web Socket handlers to a directory <scan_dir>
+ under <websock_handlers>, configure as follows:
+
+ PythonOption mod_pywebsocket.handler_scan <scan_dir>
+
+ <scan_dir> is useful in saving scan time when <websock_handlers>
+ contains many non-Web Socket handler files.
+
Example snippet of httpd.conf:
(mod_pywebsocket is in /websock_lib, Web Socket handlers are in
/websock_handlers, port is 80 for ws, 443 for wss.)
This class maintains a map from resource name to handlers.
"""
- def __init__(self, root_dir):
+ def __init__(self, root_dir, scan_dir=None):
"""Construct an instance.
Args:
root_dir: The directory where handler definition files are
- placed.
+ placed.
+ scan_dir: The directory where handler definition files are
+ searched. scan_dir must be a directory under root_dir,
+ including root_dir itself. If scan_dir is None, root_dir
+ is used as scan_dir. scan_dir can be useful in saving
+ scan time when root_dir contains many subdirectories.
"""
self._handlers = {}
self._source_warnings = []
- self._source_files_in_dir(root_dir)
+ if scan_dir is None:
+ scan_dir = root_dir
+ if not os.path.abspath(scan_dir).startswith(os.path.abspath(root_dir)):
+ raise DispatchError('scan_dir:%s must be a directory under '
+ 'root_dir:%s.' % (scan_dir, root_dir))
+ self._source_files_in_dir(root_dir, scan_dir)
def source_warnings(self):
"""Return warnings in sourcing handlers."""
except KeyError:
raise DispatchError('No handler for: %r' % request.ws_resource)
- def _source_files_in_dir(self, root_dir):
- """Source all the handler source files in the directory."""
+ def _source_files_in_dir(self, root_dir, scan_dir):
+ """Source all the handler source files in the scan_dir directory.
+
+ The resource path is determined relative to root_dir.
+ """
to_resource = _path_to_resource_converter(root_dir)
- for path in _source_file_paths(root_dir):
+ for path in _source_file_paths(scan_dir):
try:
handlers = _source(open(path).read())
except DispatchError, e:
# PythonOption to specify the handler root directory.
_PYOPT_HANDLER_ROOT = 'mod_pywebsocket.handler_root'
+# PythonOption to specify the handler scan directory.
+# This must be a directory under the root directory.
+# The default is the root directory.
+_PYOPT_HANDLER_SCAN = 'mod_pywebsocket.handler_scan'
+
def _create_dispatcher():
_HANDLER_ROOT = apache.main_server.get_options().get(
if not _HANDLER_ROOT:
raise Exception('PythonOption %s is not defined' % _PYOPT_HANDLER_ROOT,
apache.APLOG_ERR)
- dispatcher = dispatch.Dispatcher(_HANDLER_ROOT)
+ _HANDLER_SCAN = apache.main_server.get_options().get(
+ _PYOPT_HANDLER_SCAN, _HANDLER_ROOT)
+ dispatcher = dispatch.Dispatcher(_HANDLER_ROOT, _HANDLER_SCAN)
for warning in dispatcher.source_warnings():
apache.log_error('mod_pywebsocket: %s' % warning, apache.APLOG_WARNING)
return dispatcher
Usage:
python standalone.py [-p <ws_port>] [-w <websock_handlers>]
+ [-s <scan_dir>]
[-d <document_root>]
<ws_port> is the port number to use for ws:// connection.
See __init__.py for details of <websock_handlers> and how to write Web Socket
handlers. If this path is relative, <document_root> is used as the base.
+<scan_dir> is a path under the root directory. If specified, only the handlers
+under scan_dir are scanned. This is useful in saving scan time.
+
Note:
This server is derived from SocketServer.ThreadingMixIn. Hence a thread is
used for each request.
self._request = _StandaloneRequest(
self, WebSocketRequestHandler.options.use_tls)
self._dispatcher = dispatch.Dispatcher(
- WebSocketRequestHandler.options.websock_handlers)
+ WebSocketRequestHandler.options.websock_handlers,
+ WebSocketRequestHandler.options.scan_dir)
self._print_warnings_if_any()
self._handshaker = handshake.Handshaker(self._request,
self._dispatcher)
parser.add_option('-w', '--websock_handlers', dest='websock_handlers',
default='.',
help='Web Socket handlers root directory.')
+ parser.add_option('-s', '--scan_dir', dest='scan_dir',
+ default=None,
+ help=('Web Socket handlers scan directory. '
+ 'Must be a directory under websock_handlers.'))
parser.add_option('-d', '--document_root', dest='document_root',
default='.',
help='Document root directory.')
'certificate.')
sys.exit(1)
+ if not options.scan_dir:
+ options.scan_dir = options.websock_handlers
+
WebSocketRequestHandler.options = options
WebSocketServer.options = options
name=_PACKAGE_NAME,
packages=[_PACKAGE_NAME],
url='http://code.google.com/p/pywebsocket/',
- version='0.4.0',
+ version='0.4.1',
)
_TEST_HANDLERS_DIR = os.path.join(
os.path.split(__file__)[0], 'testdata', 'handlers')
+_TEST_HANDLERS_SUB_DIR = os.path.join(_TEST_HANDLERS_DIR, 'sub')
+
class DispatcherTest(unittest.TestCase):
def test_normalize_path(self):
self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
'def web_socket_transfer_data(request):pass\n'))
def test_source_warnings(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR)
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
warnings = dispatcher.source_warnings()
warnings.sort()
expected_warnings = [
for expected, actual in zip(expected_warnings, warnings):
self.assertEquals(expected, actual)
- def test_shake_hand(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR)
+ def test_do_extra_handshake(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
request = mock.MockRequest()
request.ws_resource = '/origin_check'
request.ws_origin = 'http://example.com'
dispatcher.do_extra_handshake, request)
def test_transfer_data(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR)
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
request = mock.MockRequest(connection=mock.MockConn(''))
request.ws_resource = '/origin_check'
request.ws_protocol = 'p1'
request.connection.written_data())
def test_transfer_data_no_handler(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR)
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
for resource in ['/blank', '/sub/non_callable',
'/sub/no_wsh_at_the_end', '/does/not/exist']:
request = mock.MockRequest(connection=mock.MockConn(''))
self.fail()
def test_transfer_data_handler_exception(self):
- dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR)
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
request = mock.MockRequest(connection=mock.MockConn(''))
request.ws_resource = '/sub/exception_in_transfer'
request.ws_protocol = 'p3'
except Exception:
self.fail()
+ def test_scan_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ self.assertEqual(3, len(disp._handlers))
+ self.failUnless(disp._handlers.has_key('/origin_check'))
+ self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/sub/plain'))
+
+ def test_scan_sub_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handlers))
+ self.failIf(disp._handlers.has_key('/origin_check'))
+ self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/sub/plain'))
+
+ def test_scan_sub_dir_as_root(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_SUB_DIR,
+ _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handlers))
+ self.failIf(disp._handlers.has_key('/origin_check'))
+ self.failIf(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failIf(disp._handlers.has_key('/sub/plain'))
+ self.failUnless(disp._handlers.has_key('/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/plain'))
+
+ def test_scan_dir_must_under_root(self):
+ dispatch.Dispatcher('a/b', 'a/b/c') # OK
+ dispatch.Dispatcher('a/b///', 'a/b') # OK
+ self.assertRaises(dispatch.DispatchError,
+ dispatch.Dispatcher, 'a/b/c', 'a/b')
+
if __name__ == '__main__':
unittest.main()