diff libervia/server/pages.py @ 1203:251eba911d4d

server (websockets): fixed websocket handling on HTTPS connections: Original request used to retrieve a page was stored on dynamic pages, but after the end of it, the channel was deleted, resulting in a isSecure() always returning False, and troubles in chain leading to the the use of the wrong session object. This patch fixes this by reworking the way original request is used, and creating a new wrapping class allowing to keep an API similar to iweb.IRequest, with data coming from both the original request and the websocket request. fix 327
author Goffi <goffi@goffi.org>
date Sun, 14 Jul 2019 14:45:51 +0200
parents 1211dbc3cca7
children 92d0a2b785fd
line wrap: on
line diff
--- a/libervia/server/pages.py	Fri Jul 12 14:58:11 2019 +0200
+++ b/libervia/server/pages.py	Sun Jul 14 14:45:51 2019 +0200
@@ -470,6 +470,16 @@
                 .format( *uri_tuple))
         self.uri_callbacks[uri_tuple] = (self, get_uri_cb)
 
+    def getSignalId(self, request):
+        """Retrieve signal_id for a request
+
+        signal_id is used for dynamic page, to associate a initial request with a
+        signal handler. For WebsocketRequest, signal_id attribute is used (which must
+        be orginal request's id)
+        For server.Request it's id(request)
+        """
+        return getattr(request, 'signal_id', id(request))
+
     def registerSignal(self, request, signal, check_profile=True):
         r"""register a signal handler
 
@@ -491,11 +501,12 @@
         if not self.dynamic:
             log.error(_(u"You can't register signal if page is not dynamic"))
             return
-        LiberviaPage.signals_handlers.setdefault(signal, {})[id(request)] = (
+        signal_id = self.getSignalId(request)
+        LiberviaPage.signals_handlers.setdefault(signal, {})[signal_id] = [
             self,
             request,
             check_profile,
-        )
+        ]
         request._signals_registered.append(signal)
 
     def getConfig(self, key, default=None, value_type=None):
@@ -1025,6 +1036,13 @@
         we send all cached signals
         """
         assert request._signals_cache is not None
+        # we need to replace corresponding original requests by this websocket request
+        # in signals_handlers
+        signal_id = request.signal_id
+        for signal_handlers_map in self.__class__.signals_handlers.itervalues():
+            if signal_id in signal_handlers_map:
+                signal_handlers_map[signal_id][1] = request
+
         cache = request._signals_cache
         request._signals_cache = None
         for request, signal, args in cache:
@@ -1036,8 +1054,9 @@
         we remove signal handler
         """
         for signal in request._signals_registered:
+            signal_id = self.getSignalId(request)
             try:
-                del LiberviaPage.signals_handlers[signal][id(request)]
+                del LiberviaPage.signals_handlers[signal][signal_id]
             except KeyError:
                 log.error(_(u"Can't find signal handler for [{signal}], this should not "
                             u"happen").format(signal=signal))
@@ -1208,11 +1227,11 @@
         request.template_data["websocket"] = WebsocketMeta(
             socket_url, socket_token, socket_debug
         )
-        self.host.registerWSToken(socket_token, self, request)
         # we will keep track of handlers to remove
         request._signals_registered = []
         # we will cache registered signals until socket is opened
         request._signals_cache = []
+        self.host.registerWSToken(socket_token, self, request)
 
     def _prepare_render(self, __, request):
         return defer.maybeDeferred(self.prepare_render, self, request)