跳转至

Parameters

Index-py 使用 pydantic 用于更轻松的解析 HTTP 请求信息,并为之绑定了一套生成 OpenAPI 文档的程序。

显示 OpenAPI 文档

indexpy.openapi.application.OpenAPI 挂载进 Index-py 中。启动 index,访问你服务上 /openapi/ 即可看到生成的文档。

如果你不需要生成文档,仅仅只需要自动校验参数功能,这一步可以跳过。

1
2
3
4
5
6
from indexpy import Index
from indexpy.openapi import OpenAPI

app = Index()

app.router << ("/openapi" // OpenAPI("Title", "description", "1.0").routes)

默认的文档模板使用 swagger,如果你更喜欢 redocrapidoc 的样式,可以通过更改 template_name 来达到目的,例如:OpenAPI(..., template_name="redoc")

不仅如此,你还可以通过使用 template 参数来控制显示自己的喜欢的任何模板,只需要把模板的完整内容作为字符串传给 template 参数即可。

API Tags

OpenAPI 的 Tags 是一个有用的功能,在 Index-py 里,你可以通过如下方式来指定 URL 的分类标签。

tags 参数必须是一个 dict 类型,键为标签名。值需要包含 description,用于描述此标签;paths 是 URL 列表,如果 URL 包含路径参数,直接使用不带 :type 的字符串即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
OpenAPI(
    title="index.py example",
    description="just a example, power by index.py",
    version="v1",
    tags={
        "something": {
            "description": "test over two tags in one path",
            "paths": ["/about/{username}", "/file", "/"],
        },
        "about": {
            "description": "about page",
            "paths": ["/about/", "/about/{username}"],
        },
    },
)

接口描述

对于所有可处理 HTTP 请求的方法,它们的 __doc__ 都会用于生成 OpenAPI 文档。第一行将被当作概要描述,所以尽量简明扼要,不要太长。空一行之后,后续的文字都会被当作详细介绍,被安置在 OpenAPI 文档中。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from indexpy import HTTPView


async def handler(request):
    """
    api summary

    api description..........................
    .........................................
    .........................................
    """


class ClassHandler(HTTPView):
    async def get(self):
        """
        api summary

        api description..........................
        .........................................
        .........................................
        """

标注请求参数

先看一个最简单的例子,两个分页参数,首先通过 Type hint 标注它们都需要 int 类型,在给予它们 Query(...) 作为值,Query 代表它们将会从 request.query_params 中读取值,... 作为第一个参数,意味着它没有默认值,也就是客户端请求该接口时必须传递值。譬如:?page_num=1&page_size=10

1
2
3
4
5
6
7
8
9
from indexpy import Query


async def getlist(
    request,
    page_num: int = Query(...),
    page_size: int = Query(...)
):
    ...

也可以通过使用继承自 pydantic.BaseModel 的类作为类型注解来描述同一类型的全部参数,通过类的继承可以做到复用参数。下例与上例是等价的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from indexpy import Query
from pydantic import BaseModel


class PageQuery(BaseModel):
    page_num: int
    page_size: int


async def getlist(query: PageQuery = Query(exclusive=True)):
    ...

或者你需要直接读取 request 的某些属性。如下例所示,当 code 被调用时会自动读取 request.user 并作为函数参数传入函数中。

1
2
3
4
5
6
from indexpy import Request
from yourmodule import User


async def code(user: User = Request()):
    ...

当需要读取的属性名称不能作为参数名称时,也可以为 Request 传入一个字符串作为属性名进行读取。如下例所示,request.user.name 将会作为函数参数 username 传入函数中。

1
2
3
4
5
from indexpy import Request


async def code(username: str = Request("user.name")):
    ...

描述响应结果

为了描述不同状态码的响应结果,Index-py 使用装饰器描述,而不是类型注解。describe_response 接受五个参数,其中 status 为必需项,descriptioncontentheaderslinks 为可选项,对应 OpenAPI Specification 里的同名字段。

其中,content 既可以使用类型对象或 pydantic.BaseModel 的派生子类描述响应,亦可以直接传递符合 OpenAPI 文档的 Dict(当你描述返回一个非 application/json 类型的响应时这很有用)。

如果 description 的值为默认的 "",则会使用 http 标准库中的 HTTPStatus(status).description 作为描述。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from http import HTTPStatus

from indexpy.openapi import describe_response


@describe_response(HTTPStatus.NO_CONTENT)
def handler():
    """
    .................
    """

除了 describe_response 描述单个响应状态码以外,你还可以使用 describe_responses 对状态码批量的描述。字典以 status 为键,以 OpenAPI Response Object 的四个属性作为可选的值(其中 description 为必选)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from indexpy.openapi import describe_responses

RESPONSES = {
    404: {"description": "Item not found"},
    403: {"description": "Not enough privileges"},
    302: {"description": "The item was moved"},
}


@describe_responses(RESPONSES)
@describe_response(204, "No Content")
def handler():
    """
    .................
    """

此功能到目前为止,除生成OpenAPI文档的作用外,无其他作用。未来或许会增加 mock 功能。

描述额外的 OpenAPI 文档

作为一个 Web 项目,在中间件中读取请求信息并作限制是很常见的,例如读取 JWT 用作鉴权。在每个视图都增加 header 参数是不现实的,这时候 describe_extra_docs 就派上用场了。

describe_extra_docs 增加的内容,不仅限于 parameters,任何描述都会被合并进原本的文档里。具体的字段可参考 OpenAPI Specification

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def judge_jwt(endpoint):
    describe_extra_docs(
        endpoint,
        {
            "parameters": [
                {
                    "name": "Authorization",
                    "in": "header",
                    "description": "JWT Token",
                    "required": True,
                    "schema": {"type": "string"},
                }
            ]
        },
    )

    async def judge(request):
        ...

    return judge
Version: 0.17
master
stable
0.17
0.16