{ "info": { "author": "Rob Blackbourn", "author_email": "rob.blackbourn@gmail.com", "bugtrack_url": null, "classifiers": [ "Framework :: AsyncIO", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP" ], "description": "# aiohttp-routed-middleware\n\n## Overview\n\nAn extension for [aiohttp](https://github.com/aio-libs/aiohttp) which provides route local middleware while remainining compatible with the existing router.\n\nWith the built in router the technique for managing route local middleware is to make nested applications.\nHowever nested applications require a unique url prefix. so the following cannot be achieved:\n\n| Request | Middleware | Handler |\n| ----------------- | ----------------------------------------------------- | ----------- |\n| GET /post/{id} | authenticate, authorise(['post:read']) | get_post |\n| POST /post/{id} | authenticate, authorise(['post:read:', 'post:write']) | create_post |\n| DELETE /post/{id} | authenticate, authorise(['post:read:', 'post:write']) | delete_post |\n\nThis router allows a chain of middleware terminated by a handler. For example:\n\n```python\npost_app = web.Application(router=UrlDispatcherEx())\npost_app.router.add_get('/{id}', authenticate, authorise(['post:read']), get_posts)\npost_app.router.add_post('/{id}', authenticate, authorise(['post:read', 'post:write']), get_posts)\npost_app.router.add_delete('/{id}', authenticate, authorise(['post:read', 'post:write']), get_posts)\n\napp = web.Application()\napp.add_subapp('/post', post_app)\n\n```\n\n## Usage\n\n### Basic\n\nA middleware function differs from a normal request handler, in that it gets given the next handler to call.\n\nThe following example shows how to add middleware to a route.\n\n```python\nfrom aiohttp import web\nfrom aiohttp_route_middleware import UrlDispatcherEx\n\napp = web.Application(router=UrlDispatcherEx())\napp.router.add_get('/', middleware1, middleware2, test)\n\nasync def test(request):\n print(\"..entering handler\")\n response = web.Response(text=f\"extra_stuff=[{', '.join(request.extra_stuff)}]\")\n print(\"..exiting handler\")\n return response\n\n@web.middleware\nasync def middleware1(request, handler):\n print(\"entering middleware 1\")\n request.extra_stuff = ['foo']\n response = await handler(request)\n print(\"exiting middleware 1\")\n return response\n\n@web.middleware\nasync def middleware2(request, handler):\n print(\".entering middleware 2\")\n request.extra_stuff.append('bar')\n response = await handler(request)\n print(\".exiting middleware 2\")\n return response\n\napp = web.Application(router=UrlDispatcherEx())\napp.router.add_get('/', middleware1, middleware2, test)\nweb.run_app(app)\n```\n\nThis would print out the following:\n\n```bash\nentering middleware 1\n.entering middleware 2\n..entering handler\n..exiting handler\n.exiting middleware 2\nexiting middleware 1\n```\n\n### Middleware failure\n\nA middleware function may choose not to call the next handler; for example if there was an authentication error.\n\n```python\nfrom aiohttp import web\nfrom aiohttp_route_middleware import UrlDispatcherEx\n\nasync def test(request):\n return web.Response(text=\"Success\")\n\n@web.middleware\nasync def authenticate(request, handler):\n return web.Response(body=\"unauthenticated\", status=401)\n\napp = web.Application(router=UrlDispatcherEx())\napp.router.add_get('/', authenticate, test)\nweb.run_app(app)\n```\n\n## Installation\n\nYou can install it using pip:\n\n```bash\npip install aiohttp-route-middleware\n```\n\n## Details\n\nThe extension provides a router `UrlDispatcherEx` which extends from the built in class `UrlDispatcher`. The class can be used in the following manner:\n\n```python\nfrom aiohttp_route_middleware import UrlDispatcherEx\n\n...\n\napp = web.Application(router=UrlDispatcherEx())\n```\n\nThe extension allows multiple handlers to be specified. The handlers are called in order until a handler returns a non `None` response, at which point the response is returned and execution stops. \n\nAn example of this might be a route to update a comment on a post, The sequence might be:\n1. Authenticate the user.\n2. Check the user is authorised to post a comment.\n3. Fetch the post.\n4. Post the comment.\n\n```python\napp.router.add_post('/comment?post_id=1234', authenticate, authorise, fetch_post, post_comment)\n```\n\nEach handler is written in the same manner as a normal handler, in that it takes a single request argument. The request argument may be modified or enriched by each handler.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/rob-blackbourn/aiohttp-route-middleware/", "keywords": "", "license": "Apache 2", "maintainer": "", "maintainer_email": "", "name": "aiohttp-route-middleware", "package_url": "https://pypi.org/project/aiohttp-route-middleware/", "platform": "", "project_url": "https://pypi.org/project/aiohttp-route-middleware/", "project_urls": { "Homepage": "https://github.com/rob-blackbourn/aiohttp-route-middleware/" }, "release_url": "https://pypi.org/project/aiohttp-route-middleware/0.0.2/", "requires_dist": [ "aiohttp (>=3.0)" ], "requires_python": "~=3.6", "summary": "Local middleware routing for aiohttp.", "version": "0.0.2" }, "last_serial": 4293653, "releases": { "0.0.2": [ { "comment_text": "", "digests": { "md5": "740cbf492615a33b2bad5cb97de1668d", "sha256": "d64e228da14c69ffacf6306d61e1f149db379b3c2c18633ba374ae6435241e32" }, "downloads": -1, "filename": "aiohttp_route_middleware-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "740cbf492615a33b2bad5cb97de1668d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 4015, "upload_time": "2018-09-20T17:53:40", "url": "https://files.pythonhosted.org/packages/85/8b/1627b776a7c7a0a868224bfc38af431ad82a92a0435ef45eaa7f9e28d70a/aiohttp_route_middleware-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7df6982783075c6bd5751af84c334c6c", "sha256": "c112d0eccb1cc5091f163f16e99ebb7d5fa224b0b9eea81f9d69dd6f1b088153" }, "downloads": -1, "filename": "aiohttp_route_middleware-0.0.2.tar.gz", "has_sig": false, "md5_digest": "7df6982783075c6bd5751af84c334c6c", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 7878, "upload_time": "2018-09-20T17:53:42", "url": "https://files.pythonhosted.org/packages/ef/3f/e76710e7c80bb31cbbf1fcb2e7707a1ef9eec18600c408a8495f42727f19/aiohttp_route_middleware-0.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "740cbf492615a33b2bad5cb97de1668d", "sha256": "d64e228da14c69ffacf6306d61e1f149db379b3c2c18633ba374ae6435241e32" }, "downloads": -1, "filename": "aiohttp_route_middleware-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "740cbf492615a33b2bad5cb97de1668d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": "~=3.6", "size": 4015, "upload_time": "2018-09-20T17:53:40", "url": "https://files.pythonhosted.org/packages/85/8b/1627b776a7c7a0a868224bfc38af431ad82a92a0435ef45eaa7f9e28d70a/aiohttp_route_middleware-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7df6982783075c6bd5751af84c334c6c", "sha256": "c112d0eccb1cc5091f163f16e99ebb7d5fa224b0b9eea81f9d69dd6f1b088153" }, "downloads": -1, "filename": "aiohttp_route_middleware-0.0.2.tar.gz", "has_sig": false, "md5_digest": "7df6982783075c6bd5751af84c334c6c", "packagetype": "sdist", "python_version": "source", "requires_python": "~=3.6", "size": 7878, "upload_time": "2018-09-20T17:53:42", "url": "https://files.pythonhosted.org/packages/ef/3f/e76710e7c80bb31cbbf1fcb2e7707a1ef9eec18600c408a8495f42727f19/aiohttp_route_middleware-0.0.2.tar.gz" } ] }