@@ -116,6 +116,7 @@ def __init__(self, *args, **kwargs):
116116 "rewrite_response" ,
117117 tuple (),
118118 )
119+ self ._requested_subprotocols = None
119120 super ().__init__ (* args , ** kwargs )
120121
121122 # Support/use jupyter_server config arguments allow_origin and allow_origin_pat
@@ -520,27 +521,21 @@ async def start_websocket_connection():
520521 self .log .info (f"Trying to establish websocket connection to { client_uri } " )
521522 self ._record_activity ()
522523 request = httpclient .HTTPRequest (url = client_uri , headers = headers )
523- subprotocols = (
524- [self .selected_subprotocol ] if self .selected_subprotocol else None
525- )
526524 self .ws = await pingable_ws_connect (
527525 request = request ,
528526 on_message_callback = message_cb ,
529527 on_ping_callback = ping_cb ,
530- subprotocols = subprotocols ,
528+ subprotocols = self . _requested_subprotocols ,
531529 resolver = resolver ,
532530 )
533531 self ._record_activity ()
534532 self .log .info (f"Websocket connection established to { client_uri } " )
535- if (
536- subprotocols
537- and self .ws .selected_subprotocol != self .selected_subprotocol
538- ):
533+ if self .ws .selected_subprotocol != self .selected_subprotocol :
539534 self .log .warn (
540535 f"Websocket subprotocol between proxy/server ({ self .ws .selected_subprotocol } ) "
541536 f"became different than for client/proxy ({ self .selected_subprotocol } ) "
542537 "due to https://github.com/jupyterhub/jupyter-server-proxy/issues/459. "
543- f"Requested subprotocols were { subprotocols } ."
538+ f"Requested subprotocols were { self . _requested_subprotocols } ."
544539 )
545540
546541 # Wait for the WebSocket to be connected before resolving.
@@ -578,20 +573,27 @@ def select_subprotocol(self, subprotocols):
578573 """
579574 Select a single Sec-WebSocket-Protocol during handshake.
580575
581- Note that this subprotocol selection should really be delegated to the
582- server we proxy to, but we don't! For this to happen, we would need to
583- delay accepting the handshake with the client until we have successfully
584- handshaked with the server. This issue is tracked via
585- https://github.com/jupyterhub/jupyter-server-proxy/issues/459.
586-
587576 Overrides `tornado.websocket.WebSocketHandler.select_subprotocol` that
588577 includes an informative docstring:
589578 https://github.com/tornadoweb/tornado/blob/v6.4.0/tornado/websocket.py#L337-L360.
590579 """
580+ # Stash all requested subprotocols to be re-used as requested
581+ # subprotocols in the proxy/server handshake to be performed later. At
582+ # least bokeh has used additional subprotocols to pass credentials,
583+ # making this a required workaround for now.
584+ #
585+ self ._requested_subprotocols = subprotocols if subprotocols else None
586+
591587 if subprotocols :
592588 self .log .debug (
593589 f"Client sent subprotocols: { subprotocols } , selecting the first"
594590 )
591+ # FIXME: Subprotocol selection should be delegated to the server we
592+ # proxy to, but we don't! For this to happen, we would need
593+ # to delay accepting the handshake with the client until we
594+ # have successfully handshaked with the server. This issue is
595+ # tracked in https://github.com/jupyterhub/jupyter-server-proxy/issues/459.
596+ #
595597 return subprotocols [0 ]
596598 return None
597599
0 commit comments