Skip to main content

Sanic-Dispatcher

A Dispatcher extension for Sanic that also acts as a Sanic-to-WSGI adapter

Allows you to do this: (seriously)

from sanic import Sanic, response
from sanic_dispatcher import SanicDispatcherMiddlewareController
from flask import Flask, make_response, current_app as flask_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

child_sanic_app = Sanic("MyChildSanicApp")

child_flask_app = Flask("MyChildFlaskApp")

@app.middleware("response")
async def modify_response(request, response):
    response.body = response.body + b"\nModified by Sanic Response middleware!"
    response.headers['Content-Length'] = len(response.body)
    return response

@app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_sanic_app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_flask_app.route("/")
def index():
    app = flask_app
    return make_response("Hello World from {}".format(app.import_name))

dispatcher.register_sanic_application(child_sanic_app, '/sanicchild', apply_middleware=True)
dispatcher.register_wsgi_application(child_flask_app.wsgi_app, '/flaskchild', apply_middleware=True)

if __name__ == "__main__":
    app.run(port=8001, debug=True)

Installation

pip install Sanic-Dispatcher

How To Use

First make a Sanic application the way you normally do:

from sanic import Sanic

app = Sanic(__name__) # This creates a sanic app

app becomes your 'base' or 'parent' sanic app which will accommodate the Dispatcher extension

Create a Dispatcher

from sanic_dispatcher import SanicDispatcherMiddlewareController

dispatcher = SanicDispatcherMiddlewareController(app)

dispatcher is your new dispatcher controller. Note: This takes a reference to app as its first parameter, but it does not consume app, nor does it return app.

I want to dispatch another Sanic App

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

otherapp = Sanic("MyChildApp")

dispatcher.register_sanic_application(otherapp, "/childprefix")

@otherapp.route('/')
async def index(request):
    return response.text("Hello World from Child App")

Browsing to url /childprefix/ will invoke the otherapp App, and call the / route which displays "Hello World from Child App"

What if the other App is a Flask App?

from flask import Flask, make_response

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)
flaskapp = Flask("MyFlaskApp")

# register the wsgi_app method from the flask app into the dispatcher
dispatcher.register_wsgi_application(flaskapp.wsgi_app, "/flaskprefix")

@flaskapp.route('/')
def index():
    return make_response("Hello World from Flask App")

Browsing to url /flaskprefix/ will invoke the Flask App, and call the / route which displays "Hello World from Flask App"

What if the other App is a Django App?

import my_django_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)
# register the django wsgi application into the dispatcher
dispatcher.register_wsgi_application(my_django_app.wsgi.application,
                                     "/djangoprefix")

Browsing to url /djangoprefix/ will invoke the Django App.

Can I run a default application?

The Sanic App app you create at the start is also the default app.

When you navigate to a URL that does not match a registered dispatch prefix, this Sanic app will handle the request itself as per normal.

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

otherapp = Sanic("MyChildApp")

dispatcher.register_sanic_application(otherapp, "/childprefix")

@app.route('/')
async def index(request):
    return response.text("Hello World from Default App")

@otherapp.route('/')
async def index(request):
    return response.text("Hello World from Child App")

Browsing to url / will not invoke any Dispatcher applications, so app will handle the request itself, resolving the / route which displays "Hello World from Default App"

I want to apply common middleware to the registered applications!

Easy!

import my_django_app
from flask import Flask, make_response, current_app

app = Sanic(__name__)

dispatcher = SanicDispatcherMiddlewareController(app)

child_sanic_app = Sanic("MyChildSanicApp")

child_flask_app = Flask("MyChildFlaskApp")

@app.middleware("request")
async def modify_request(request):
    request.headers['Content-Type'] = "text/plain"

@app.middleware("response")
async def modify_response(request, response):
    response.body = response.body + b"\nModified by Sanic Response middleware!"
    response.headers['Content-Length'] = len(response.body)
    return response

@app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_sanic_app.route("/")
async def index(request):
    return response.text("Hello World from {}".format(request.app.name))

@child_flask_app.route("/")
def index():
    app = current_app
    return make_response("Hello World from {}".format(app.import_name))

dispatcher.register_sanic_application(child_sanic_app,
                                      '/childprefix', apply_middleware=True)
dispatcher.register_wsgi_application(my_django_app.wsgi.application,
                                     '/djangoprefix', apply_middleware=True)
dispatcher.register_wsgi_application(child_flask_app.wsgi_app,
                                     '/flaskprefix', apply_middleware=True)

The key here is passing apply_middleware=True to the relevant register application function. By default apply_middleware is set to False for all registered dispatcher applications.

In this example the Sanic Request Middleware modify_request will be applied to ALL requests, including those handled by applications registered on the dispatcher. The request middleware will be applied to the request before it is passed to any registered applications.

In this example the Sanic Response Middleware modify_response will be applied to ALL responses, including those which were generated by applications registered on the dispatcher. The response middleware will be applied to the response after it is processed by the registered application.

Metadata

Release files for Sanic-Dispatcher 0.8.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Sanic-Dispatcher 0.8.0.0
File Size Uploaded
Sanic-Dispatcher-0.8.0.0.tar.gz 11.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for Sanic-Dispatcher 0.8.0.0
File Interpreter ABI Platform
Sanic_Dispatcher-0.8.0.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 21.9 kB

Release files / Sanic-Dispatcher-0.8.0.0.tar.gz

Download URL Sanic-Dispatcher-0.8.0.0.tar.gz
Size 11.0 kB
Tags Source
SHA-256 checksum
How to use checksums
49b757df00818a8f22a00848f27b147f56bbd619d2eca9c2ed6d0f59ac4a894d
BLAKE2b-256 checksum
How to use checksums
c9add6178f101f98dd7c5c6bd3d033212e13912e3a3d96b97406e3d3723f0d29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.8.5

Release files / Sanic_Dispatcher-0.8.0.0-py2.py3-none-any.whl

Download URL Sanic_Dispatcher-0.8.0.0-py2.py3-none-any.whl
Size 10.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
5515265689adb87a971a12dd7d545d98a335cf63788b4e60f147551f674d7df8
BLAKE2b-256 checksum
How to use checksums
7117de627af0163625f3d35b1d2928638d04f71aaf70338872881c46a368bc8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.8.5

Release history Release notifications | RSS feed

This release

0.8.0.0 This release

2 release files

0.5.0

3 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page