Source code for bokeh.server.views.session_handler
#-----------------------------------------------------------------------------# Copyright (c) 2012 - 2024, Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------''' Abstract request handler that handles bokeh-session-id'''#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsfromtypingimportTYPE_CHECKING# External importsfromtornado.httputilimportHTTPServerRequestfromtornado.webimportHTTPError,authenticated# Bokeh importsfrombokeh.util.tokenimport(check_token_signature,generate_jwt_token,generate_session_id,get_session_id,)# Bokeh importsfrom.auth_request_handlerimportAuthRequestHandlerifTYPE_CHECKING:from...core.typesimportIDfrom..contextsimportApplicationContextfrom..sessionimportServerSessionfrom..tornadoimportBokehTornado#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('SessionHandler',)#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------
[docs]classSessionHandler(AuthRequestHandler):''' Implements a custom Tornado handler for document display page '''application:BokehTornadorequest:HTTPServerRequestapplication_context:ApplicationContextbokeh_websocket_path:strdef__init__(self,tornado_app:BokehTornado,*args,**kw)->None:self.application_context=kw['application_context']self.bokeh_websocket_path=kw['bokeh_websocket_path']# Note: tornado_app is stored as self.applicationsuper().__init__(tornado_app,*args,**kw)
@authenticatedasyncdefget_session(self)->ServerSession:app=self.applicationtoken=self.get_argument("bokeh-token",default=None)session_id:ID|None=self.get_argument("bokeh-session-id",default=None)if'Bokeh-Session-Id'inself.request.headers:ifsession_idisnotNone:log.debug("Server received session ID in request argument and header, expected only one")raiseHTTPError(status_code=403,reason="session ID was provided as an argument and header")session_id=self.request.headers.get('Bokeh-Session-Id')iftokenisnotNone:ifsession_idisnotNone:log.debug("Server received both token and session ID, expected only one")raiseHTTPError(status_code=403,reason="Both token and session ID were provided")session_id=get_session_id(token)elifsession_idisNone:ifapp.generate_session_ids:session_id=generate_session_id(secret_key=app.secret_key,signed=app.sign_sessions)else:log.debug("Server configured not to generate session IDs and none was provided")raiseHTTPError(status_code=403,reason="No bokeh-session-id provided")iftokenisNone:ifapp.include_headersisNone:excluded_headers=(app.exclude_headersor[])allowed_headers=[headerforheaderinself.request.headersifheadernotinexcluded_headers]else:allowed_headers=app.include_headersheaders={k:vfork,vinself.request.headers.items()ifkinallowed_headers}ifapp.include_cookiesisNone:excluded_cookies=(app.exclude_cookiesor[])allowed_cookies=[cookieforcookieinself.request.cookiesifcookienotinexcluded_cookies]else:allowed_cookies=app.include_cookiescookies={k:v.valuefork,vinself.request.cookies.items()ifkinallowed_cookies}ifcookiesand'Cookie'inheadersand'Cookie'notin(app.include_headersor[]):# Do not include Cookie header since cookies can be restored from cookies dictdelheaders['Cookie']arguments={}ifself.request.argumentsisNoneelseself.request.argumentspayload={'headers':headers,'cookies':cookies,'arguments':arguments}payload.update(self.application_context.application.process_request(self.request))token=generate_jwt_token(session_id,secret_key=app.secret_key,signed=app.sign_sessions,expiration=app.session_token_expiration,extra_payload=payload)ifnotcheck_token_signature(token,secret_key=app.secret_key,signed=app.sign_sessions):log.error("Session id had invalid signature: %r",session_id)raiseHTTPError(status_code=403,reason="Invalid token or session ID")session=awaitself.application_context.create_session_if_needed(session_id,self.request,token)returnsession