FastAPI 中我们可以接收的上传文件的最大大小是多少?

aay*_*all 10 python http backend server-side fastapi

我试图计算出我的客户端可以上传的最大文件大小,以便我的 python fastapi 服务器可以毫无问题地处理它。

Sim*_*mba 17

您的请求不会直接到达 ASGI 应用程序。在由 ASGI 应用程序处理之前,它会经过反向代理(Nginx、Apache)、ASGI 服务器(uvicorn、hypercorn、gunicorn)。

\n

反向代理

\n

对于 Nginx,主体大小由 控制client_max_body_size,默认为 1MB。

\n

对于 Apache,主体大小可以通过 控制LimitRequestBody,默认为 0。

\n

ASGI服务器

\n

ASGI 服务器没有主体大小的限制。至少gunicorn、uvicorn、hypercorn 是这样。

\n

引用自 Hypercorn 文档。

\n
\n

请求正文较大

\n

这种攻击是第二种类型,旨在通过邀请服务器接收大型请求正文(从而将请求正文写入内存)来耗尽服务器\xe2\x80\x99s的内存。配置不当的服务器对请求主体大小没有限制,并且可能允许单个请求耗尽服务器。

\n

框架来防范这种攻击。这是为了允许框架在需要时使用请求正文。

\n
\n

注意:Gunicorn 不限制请求正文的大小,而是限制请求行和请求标头的大小。

\n
    \n
  • --limit-request-line,每个req行的大小限制,默认4096
  • \n
  • --limit-request-fields, 标头字段数量, 默认100
  • \n
  • --limit-request-field_size,headef字段的大小,默认8190
  • \n
\n

ASGI 应用程序/框架

\n

由于 FastAPI 是基于 Starlette 的。如何读取正文由 Starlette 处理。从源代码(0.14.3)读取,请求主体似乎也没有限制。

\n
class Request(HTTPConnection):\n    ...\n    async def stream(self) -> typing.AsyncGenerator[bytes, None]:\n        if hasattr(self, "_body"):\n            yield self._body\n            yield b""\n            return\n\n        if self._stream_consumed:\n            raise RuntimeError("Stream consumed")\n\n        self._stream_consumed = True\n        while True:\n            message = await self._receive()\n            if message["type"] == "http.request":\n                body = message.get("body", b"")\n                if body:\n                    yield body\n                if not message.get("more_body", False):\n                    break\n            elif message["type"] == "http.disconnect":\n                self._is_disconnected = True\n                raise ClientDisconnect()\n        yield b""\n\n    async def body(self) -> bytes:\n        if not hasattr(self, "_body"):\n            chunks = []\n            async for chunk in self.stream():\n                chunks.append(chunk)\n            self._body = b"".join(chunks)\n        return self._body\n
Run Code Online (Sandbox Code Playgroud)\n
\n

结论:如果出现413 Payload Too Large错误,请检查反向代理。

\n