中间件#

中间件可以用于包装 Quart 应用实例并更改 ASGI 进程。一个非常简单的示例是根据是否存在标头来拒绝请求,

class RejectMiddleware:

    def __init__(self, app):
        self.app = app

    async def __call__(self, scope, receive, send):
        if "headers" not in scope:
            return await self.app(scope, receive, send)

        for header, value in scope['headers']:
            if header.lower() == b'x-secret' and value == b'very-secret':
                return await self.app(scope, receive, send)

        return await self.error_response(receive, send)

    async def error_response(self, receive, send):
        await send({
            'type': 'http.response.start',
            'status': 401,
            'headers': [(b'content-length', b'0')],
        })
        await send({
            'type': 'http.response.body',
            'body': b'',
            'more_body': False,
        })

虽然中间件始终可以作为应用实例的包装器使用,但最好将其分配给并包装 asgi_app 属性,

quart_app.asgi_app = RejectMiddleware(quart_app.asgi_app)

因为这样可以确保在任何测试代码中应用中间件。

您可以组合多个中间件包装器,

quart_app.asgi_app = RejectMiddleware(quart_app.asgi_app)
quart_app.asgi_app = AdditionalMiddleware(quart_app.asgi_app)

并使用任何 ASGI 中间件。

警告

中间件在任何 Quart 代码之前运行,这意味着如果中间件返回响应,则不会运行任何 Quart 功能或 Quart 扩展。