跳转至

OpenAPI Document

编写如下代码,访问你服务上 /docs/ 即可看到生成的文档。

from kui.wsgi import Kui, OpenAPI

app = Kui()

app.router << ("/docs" // OpenAPI().routes)

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

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

标签

在 Kuí 里,你可以通过如下方式来定义 Tag 的 description 值。

OpenAPI(
    ......,
    tags={
        "tag-name": {
            "description": ".......",
        },
    },
)

Tip

如果不需要为 tag 增加 description,那么可以跳过这一步。

在注册路由时传入 tags 参数,

from kui.wsgi import Routes

routes = Routes()


@routes.http.get('/', tags=["tag-name", "tag-name-2"])
def handler():
    return "/"

接口介绍

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

例如:

from kui.wsgi import HTTPView


def handler():
    """
    api summary

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


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

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

你也可以在注册路由传入参数。

Tip

参数传入时,会覆盖掉从 __doc__ 中解析出的内容。

from kui.wsgi import Routes

routes = Routes()


@routes.http.get('/', summary="api summary", description="api description.............")
def handler():
    return "/"

描述请求参数

当你使用依赖注入时,请求参数将自动生成。

修改 Content-Type

Kuí 会自动读取 app.factory_class.http.data 的函数签名,并读取其中包含的 ContentType 对象作为 Content-Type 生成 OpenAPI 文档。

一个简单自定义样例——使用 msgpack 解析数据:

import typing
from http import HTTPStatus

import msgpack
from typing_extensions import Annotated

from kui.wsgi import Kui, FactoryClass, HttpRequest


class MsgPackRequest(HttpRequest):
    def data(self) -> Annotated[typing.Any, ContentType("application/x-msgpack")]:
        if self.content_type == "application/x-msgpack":
            return msgpack.unpackb(self.body)

        raise HTTPException(
            HTTPStatus.UNSUPPORTED_MEDIA_TYPE,
            headers={"Accept": "application/x-msgpack"},
        )


app = Kui(factory_class=FactoryClass(http=MsgPackRequest))

描述响应结果

为了生成响应结果的 OpenAPI 文档,你应当使用 Annotated 对视图的返回值进行描述。

from typing_extensions import Annotated
from kui.wsgi import Kui, JSONResponse

app = Kui()


@app.router.http.get("/hello")
def hello() -> Annotated[Any, JSONResponse[200, {}, List[str]]]:
    """
    hello
    """
    return ["hello", "world"]

你还可以描述多个响应结果,如下所示:

from typing_extensions import Annotated
from kui.wsgi import Kui, JSONResponse
from pydantic import BaseModel

app = Kui()


class ErrorMessage(BaseModel):
    code: int
    message: str


@app.router.http.get("/hello")
def hello() -> Annotated[
    Any,
    JSONResponse[200, {}, List[str]],
    JSONResponse[400, {}, ErrorMessage]
]:
    """
    hello
    """
    ...

使用不同的 Response 子类可以生成不同的响应结果文档。

Tip

只有第一个参数是必须的,其他参数都可不填。

所有响应里的 headers 参数应当是一个标准的 OpenAPI Response 中所需要的 Headers 字典。例如:{"Location": {"schema": {"type": "string"}}}

  • json: JSONResponse[status_code, headers, content]

    • content: 可以是标准 OpenAPI Response 中所需要的 Content 字典;也可以是 TypedDictstr 之类的类型,还可以是 pydantic.BaseModel 的子类。
  • html: HTMLResponse[status_code, headers]

  • text: TextResponse[status_code, headers]
  • redirect: RedirectResponse[status_code, headers]
  • file: FileResponse[content_type, headers]
    • content_type: 指定返回的文件的 Content-Type。

除此之外,你还可以直接使用标准 OpenAPI Response 字典(dict)来描述响应结果,这同样会被解析、插入到最终生成的 API 文档里。

在中间件里使用

和在视图函数中使用一样,你可以在中间件中使用 Annotated 来描述响应结果。

from typing_extensions import Annotated


def required_auth(endpoint):
    def wrapper(authorization: Annotated[str, Header()]) -> Annotated[Any, JSONResponse[401]]:
        ...
        return await endpoint()

    return wrapper

在依赖函数里使用

和在视图函数中使用一样,你可以在依赖函数中使用 Annotated 来描述响应结果。

from typing_extensions import Annotated


def required_auth(authorization: Annotated[str, Header()]) -> Annotated[Any, JSONResponse[401]]:
    ...

描述额外的 OpenAPI 文档

可以使用 describe_extra_docs 对接口所对应的 OpenAPI 文档描述进行补充,使用 describe_extra_docs 增加的任何描述都会被合并进原本的文档里。

具体的字段可参考 OpenAPI Specification