教程:构建 RESTful API#

在本教程中,我们将构建一个 RESTful JSON API。它将自动生成 OpenAPI 文档并验证请求和响应数据。

本教程旨在作为在 Quart 中构建 API 的入门介绍。如果您想直接跳到最后,代码位于 Github 上。

1:创建项目#

我们需要为我们的 api 服务器创建一个项目,我喜欢使用 Poetry 来完成此操作。Poetry 是通过 pip(或通过 Brew)安装的。

pip install poetry

然后我们可以使用 Poetry 创建一个新的 api 项目。

poetry new --src api

现在可以在 api 目录中开发我们的项目,所有后续命令都应在运行 api 目录中。

2:添加依赖项#

首先,我们只需要 Quart 来构建 api 服务器,我们可以通过运行以下命令将其安装为项目的依赖项。

poetry add quart

Poetry 将通过运行以下命令来确保此依赖项存在且路径正确。

poetry install

3:创建应用程序#

我们需要一个 Quart 应用程序作为我们的 Web 服务器,它由以下添加到 src/api/__init__.py 中的内容创建。

src/api/__init__.py#
from quart import Quart

app = Quart(__name__)

def run() -> None:
    app.run()

为了方便运行应用程序,我们可以通过在 pyproject.toml 中添加以下内容来从 poetry 脚本调用 run 方法。

pyproject.toml#
[tool.poetry.scripts]
start = "api:run"

这允许以下命令启动应用程序。

poetry run start

4:添加简单的 JSON API#

首先,我们可以添加一个路由,该路由读取发送给它的 JSON 并将其在响应中回显,方法是将以下内容添加到 src/api/__init__.py 中。

src/api/__init__.py#
from quart import request

@app.post("/echo")
async def echo():
    data = await request.get_json()
    return {"input": data, "extra": True}

我们可以使用 curl 来测试它。

curl --json '{"hello": "world"}' https://127.0.0.1:5000/echo

这将给出以下结果。

{"extra":true,"input":{"hello":"world"}}

明确地说,从路由处理程序返回的任何字典都将以 JSON 格式返回到响应中,并带有正确的 Content-Type 标头。如果您希望返回一个顶级数组作为 JSON 响应,则可以使用 jsonify 函数,如下所示。

from quart import jsonify

@app.get("/example")
async def example():
    return jsonify(["a", "b"])

5:添加模式#

使用 Quart-Schema 扩展,我们可以定义模式来验证请求和响应数据。此外,Quart-Schema 然后将利用这些模式来自动生成 OpenAPI(Swagger)文档。首先,我们需要安装 quart-schema。

poetry add quart-schema

然后,我们可以通过将以下内容添加到 src/api/__init__.py 中来添加 Todo 对象的模式。

src/api/__init__.py#
from dataclasses import dataclass
from datetime import datetime

from quart import Quart
from quart_schema import QuartSchema, validate_request, validate_response

app = Quart(__name__)

QuartSchema(app)

@dataclass
class TodoIn:
    task: str
    due: datetime | None

@dataclass
class Todo(TodoIn):
    id: int

@app.post("/todos/")
@validate_request(TodoIn)
@validate_response(Todo)
async def create_todo(data: TodoIn) -> Todo:
    return Todo(id=1, task=data.task, due=data.due)

然后,OpenAPI 模式可在 https://127.0.0.1:5000/openapi.json 获取,文档本身可在 https://127.0.0.1:5000/docs 获取。

6:测试#

要测试我们的应用程序,我们需要检查 echo 路由是否返回发送给它的 JSON 数据以及 create_todo 路由是否创建了一个待办事项。这可以通过将以下内容添加到 tests/test_api.py 中来完成。

tests/test_api.py#
from api import app, TodoIn

async def test_echo() -> None:
    test_client = app.test_client()
    response = await test_client.post("/echo", json={"a": "b"})
    data = await response.get_json()
    assert data == {"extra":True,"input":{"a":"b"}}

async def test_create_todo() -> None:
    test_client = app.test_client()
    response = await test_client.post("/todos/", json=TodoIn(task="Abc", due=None))
    data = await response.get_json()
    assert data == {"id": 1, "task": "Abc", "due": None}

由于测试是一个异步函数,我们需要通过运行以下命令安装 pytest-asyncio

poetry add --dev pytest-asyncio

安装完成后,需要通过在 pyproject.toml 中添加以下内容来配置它。

[tool.pytest.ini_options]
asyncio_mode = "auto"

最后,我们可以通过以下命令运行测试。

poetry run pytest tests/

如果您在 Quart 示例文件夹中运行此命令,您需要添加一个 -c pyproject.toml 选项以防止 pytest 使用 Quart pytest 配置。

7:总结#

我们构建了一个带有自动生成的 OpenAPI 文档和验证的 RESTful API 服务器。您现在可以利用这段代码构建任何 API。