Commits

bb b...@gmx.de  committed cc42f2c Draft

infer endpoint name from websocket URL path;
store websocket with other outbound endpoints

  • Participants
  • Parent commits f4b828f

Comments (0)

Files changed (1)

File araldo/app.py

 """ Handles WebSocket requests and HTTP requests
 """
 import logging
+import re
 from geventwebsocket.exceptions import WebSocketError
 import gevent
 from araldo.message import Message
 STATIC_DIR = "."
 WS_TIMEOUT = 10  # WebSocket timeout (s)
 
+WEBSOCKET_NAME_RE = re.compile("/websocket/([^/]+)/?")
 
 class TooLong(Exception):
     """ Indicates a gevent timeout
         logging.getLogger("araldo").debug("A timeout occurred")
         Exception.__init__(self, TooLong._msg)
 
+class AppException(Exception):
+    """ An internal exception 
+    """
+
+    def __init__(self, msg):
+        logging.getLogger("araldo").error(msg)
+        Exception.__init__(self, msg)
 
 class WebSocketApp(object):
     """ Provides bidirectional communication:
         self._logger = logging.getLogger("araldo")
         self._plugin_manager = PluginManager.get()
         outbound = self._plugin_manager.plugin_instances()["araldo.endpoints.outbound"]
-        if "websocket" not in outbound:
-            outbound["websocket"] = {}
-        self._websockets = outbound["websocket"]
+        self._websockets = outbound
 
-    def _communicate_with_websocket(self, web_socket):
+    def _communicate_with_websocket(self, web_socket, web_socket_name):
         """ Receive incoming message from websocket.
             :param web_socket: WebSocket to listen to
             :raises Timeout: if no message receives for `WS_TIMEOUT` seconds.
         """
-        #print web_socket, dir(web_socket)
         timeout = gevent.Timeout(WS_TIMEOUT)
         timeout.start()
         message = web_socket.receive()
             gevent.sleep(0)
         else:
             self._logger.debug("null message (client disconnect?)")
-            if id(web_socket) in self._websockets:
+            if web_socket_name in self._websockets:
                 self._logger.debug("Removing websocket")
-                del self._websockets[id(web_socket)]
+                del self._websockets[web_socket_name]
             return
 
-    def _handle_websocket(self, environ):
+    def _handle_websocket(self, environ, web_socket_name):
         """ Handle call to websocket.
             This method will never return (serves forever)
 
         """
         self._logger.debug("Received WebSocket call: %s" % environ)
         web_socket = environ["wsgi.websocket"]
-        self._logger.debug("Adding websocket")
+        self._logger.debug("Adding websocket '%s'" % web_socket_name)
         self._logger.debug("### %s" % dir(web_socket))
-        self._websockets[id(web_socket)] = web_socket
+        self._websockets[web_socket_name] = web_socket
         while True:
             try:
                 self._communicate_with_websocket(
-                    web_socket)
+                    web_socket, web_socket_name)
             except gevent.Timeout, error:
                 self._logger.debug(str(error))
             gevent.sleep(0)
 ##        start_response('200 OK', [('Content-Type', 'text/html')])
 ##        return ["outbound response\n"]
 
+    def _parse_websocket_name(self, path_info):
+            m = WEBSOCKET_NAME_RE.match(path_info)
+            if not m:
+                raise AppException("Unable to determine WebSocket name")
+            return m.group(1)
+
     def __call__(self, environ, start_response):
         """ main WSGI method
         """
         path_info = environ["PATH_INFO"]
-        if path_info == '/websocket':
-            self._handle_websocket(environ)
-        elif path_info == '/outbound':
-            return self._handle_outbound(environ, start_response)
+        if path_info.startswith('/websocket'):
+            self._handle_websocket(
+                environ,
+                self._parse_websocket_name(path_info))
+        #elif path_info == '/outbound':
+        #    return self._handle_outbound(environ, start_response)
+        else:
+            start_response('404 NOT FOUND', [('Content-Type', 'text/html')])
+            return ["<h1>Not found</h1"]
 
         self._logger.debug("returning")