消费请求体#

请求可以包含一个主体,例如对于 POST 请求,主体可以包含来自网页的表单编码数据或来自客户端的 JSON 编码数据。主体在请求行和 HTTP/1 和 HTTP/2 的标头之后发送。这允许 Quart 在收到完整主体之前触发应用程序的请求处理代码。此外,请求者可以选择流式传输请求主体,尤其是在主体很大时,就像发送文件时经常发生的那样。

Quart 遵循 Flask 并提供方法在继续之前等待整个主体,

@app.route('/', methods=['POST'])
async def index():
    await request.get_data()

高级用法#

您可能希望完全控制请求主体是如何被消费的,最有可能的是为了在数据被接收时消费数据。为此,Quart 提供了迭代主体的的方法,

from async_timeout import timeout

@app.route('/', methods=['POST'])
async def index():
    async with timeout(app.config['BODY_TIMEOUT']):
        async for data in request.body:
            ...

注意

上面的代码片段使用 Async-Timeout 来确保主体在指定的时间范围内收到。

警告

虽然其他访问主体的请求方法和属性如果客户端发送请求的时间过长会超时。使用 body 不会,并且由您自己负责将使用包装在超时中。

警告

迭代主体会消耗数据,因此除非在迭代期间保存数据,否则任何进一步使用数据都是不可能的。

测试#

要测试路由是否以迭代方式消费主体,您需要使用 request() 方法,

async def test_stream() -> None:
    test_client = app.test_client()
    async with test_client.request(...) as connection:
        await connection.send(b"data")
        await connection.send_complete()
    response = await connection.as_response()
    assert response ...

检查代码在客户端在发送请求主体时断开连接时按预期清理也很有意义,

async def test_stream_closed() -> None:
    test_client = app.test_client()
    async with test_client.request(...) as connection:
        await connection.send(b"partial")
        await connection.disconnect()
    # Check cleanup markers....