Mercurial > libervia-web
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): |