Skip to main content
Donate to the Python Software Foundation or Purchase a PyCharm License to Benefit the PSF! Donate Now

Build and document REST APIs with aiohttp and apispec

Project description

aiohttp-apispec

Build and document REST APIs with aiohttp and apispec

Pypi build status [codcov]

[docs] Code style: black Contributors

Python 3.5 Python 3.6 Python 3.7

aiohttp-apispec key features:

  • docs and request_schema decorators to add swagger spec support out of the box;
  • validation_middleware middleware to enable validating with marshmallow schemas from those decorators;
  • SwaggerUI support.

aiohttp-apispec api is fully inspired by flask-apispec library

Contents

Install

pip install aiohttp-apispec

Quickstart

from aiohttp_apispec import (
    docs,
    request_schema,
    setup_aiohttp_apispec,
)
from aiohttp import web
from marshmallow import Schema, fields


class RequestSchema(Schema):
    id = fields.Int()
    name = fields.Str(description="name")

@docs(
    tags=["mytag"],
    summary="Test method summary",
    description="Test method description",
)
@request_schema(RequestSchema(strict=True))
async def index(request):
    return web.json_response({"msg": "done", "data": {}})


app = web.Application()
app.router.add_post("/v1/test", index)

# init docs with all parameters, usual for ApiSpec
setup_aiohttp_apispec(
    app=app, 
    title="My Documentation", 
    version="v1",
    url="/api/docs/swagger.json",
    swagger_path="/api/docs",
)

# Now we can find spec on 'http://localhost:8080/api/docs/swagger.json'
# and docs on 'http://localhost:8080/api/docs'
web.run_app(app)

Class based views are also supported:

class TheView(web.View):
    @docs(
        tags=["mytag"],
        summary="View method summary",
        description="View method description",
    )
    @request_schema(RequestSchema(strict=True))
    @response_schema(ResponseSchema(), 200)
    def delete(self):
        return web.json_response(
            {"msg": "done", "data": {"name": self.request["data"]["name"]}}
        )


app.router.add_view("/v1/view", TheView)

As alternative you can add responses info to docs decorator, which is more compact way. And it allows you not to use schemas for responses documentation:

@docs(
    tags=["mytag"],
    summary="Test method summary",
    description="Test method description",
    responses={
        200: {
            "schema": ResponseSchema,
            "description": "Success response",
        },  # regular response
        404: {"description": "Not found"},  # responses without schema
        422: {"description": "Validation error"},
    },
)
@request_schema(RequestSchema(strict=True))
async def index(request):
    return web.json_response({"msg": "done", "data": {}})

Adding validation middleware

from aiohttp_apispec import validation_middleware

...

app.middlewares.append(validation_middleware)

Now you can access all validated data in route from request['data'] like so:

@docs(
    tags=["mytag"],
    summary="Test method summary",
    description="Test method description",
)
@request_schema(RequestSchema(strict=True))
@response_schema(ResponseSchema(), 200)
async def index(request):
    uid = request["data"]["id"]
    name = request["data"]["name"]
    return web.json_response(
        {"msg": "done", "data": {"info": f"name - {name}, id - {uid}"}}
    )

You can change Request's 'data' param to another with request_data_name argument of setup_aiohttp_apispec function:

setup_aiohttp_apispec(
    app=app,
    request_data_name="validated_data",
)

...


@request_schema(RequestSchema(strict=True))
async def index(request):
    uid = request["validated_data"]["id"]
    ...

If you want to catch validation errors you should write your own middleware and catch web.HTTPClientError, json.JSONDecodeError and so on. Like this:

@web.middleware
async def my_middleware(request, handler):
    try:
        return await handler(request)
    except web.HTTPClientError:
        return web.json_response(status=400)


app.middlewares.extend(
    [
        my_middleware,  # Catch exception by your own, format it and respond to client
        validation_middleware,
    ]
)

Build swagger web client

3.X SwaggerUI version

Just add swagger_path parameter to setup_aiohttp_apispec function.

For example:

setup_aiohttp_apispec(app, swagger_path="/docs")

Then go to /docs and see awesome SwaggerUI

2.X SwaggerUI version

If you prefer older version you can use aiohttp_swagger library. aiohttp-apispec adds swagger_dict parameter to aiohttp web application after initialization (with setup_aiohttp_apispec function). So you can use it easily like:

from aiohttp_apispec import setup_aiohttp_apispec
from aiohttp_swagger import setup_swagger


def create_app(app):
    setup_aiohttp_apispec(app)

    async def swagger(app):
        setup_swagger(
            app=app, swagger_url="/api/doc", swagger_info=app["swagger_dict"]
        )

    app.on_startup.append(swagger)
    # now we can access swagger client on '/api/doc' url
    ...
    return app

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size & hash SHA256 hash help File type Python version Upload date
aiohttp-apispec-1.1.2.tar.gz (2.3 MB) Copy SHA256 hash SHA256 Source None

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page