{"id":13705598,"url":"https://github.com/ashleysommer/sanic-dispatcher","last_synced_at":"2025-04-09T17:24:43.105Z","repository":{"id":57463838,"uuid":"84781233","full_name":"ashleysommer/sanic-dispatcher","owner":"ashleysommer","description":"A Dispatcher extension for Sanic which also acts as a Sanic-to-WSGI adapter","archived":false,"fork":false,"pushed_at":"2021-03-25T09:24:41.000Z","size":32,"stargazers_count":30,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-03-15T03:55:25.371Z","etag":null,"topics":["plugin","python-3","python-3-5","python-3-6","python3","sanic","wsgi","wsgi-middleware"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ashleysommer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-13T03:43:01.000Z","updated_at":"2022-09-10T06:50:47.000Z","dependencies_parsed_at":"2022-09-17T14:52:45.848Z","dependency_job_id":null,"html_url":"https://github.com/ashleysommer/sanic-dispatcher","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashleysommer%2Fsanic-dispatcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashleysommer%2Fsanic-dispatcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashleysommer%2Fsanic-dispatcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashleysommer%2Fsanic-dispatcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ashleysommer","download_url":"https://codeload.github.com/ashleysommer/sanic-dispatcher/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248075647,"owners_count":21043630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["plugin","python-3","python-3-5","python-3-6","python3","sanic","wsgi","wsgi-middleware"],"created_at":"2024-08-02T22:00:44.549Z","updated_at":"2025-04-09T17:24:43.079Z","avatar_url":"https://github.com/ashleysommer.png","language":"Python","funding_links":[],"categories":["Extensions"],"sub_categories":["Utils"],"readme":"# Sanic-Dispatcher\n### A Dispatcher extension for Sanic that also acts as a Sanic-to-WSGI adapter \n\nAllows you to do this: *(seriously)*\n```python\nfrom sanic import Sanic, response\nfrom sanic_dispatcher import SanicDispatcherMiddlewareController\nfrom flask import Flask, make_response, current_app as flask_app\n\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n\nchild_sanic_app = Sanic(\"MyChildSanicApp\")\n\nchild_flask_app = Flask(\"MyChildFlaskApp\")\n\n@app.middleware(\"response\")\nasync def modify_response(request, response):\n    response.body = response.body + b\"\\nModified by Sanic Response middleware!\"\n    response.headers['Content-Length'] = len(response.body)\n    return response\n\n@app.route(\"/\")\nasync def index(request):\n    return response.text(\"Hello World from {}\".format(request.app.name))\n\n@child_sanic_app.route(\"/\")\nasync def index(request):\n    return response.text(\"Hello World from {}\".format(request.app.name))\n\n@child_flask_app.route(\"/\")\ndef index():\n    app = flask_app\n    return make_response(\"Hello World from {}\".format(app.import_name))\n\ndispatcher.register_sanic_application(child_sanic_app, '/sanicchild', apply_middleware=True)\ndispatcher.register_wsgi_application(child_flask_app.wsgi_app, '/flaskchild', apply_middleware=True)\n\nif __name__ == \"__main__\":\n    app.run(port=8001, debug=True)\n```\n\n## Installation \n\n    pip install Sanic-Dispatcher\n\n## How To Use\n\nFirst make a Sanic application the way you normally do:\n```python\nfrom sanic import Sanic\n\napp = Sanic(__name__) # This creates a sanic app\n```\n`app` becomes your 'base' or 'parent' sanic app which will accommodate the Dispatcher extension\n\nCreate a Dispatcher\n```python\nfrom sanic_dispatcher import SanicDispatcherMiddlewareController\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n```\n`dispatcher` is your new dispatcher controller.\n*Note: This takes a reference to `app` as its first parameter, but it does not consume `app`, nor does it return `app`.*\n\n**I want to dispatch another Sanic App**\n```python\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n\notherapp = Sanic(\"MyChildApp\")\n\ndispatcher.register_sanic_application(otherapp, \"/childprefix\")\n\n@otherapp.route('/')\nasync def index(request):\n    return response.text(\"Hello World from Child App\")\n```\nBrowsing to url `/childprefix/` will invoke the `otherapp` App, and call the `/` route which displays \"Hello World from Child App\"\n\n**What if the other App is a Flask App?**\n```python\nfrom flask import Flask, make_response\n\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\nflaskapp = Flask(\"MyFlaskApp\")\n\n# register the wsgi_app method from the flask app into the dispatcher\ndispatcher.register_wsgi_application(flaskapp.wsgi_app, \"/flaskprefix\")\n\n@flaskapp.route('/')\ndef index():\n    return make_response(\"Hello World from Flask App\")\n```\nBrowsing to url `/flaskprefix/` will invoke the Flask App, and call the `/` route which displays \"Hello World from Flask App\"\n\n**What if the other App is a Django App?**\n```python\nimport my_django_app\n\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n# register the django wsgi application into the dispatcher\ndispatcher.register_wsgi_application(my_django_app.wsgi.application,\n                                     \"/djangoprefix\")\n```\nBrowsing to url `/djangoprefix/` will invoke the Django App.\n\n**Can I run a default application?**\n\nThe Sanic App `app` you create at the start is also the default app.\n\nWhen you navigate to a URL that does not match a registered dispatch prefix, this Sanic app will handle the request itself as per normal.\n```python\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n\notherapp = Sanic(\"MyChildApp\")\n\ndispatcher.register_sanic_application(otherapp, \"/childprefix\")\n\n@app.route('/')\nasync def index(request):\n    return response.text(\"Hello World from Default App\")\n\n@otherapp.route('/')\nasync def index(request):\n    return response.text(\"Hello World from Child App\")\n```\nBrowsing 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\"\n\n**I want to apply common middleware to the registered applications!**\n\nEasy!\n```python\nimport my_django_app\nfrom flask import Flask, make_response, current_app\n\napp = Sanic(__name__)\n\ndispatcher = SanicDispatcherMiddlewareController(app)\n\nchild_sanic_app = Sanic(\"MyChildSanicApp\")\n\nchild_flask_app = Flask(\"MyChildFlaskApp\")\n\n@app.middleware(\"request\")\nasync def modify_request(request):\n    request.headers['Content-Type'] = \"text/plain\"\n\n@app.middleware(\"response\")\nasync def modify_response(request, response):\n    response.body = response.body + b\"\\nModified by Sanic Response middleware!\"\n    response.headers['Content-Length'] = len(response.body)\n    return response\n\n@app.route(\"/\")\nasync def index(request):\n    return response.text(\"Hello World from {}\".format(request.app.name))\n\n@child_sanic_app.route(\"/\")\nasync def index(request):\n    return response.text(\"Hello World from {}\".format(request.app.name))\n\n@child_flask_app.route(\"/\")\ndef index():\n    app = current_app\n    return make_response(\"Hello World from {}\".format(app.import_name))\n\ndispatcher.register_sanic_application(child_sanic_app,\n                                      '/childprefix', apply_middleware=True)\ndispatcher.register_wsgi_application(my_django_app.wsgi.application,\n                                     '/djangoprefix', apply_middleware=True)\ndispatcher.register_wsgi_application(child_flask_app.wsgi_app,\n                                     '/flaskprefix', apply_middleware=True)\n```\nThe 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.\n\nIn 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.\n\nIn 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashleysommer%2Fsanic-dispatcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fashleysommer%2Fsanic-dispatcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashleysommer%2Fsanic-dispatcher/lists"}