You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
"""
Application Dispatcher ======================
This middleware creates a single WSGI application that dispatches to multiple other WSGI applications mounted at different URL paths.
A common example is writing a Single Page Application, where you have a backend API and a frontend written in JavaScript that does the routing in the browser rather than requesting different pages from the server. The frontend is a single HTML and JS file that should be served for any path besides "/api".
This example dispatches to an API app under "/api", an admin app under "/admin", and an app that serves frontend files for all other requests::
app = DispatcherMiddleware(serve_frontend, { '/api': api_app, '/admin': admin_app, })
In production, you might instead handle this at the HTTP server level, serving files or proxying to application servers based on location. The API and admin apps would each be deployed with a separate WSGI server, and the static files would be served directly by the HTTP server.
.. autoclass:: DispatcherMiddleware
:copyright: 2007 Pallets :license: BSD-3-Clause """
import typing as t
if t.TYPE_CHECKING: from _typeshed.wsgi import StartResponse from _typeshed.wsgi import WSGIApplication from _typeshed.wsgi import WSGIEnvironment
class DispatcherMiddleware: """Combine multiple applications as a single WSGI application.
Requests are dispatched to an application based on the path it is mounted under.
:param app: The WSGI application to dispatch to if the request doesn't match a mounted path. :param mounts: Maps path prefixes to applications for dispatching. """
def __init__( self, app: "WSGIApplication", mounts: t.Optional[t.Dict[str, "WSGIApplication"]] = None, ) -> None: self.app = app self.mounts = mounts or {}
def __call__( self, environ: "WSGIEnvironment", start_response: "StartResponse" ) -> t.Iterable[bytes]: script = environ.get("PATH_INFO", "") path_info = ""
while "/" in script: if script in self.mounts: app = self.mounts[script] break
script, last_item = script.rsplit("/", 1) path_info = f"/{last_item}{path_info}" else: app = self.mounts.get(script, self.app)
original_script_name = environ.get("SCRIPT_NAME", "") environ["SCRIPT_NAME"] = original_script_name + script environ["PATH_INFO"] = path_info return app(environ, start_response)
|