{"id":13494337,"url":"https://github.com/maximdanilchenko/aiohttp-apispec","last_synced_at":"2025-05-15T03:05:11.645Z","repository":{"id":27317299,"uuid":"113189253","full_name":"maximdanilchenko/aiohttp-apispec","owner":"maximdanilchenko","description":"Build and document REST APIs with aiohttp and apispec","archived":false,"fork":false,"pushed_at":"2024-11-15T10:07:46.000Z","size":6155,"stargazers_count":220,"open_issues_count":25,"forks_count":57,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-15T03:04:57.079Z","etag":null,"topics":["aiohttp","apispec","asyncio","documentation","marshmallow","swagger","validation","webargs"],"latest_commit_sha":null,"homepage":"https://aiohttp-apispec.rtfd.io","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/maximdanilchenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-05T13:59:59.000Z","updated_at":"2025-04-14T12:22:24.000Z","dependencies_parsed_at":"2024-06-12T16:15:57.287Z","dependency_job_id":"53c92b46-3f7e-438f-873d-b6030679460e","html_url":"https://github.com/maximdanilchenko/aiohttp-apispec","commit_stats":{"total_commits":271,"total_committers":37,"mean_commits":7.324324324324325,"dds":0.3837638376383764,"last_synced_commit":"f5c55473c93a1cc16958e3e3606b271c7c67e51a"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximdanilchenko%2Faiohttp-apispec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximdanilchenko%2Faiohttp-apispec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximdanilchenko%2Faiohttp-apispec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximdanilchenko%2Faiohttp-apispec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maximdanilchenko","download_url":"https://codeload.github.com/maximdanilchenko/aiohttp-apispec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"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":["aiohttp","apispec","asyncio","documentation","marshmallow","swagger","validation","webargs"],"created_at":"2024-07-31T19:01:24.045Z","updated_at":"2025-05-15T03:05:11.590Z","avatar_url":"https://github.com/maximdanilchenko.png","language":"Python","readme":"\u003ch1 align=\"center\"\u003eaiohttp-apispec\u003c/h1\u003e\n\u003cp align=\"center\"\u003eBuild and document REST APIs with \u003ca href=\"https://github.com/aio-libs/aiohttp\"\u003eaiohttp\u003c/a\u003e and \u003ca href=\"https://github.com/marshmallow-code/apispec\"\u003eapispec\u003c/a\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.python.org/pypi/aiohttp-apispec\"\u003e\u003cimg src=\"https://badge.fury.io/py/aiohttp-apispec.svg\" alt=\"Pypi\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/maximdanilchenko/aiohttp-apispec/graphs/contributors\"\u003e\u003cimg src=\"https://img.shields.io/github/contributors/maximdanilchenko/aiohttp-apispec.svg\" alt=\"Contributors\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pepy.tech/project/aiohttp-apispec\"\u003e\u003cimg src=\"https://pepy.tech/badge/aiohttp-apispec\" alt=\"Downloads\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://app.travis-ci.com/github/maximdanilchenko/aiohttp-apispec\"\u003e\u003cimg src=\"https://app.travis-ci.com/maximdanilchenko/aiohttp-apispec.svg?branch=master\" alt=\"build status\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://aiohttp-apispec.readthedocs.io/en/latest/?badge=latest\"\u003e\u003cimg src=\"https://readthedocs.org/projects/aiohttp-apispec/badge/?version=latest\" alt=\"[docs]\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/maximdanilchenko/aiohttp-apispec\"\u003e\u003cimg src=\"https://codecov.io/gh/maximdanilchenko/aiohttp-apispec/branch/master/graph/badge.svg\" alt=\"[codcov]\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ambv/black\"\u003e\u003cimg src=\"https://img.shields.io/badge/code%20style-black-000000.svg\" alt=\"Code style: black\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n\n```aiohttp-apispec``` key features:\n- ```docs``` and ```request_schema``` decorators \nto add swagger spec support out of the box;\n- ```validation_middleware``` middleware to enable validating \nwith marshmallow schemas from those decorators;\n- **SwaggerUI** support.\n- *New from version 2.0* -  ```match_info_schema```, ```querystring_schema```, \n```form_schema```, ```json_schema```, ```headers_schema``` and ```cookies_schema``` \ndecorators for specific request parts validation. \nLook [here](#more-decorators) for more info.\n\n```aiohttp-apispec``` api is fully inspired by ```flask-apispec``` library\n\n**Version 3.0.0b1 with apispec\u003e=5.0 webargs\u003e=8.0 is in beta now** (`pip install aiohttp-apispec==3.0.0b1`).\n\n## Contents\n\n- [Install](#install)\n- [Quickstart](#quickstart)\n- [Adding validation middleware](#adding-validation-middleware)\n- [More decorators](#more-decorators)\n- [Custom error handling](#custom-error-handling)\n- [Build swagger web client](#build-swagger-web-client)\n- [Versioning](#versioning)\n\n\n## Install\n\n```\npip install aiohttp-apispec\n```\n\n## Quickstart\n\n*Also you can read [blog post](https://dmax.blog/how_to_easily_build_modern_web_apis_with_python_and_aiohttp) about quickstart with aiohttp-apispec*\n\n```Python\nfrom aiohttp_apispec import (\n    docs,\n    request_schema,\n    setup_aiohttp_apispec,\n)\nfrom aiohttp import web\nfrom marshmallow import Schema, fields\n\n\nclass RequestSchema(Schema):\n    id = fields.Int()\n    name = fields.Str(description=\"name\")\n\n@docs(\n    tags=[\"mytag\"],\n    summary=\"Test method summary\",\n    description=\"Test method description\",\n)\n@request_schema(RequestSchema(strict=True))\nasync def index(request):\n    return web.json_response({\"msg\": \"done\", \"data\": {}})\n\n\napp = web.Application()\napp.router.add_post(\"/v1/test\", index)\n\n# init docs with all parameters, usual for ApiSpec\nsetup_aiohttp_apispec(\n    app=app, \n    title=\"My Documentation\", \n    version=\"v1\",\n    url=\"/api/docs/swagger.json\",\n    swagger_path=\"/api/docs\",\n)\n\n# Now we can find spec on 'http://localhost:8080/api/docs/swagger.json'\n# and docs on 'http://localhost:8080/api/docs'\nweb.run_app(app)\n```\nClass based views are also supported:\n```python\nclass TheView(web.View):\n    @docs(\n        tags=[\"mytag\"],\n        summary=\"View method summary\",\n        description=\"View method description\",\n    )\n    @request_schema(RequestSchema(strict=True))\n    @response_schema(ResponseSchema(), 200)\n    def delete(self):\n        return web.json_response(\n            {\"msg\": \"done\", \"data\": {\"name\": self.request[\"data\"][\"name\"]}}\n        )\n\n\napp.router.add_view(\"/v1/view\", TheView)\n```\n\nAs alternative you can add responses info to `docs` decorator, which is more compact way. \nAnd it allows you not to use schemas for responses documentation:\n\n```python\n@docs(\n    tags=[\"mytag\"],\n    summary=\"Test method summary\",\n    description=\"Test method description\",\n    responses={\n        200: {\n            \"schema\": ResponseSchema,\n            \"description\": \"Success response\",\n        },  # regular response\n        404: {\"description\": \"Not found\"},  # responses without schema\n        422: {\"description\": \"Validation error\"},\n    },\n)\n@request_schema(RequestSchema(strict=True))\nasync def index(request):\n    return web.json_response({\"msg\": \"done\", \"data\": {}})\n```\n\n## Adding validation middleware\n\n```Python\nfrom aiohttp_apispec import validation_middleware\n\n...\n\napp.middlewares.append(validation_middleware)\n```\nNow you can access all validated data in route from ```request['data']``` like so:\n\n```Python\n@docs(\n    tags=[\"mytag\"],\n    summary=\"Test method summary\",\n    description=\"Test method description\",\n)\n@request_schema(RequestSchema(strict=True))\n@response_schema(ResponseSchema, 200)\nasync def index(request):\n    uid = request[\"data\"][\"id\"]\n    name = request[\"data\"][\"name\"]\n    return web.json_response(\n        {\"msg\": \"done\", \"data\": {\"info\": f\"name - {name}, id - {uid}\"}}\n    )\n```\n\n\nYou can change ``Request``'s ``'data'`` param to another with ``request_data_name`` argument of \n``setup_aiohttp_apispec`` function:\n\n```python\nsetup_aiohttp_apispec(\n    app=app,\n    request_data_name=\"validated_data\",\n)\n\n...\n\n\n@request_schema(RequestSchema(strict=True))\nasync def index(request):\n    uid = request[\"validated_data\"][\"id\"]\n    ...\n```\n\nAlso you can do it for specific view using ```put_into``` \nparameter (beginning from version 2.0):\n\n```python\n@request_schema(RequestSchema(strict=True), put_into=\"validated_data\")\nasync def index(request):\n    uid = request[\"validated_data\"][\"id\"]\n    ...\n```\n\n## More decorators\n\nStarting from version 2.0 you can use shortenings for documenting and validating \nspecific request parts like cookies, headers etc using those decorators:\n\n| Decorator name | Default put_into param |\n|:----------|:-----------------|\n| match_info_schema | match_info |\n| querystring_schema | querystring |\n| form_schema | form |\n| json_schema | json |\n| headers_schema | headers |\n| cookies_schema | cookies | \n\nAnd example:\n\n```python\n@docs(\n    tags=[\"users\"],\n    summary=\"Create new user\",\n    description=\"Add new user to our toy database\",\n    responses={\n        200: {\"description\": \"Ok. User created\", \"schema\": OkResponse},\n        401: {\"description\": \"Unauthorized\"},\n        422: {\"description\": \"Validation error\"},\n        500: {\"description\": \"Server error\"},\n    },\n)\n@headers_schema(AuthHeaders)  # \u003c- schema for headers validation\n@json_schema(UserMeta)  # \u003c- schema for json body validation\n@querystring_schema(UserParams)  # \u003c- schema for querystring params validation\nasync def create_user(request: web.Request):\n    headers = request[\"headers\"]  # \u003c- validated headers!\n    json_data = request[\"json\"]  # \u003c- validated json!\n    query_params = request[\"querystring\"]  # \u003c- validated querystring!\n    ...\n```\n\n## Custom error handling\n\nIf you want to catch validation errors by yourself you \ncould use `error_callback` parameter and create your custom error handler. Note that\nit can be one of coroutine or callable and it should \nhave interface exactly like in examples below:\n\n```python\nfrom marshmallow import ValidationError, Schema\nfrom aiohttp import web\nfrom typing import Optional, Mapping, NoReturn\n\n\ndef my_error_handler(\n    error: ValidationError,\n    req: web.Request,\n    schema: Schema,\n    error_status_code: Optional[int] = None,\n    error_headers: Optional[Mapping[str, str]] = None,\n) -\u003e NoReturn:\n    raise web.HTTPBadRequest(\n            body=json.dumps(error.messages),\n            headers=error_headers,\n            content_type=\"application/json\",\n        )\n\nsetup_aiohttp_apispec(app, error_callback=my_error_handler)\n```\nAlso you can create your own exceptions and create \nregular Request in middleware like so:\n\n```python\nclass MyException(Exception):\n    def __init__(self, message):\n        self.message = message\n\n# It can be coroutine as well:\nasync def my_error_handler(\n    error, req, schema, error_status_code, error_headers\n):\n    await req.app[\"db\"].do_smth()  # So you can use some async stuff\n    raise MyException({\"errors\": error.messages, \"text\": \"Oops\"})\n\n# This middleware will handle your own exceptions:\n@web.middleware\nasync def intercept_error(request, handler):\n    try:\n        return await handler(request)\n    except MyException as e:\n        return web.json_response(e.message, status=400)\n\n\nsetup_aiohttp_apispec(app, error_callback=my_error_handler)\n\n# Do not forget to add your own middleware before validation_middleware\napp.middlewares.extend([intercept_error, validation_middleware])\n```\n\n## Build swagger web client\n\n#### 3.X SwaggerUI version\n\nJust add `swagger_path` parameter to `setup_aiohttp_apispec` function.\n\nFor example:\n\n```python\nsetup_aiohttp_apispec(app, swagger_path=\"/docs\")\n```\n\nThen go to `/docs` and see awesome SwaggerUI\n\n#### 2.X SwaggerUI version\n\nIf you prefer older version you can use \n[aiohttp_swagger](https://github.com/cr0hn/aiohttp-swagger) library.\n`aiohttp-apispec` adds `swagger_dict` parameter to aiohttp web application \nafter initialization (with `setup_aiohttp_apispec` function). \nSo you can use it easily like:\n\n```Python\nfrom aiohttp_apispec import setup_aiohttp_apispec\nfrom aiohttp_swagger import setup_swagger\n\n\ndef create_app(app):\n    setup_aiohttp_apispec(app)\n\n    async def swagger(app):\n        setup_swagger(\n            app=app, swagger_url=\"/api/doc\", swagger_info=app[\"swagger_dict\"]\n        )\n\n    app.on_startup.append(swagger)\n    # now we can access swagger client on '/api/doc' url\n    ...\n    return app\n```\n\n## Versioning\n\nThis software follows [Semantic Versioning](http://semver.org/).\n\n------\n\nPlease star this repository if this project helped you!\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximdanilchenko%2Faiohttp-apispec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaximdanilchenko%2Faiohttp-apispec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximdanilchenko%2Faiohttp-apispec/lists"}