comparison 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
comparison
equal deleted inserted replaced
1202:3f791fbc1643 1203:251eba911d4d
468 if uri_tuple in self.uri_callbacks: 468 if uri_tuple in self.uri_callbacks:
469 log.info(_(u"{}/{} URIs are already handled, replacing by the new handler") 469 log.info(_(u"{}/{} URIs are already handled, replacing by the new handler")
470 .format( *uri_tuple)) 470 .format( *uri_tuple))
471 self.uri_callbacks[uri_tuple] = (self, get_uri_cb) 471 self.uri_callbacks[uri_tuple] = (self, get_uri_cb)
472 472
473 def getSignalId(self, request):
474 """Retrieve signal_id for a request
475
476 signal_id is used for dynamic page, to associate a initial request with a
477 signal handler. For WebsocketRequest, signal_id attribute is used (which must
478 be orginal request's id)
479 For server.Request it's id(request)
480 """
481 return getattr(request, 'signal_id', id(request))
482
473 def registerSignal(self, request, signal, check_profile=True): 483 def registerSignal(self, request, signal, check_profile=True):
474 r"""register a signal handler 484 r"""register a signal handler
475 485
476 the page must be dynamic 486 the page must be dynamic
477 when signal is received, self.on_signal will be called with: 487 when signal is received, self.on_signal will be called with:
489 # FIXME: add a timeout; if socket is not opened before it, signal handler 499 # FIXME: add a timeout; if socket is not opened before it, signal handler
490 # must be removed 500 # must be removed
491 if not self.dynamic: 501 if not self.dynamic:
492 log.error(_(u"You can't register signal if page is not dynamic")) 502 log.error(_(u"You can't register signal if page is not dynamic"))
493 return 503 return
494 LiberviaPage.signals_handlers.setdefault(signal, {})[id(request)] = ( 504 signal_id = self.getSignalId(request)
505 LiberviaPage.signals_handlers.setdefault(signal, {})[signal_id] = [
495 self, 506 self,
496 request, 507 request,
497 check_profile, 508 check_profile,
498 ) 509 ]
499 request._signals_registered.append(signal) 510 request._signals_registered.append(signal)
500 511
501 def getConfig(self, key, default=None, value_type=None): 512 def getConfig(self, key, default=None, value_type=None):
502 return self.host.getConfig(self.vhost_root, key=key, default=default, 513 return self.host.getConfig(self.vhost_root, key=key, default=default,
503 value_type=value_type) 514 value_type=value_type)
1023 """Called for dynamic pages when socket has just been opened 1034 """Called for dynamic pages when socket has just been opened
1024 1035
1025 we send all cached signals 1036 we send all cached signals
1026 """ 1037 """
1027 assert request._signals_cache is not None 1038 assert request._signals_cache is not None
1039 # we need to replace corresponding original requests by this websocket request
1040 # in signals_handlers
1041 signal_id = request.signal_id
1042 for signal_handlers_map in self.__class__.signals_handlers.itervalues():
1043 if signal_id in signal_handlers_map:
1044 signal_handlers_map[signal_id][1] = request
1045
1028 cache = request._signals_cache 1046 cache = request._signals_cache
1029 request._signals_cache = None 1047 request._signals_cache = None
1030 for request, signal, args in cache: 1048 for request, signal, args in cache:
1031 self.on_signal(self, request, signal, *args) 1049 self.on_signal(self, request, signal, *args)
1032 1050
1034 """Called for dynamic pages when socket has just been closed 1052 """Called for dynamic pages when socket has just been closed
1035 1053
1036 we remove signal handler 1054 we remove signal handler
1037 """ 1055 """
1038 for signal in request._signals_registered: 1056 for signal in request._signals_registered:
1057 signal_id = self.getSignalId(request)
1039 try: 1058 try:
1040 del LiberviaPage.signals_handlers[signal][id(request)] 1059 del LiberviaPage.signals_handlers[signal][signal_id]
1041 except KeyError: 1060 except KeyError:
1042 log.error(_(u"Can't find signal handler for [{signal}], this should not " 1061 log.error(_(u"Can't find signal handler for [{signal}], this should not "
1043 u"happen").format(signal=signal)) 1062 u"happen").format(signal=signal))
1044 else: 1063 else:
1045 log.debug(_(u"Removed signal handler")) 1064 log.debug(_(u"Removed signal handler"))
1206 socket_url = self.host.getWebsocketURL(request) 1225 socket_url = self.host.getWebsocketURL(request)
1207 socket_debug = C.boolConst(self.host.debug) 1226 socket_debug = C.boolConst(self.host.debug)
1208 request.template_data["websocket"] = WebsocketMeta( 1227 request.template_data["websocket"] = WebsocketMeta(
1209 socket_url, socket_token, socket_debug 1228 socket_url, socket_token, socket_debug
1210 ) 1229 )
1211 self.host.registerWSToken(socket_token, self, request)
1212 # we will keep track of handlers to remove 1230 # we will keep track of handlers to remove
1213 request._signals_registered = [] 1231 request._signals_registered = []
1214 # we will cache registered signals until socket is opened 1232 # we will cache registered signals until socket is opened
1215 request._signals_cache = [] 1233 request._signals_cache = []
1234 self.host.registerWSToken(socket_token, self, request)
1216 1235
1217 def _prepare_render(self, __, request): 1236 def _prepare_render(self, __, request):
1218 return defer.maybeDeferred(self.prepare_render, self, request) 1237 return defer.maybeDeferred(self.prepare_render, self, request)
1219 1238
1220 def _render_method(self, __, request): 1239 def _render_method(self, __, request):