function get_server
Creates and configures a Bokeh Server instance to serve Panel applications with support for OAuth authentication, static file serving, and session management.
/tf/active/vicechatdev/patches/server.py
574 - 757
complex
Purpose
This function is the primary entry point for deploying Panel applications as web servers. It handles the complete server setup including application routing, OAuth configuration, websocket origins, static file directories, and optional auto-start/show functionality. It supports serving single Panel objects, functions that return Panel objects, or multiple applications mapped to different URL slugs. The function also integrates with Flask applications and can serve Python/Jupyter notebook files directly.
Source Code
def get_server(panel, port=0, address=None, websocket_origin=None,
loop=None, show=False, start=False, title=None,
verbose=False, location=True, static_dirs={},
oauth_provider=None, oauth_key=None, oauth_secret=None,
oauth_extra_params={}, cookie_secret=None,
oauth_encryption_key=None, session_history=None, **kwargs):
"""
Returns a Server instance with this panel attached as the root
app.
Arguments
---------
panel: Viewable, function or {str: Viewable}
A Panel object, a function returning a Panel object or a
dictionary mapping from the URL slug to either.
port: int (optional, default=0)
Allows specifying a specific port
address : str
The address the server should listen on for HTTP requests.
websocket_origin: str or list(str) (optional)
A list of hosts that can connect to the websocket.
This is typically required when embedding a server app in
an external web site.
If None, "localhost" is used.
loop : tornado.ioloop.IOLoop (optional, default=IOLoop.current())
The tornado IOLoop to run the Server on.
show : boolean (optional, default=False)
Whether to open the server in a new browser tab on start.
start : boolean(optional, default=False)
Whether to start the Server.
title : str or {str: str} (optional, default=None)
An HTML title for the application or a dictionary mapping
from the URL slug to a customized title.
verbose: boolean (optional, default=False)
Whether to report the address and port.
location : boolean or panel.io.location.Location
Whether to create a Location component to observe and
set the URL location.
static_dirs: dict (optional, default={})
A dictionary of routes and local paths to serve as static file
directories on those routes.
oauth_provider: str
One of the available OAuth providers
oauth_key: str (optional, default=None)
The public OAuth identifier
oauth_secret: str (optional, default=None)
The client secret for the OAuth provider
oauth_extra_params: dict (optional, default={})
Additional information for the OAuth provider
cookie_secret: str (optional, default=None)
A random secret string to sign cookies (required for OAuth)
oauth_encryption_key: str (optional, default=False)
A random encryption key used for encrypting OAuth user
information and access tokens.
session_history: int (optional, default=None)
The amount of session history to accumulate. If set to non-zero
and non-None value will launch a REST endpoint at
/rest/session_info, which returns information about the session
history.
kwargs: dict
Additional keyword arguments to pass to Server instance.
Returns
-------
server : bokeh.server.server.Server
Bokeh Server instance running this panel
"""
from ..config import config
from .rest import REST_PROVIDERS
server_id = kwargs.pop('server_id', uuid.uuid4().hex)
kwargs['extra_patterns'] = extra_patterns = kwargs.get('extra_patterns', [])
if isinstance(panel, dict):
apps = {}
for slug, app in panel.items():
if isinstance(title, dict):
try:
title_ = title[slug]
except KeyError:
raise KeyError(
"Keys of the title dictionnary and of the apps "
f"dictionary must match. No {slug} key found in the "
"title dictionary.")
else:
title_ = title
slug = slug if slug.startswith('/') else '/'+slug
if 'flask' in sys.modules:
from flask import Flask
if isinstance(app, Flask):
wsgi = WSGIContainer(app)
if slug == '/':
raise ValueError('Flask apps must be served on a subpath.')
if not slug.endswith('/'):
slug += '/'
extra_patterns.append(('^'+slug+'.*', ProxyFallbackHandler,
dict(fallback=wsgi, proxy=slug)))
continue
if isinstance(app, pathlib.Path):
app = str(app) # enables serving apps from Paths
if (isinstance(app, str) and (app.endswith(".py") or app.endswith(".ipynb"))
and os.path.isfile(app)):
apps[slug] = build_single_handler_application(app)
else:
handler = FunctionHandler(partial(_eval_panel, app, server_id, title_, location))
apps[slug] = Application(handler)
else:
handler = FunctionHandler(partial(_eval_panel, panel, server_id, title, location))
apps = {'/': Application(handler)}
extra_patterns += get_static_routes(static_dirs)
if session_history is not None:
config.session_history = session_history
if config.session_history != 0:
pattern = REST_PROVIDERS['param']([], 'rest')
extra_patterns.extend(pattern)
state.publish('session_info', state, ['session_info'])
opts = dict(kwargs)
if loop:
loop.make_current()
opts['io_loop'] = loop
elif opts.get('num_procs', 1) == 1:
opts['io_loop'] = IOLoop.current()
if 'index' not in opts:
opts['index'] = INDEX_HTML
if address is not None:
opts['address'] = address
if websocket_origin:
if not isinstance(websocket_origin, list):
websocket_origin = [websocket_origin]
opts['allow_websocket_origin'] = websocket_origin
# Configure OAuth
from ..config import config
if config.oauth_provider:
from ..auth import OAuthProvider
opts['auth_provider'] = OAuthProvider()
if oauth_provider:
config.oauth_provider = oauth_provider
if oauth_key:
config.oauth_key = oauth_key
if oauth_extra_params:
config.oauth_extra_params = oauth_extra_params
if cookie_secret:
config.cookie_secret = cookie_secret
opts['cookie_secret'] = config.cookie_secret
server = Server(apps, port=port, **opts)
if verbose:
address = server.address or 'localhost'
url = f"http://{address}:{server.port}{server.prefix}"
print(f"Launching server at {url}")
state._servers[server_id] = (server, panel, [])
if show:
def show_callback():
server.show('/login' if config.oauth_provider else '/')
server.io_loop.add_callback(show_callback)
def sig_exit(*args, **kwargs):
server.io_loop.add_callback_from_signal(do_stop)
def do_stop(*args, **kwargs):
server.io_loop.stop()
try:
signal.signal(signal.SIGINT, sig_exit)
except ValueError:
pass # Can't use signal on a thread
if start:
server.start()
try:
server.io_loop.start()
except RuntimeError:
pass
return server
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
panel |
- | - | positional_or_keyword |
port |
- | 0 | positional_or_keyword |
address |
- | None | positional_or_keyword |
websocket_origin |
- | None | positional_or_keyword |
loop |
- | None | positional_or_keyword |
show |
- | False | positional_or_keyword |
start |
- | False | positional_or_keyword |
title |
- | None | positional_or_keyword |
verbose |
- | False | positional_or_keyword |
location |
- | True | positional_or_keyword |
static_dirs |
- | {} | positional_or_keyword |
oauth_provider |
- | None | positional_or_keyword |
oauth_key |
- | None | positional_or_keyword |
oauth_secret |
- | None | positional_or_keyword |
oauth_extra_params |
- | {} | positional_or_keyword |
cookie_secret |
- | None | positional_or_keyword |
oauth_encryption_key |
- | None | positional_or_keyword |
session_history |
- | None | positional_or_keyword |
**kwargs |
- | - | var_keyword |
Parameter Details
panel: The Panel application to serve. Can be a Viewable object, a function returning a Viewable, a dictionary mapping URL slugs to Viewables/functions, a Flask app, or a path to a .py/.ipynb file.
port: TCP port number for the server to listen on. Default 0 means the OS will assign an available port automatically.
address: Network address/hostname for the server to bind to (e.g., 'localhost', '0.0.0.0'). None uses Bokeh's default.
websocket_origin: Allowed origins for websocket connections. Required when embedding the app in external sites. Can be a string or list of strings. None defaults to 'localhost'.
loop: Tornado IOLoop instance to run the server on. If None, uses IOLoop.current().
show: If True, automatically opens the server URL in a new browser tab when started.
start: If True, starts the server immediately and blocks until stopped. If False, returns the server instance without starting.
title: HTML page title. Can be a string for single apps or a dictionary mapping URL slugs to titles for multi-app setups.
verbose: If True, prints the server address and port to console when launching.
location: Whether to create a Location component for URL observation and manipulation. Can be boolean or a Location instance.
static_dirs: Dictionary mapping URL routes to local filesystem paths for serving static files (e.g., {'/static': '/path/to/files'}).
oauth_provider: Name of OAuth provider to use for authentication (e.g., 'github', 'google', 'azure').
oauth_key: OAuth client ID/public identifier from the OAuth provider.
oauth_secret: OAuth client secret from the OAuth provider. Required for OAuth authentication.
oauth_extra_params: Additional provider-specific OAuth parameters as a dictionary.
cookie_secret: Secret string for signing secure cookies. Required when using OAuth. Should be a random, hard-to-guess string.
oauth_encryption_key: Encryption key for securing OAuth tokens and user information. Should be a random string.
session_history: Number of session history entries to track. If non-zero/non-None, enables a REST endpoint at /rest/session_info for session data.
kwargs: Additional keyword arguments passed directly to the Bokeh Server constructor (e.g., 'num_procs', 'index', 'extra_patterns').
Return Value
Returns a bokeh.server.server.Server instance configured with the specified Panel application(s). The server may or may not be started depending on the 'start' parameter. The server object can be used to control the server lifecycle (start, stop) and access server properties (port, address, io_loop).
Dependencies
panelbokehtornadoparamflaskuuidsignalpathlibfunctoolssysos
Required Imports
from panel.io.server import get_server
Conditional/Optional Imports
These imports are only needed under specific conditions:
from flask import Flask
Condition: only if serving Flask applications within the panel dictionary
Optionalfrom tornado.ioloop import IOLoop
Condition: only if providing a custom event loop via the 'loop' parameter
Optionalfrom panel.auth import OAuthProvider
Condition: only if using OAuth authentication (oauth_provider parameter)
OptionalUsage Example
import panel as pn
from panel.io.server import get_server
# Simple example with a single Panel object
def create_app():
return pn.Column(
pn.pane.Markdown('# My Panel App'),
pn.widgets.Button(name='Click me')
)
# Start server on port 5006 and open in browser
server = get_server(
panel=create_app,
port=5006,
show=True,
start=False,
title='My Panel Application',
verbose=True
)
# Multi-app example with different routes
apps = {
'/': create_app,
'/dashboard': lambda: pn.pane.Markdown('Dashboard'),
'/admin': lambda: pn.pane.Markdown('Admin Panel')
}
server = get_server(
panel=apps,
port=5007,
title={'/' : 'Home', '/dashboard': 'Dashboard', '/admin': 'Admin'},
websocket_origin=['localhost:5007', 'myapp.com'],
static_dirs={'/static': './static_files'},
verbose=True
)
# Start the server
server.start()
server.io_loop.start()
Best Practices
- Always use a secure random string for cookie_secret in production, especially when using OAuth
- Set websocket_origin when embedding the app in external websites to prevent CORS issues
- Use verbose=True during development to easily see the server URL
- For production, set start=False and manage the server lifecycle manually for better control
- When serving multiple apps, ensure title dictionary keys match the panel dictionary keys
- Flask apps must be served on a subpath (not '/') and the slug will automatically get a trailing slash
- Use session_history cautiously as it stores session data in memory
- Consider using num_procs parameter in kwargs for multi-process deployments
- The server_id is automatically generated but can be overridden via kwargs for tracking purposes
- Signal handlers (SIGINT) are registered automatically but may not work in threaded contexts
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function serve 84.3% similar
-
function init_doc 53.5% similar
-
class Application 53.1% similar
-
function server_html_page_for_session 52.2% similar
-
function _eval_panel 52.0% similar