def do_extra_handshake(self, request): """Do extra checking in WebSocket handshake. Select a handler based on request.uri and call its web_socket_do_extra_handshake function. Args: request: mod_python request. Raises: DispatchException: when handler was not found AbortedByUserException: when user handler abort connection HandshakeException: when opening handshake failed """ handler_suite = self.get_handler_suite(request.ws_resource) if handler_suite is None: raise DispatchException('No handler for: %r' % request.ws_resource) do_extra_handshake_ = handler_suite.do_extra_handshake try: do_extra_handshake_(request) except handshake.AbortedByUserException as e: # Re-raise to tell the caller of this function to finish this # connection without sending any error. self._logger.debug('%s', util.get_stack_trace()) raise except Exception as e: util.prepend_message_to_exception( '%s raised exception for %s: ' % ( _DO_EXTRA_HANDSHAKE_HANDLER_NAME, request.ws_resource), e) raise handshake.HandshakeException(e, common.HTTP_STATUS_FORBIDDEN)
class Dispatcher(object): """Dispatches WebSocket requests. This class maintains a map from resource name to handlers. """ def __init__(self, root_dir, scan_dir=None, allow_handlers_outside_root_dir=True): """Construct an instance. Args: root_dir: The directory where handler definition files are 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. allow_handlers_outside_root_dir: Scans handler files even if their canonical path is not under root_dir. """ self._logger = util.get_class_logger(self) self._handler_suite_map = {} self._source_warnings = [] if scan_dir is None: scan_dir = root_dir if not os.path.realpath(scan_dir).startswith( os.path.realpath(root_dir)): raise DispatchException('scan_dir:%s must be a directory under ' 'root_dir:%s.' % (scan_dir, root_dir)) self._source_handler_files_in_dir(root_dir, scan_dir, allow_handlers_outside_root_dir) def add_resource_path_alias(self, alias_resource_path, existing_resource_path): """Add resource path alias. Once added, request to alias_resource_path would be handled by handler registered for existing_resource_path. Args: alias_resource_path: alias resource path existing_resource_path: existing resource path """ try: handler_suite = self._handler_suite_map[existing_resource_path] self._handler_suite_map[alias_resource_path] = handler_suite except KeyError: raise DispatchException('No handler for: %r' % existing_resource_path) def source_warnings(self): """Return warnings in sourcing handlers.""" return self._source_warnings def do_extra_handshake(self, request): """Do extra checking in WebSocket handshake. Select a handler based on request.uri and call its web_socket_do_extra_handshake function. Args: request: mod_python request. Raises: DispatchException: when handler was not found AbortedByUserException: when user handler abort connection HandshakeException: when opening handshake failed """ handler_suite = self.get_handler_suite(request.ws_resource) if handler_suite is None: raise DispatchException('No handler for: %r' % request.ws_resource) do_extra_handshake_ = handler_suite.do_extra_handshake try: do_extra_handshake_(request) except handshake.AbortedByUserException, e: raise except Exception, e: util.prepend_message_to_exception( '%s raised exception for %s: ' % (_DO_EXTRA_HANDSHAKE_HANDLER_NAME, request.ws_resource), e) raise handshake.HandshakeException(e, common.HTTP_STATUS_FORBIDDEN)