提问人:aayushmittall 提问时间:6/23/2021 更新时间:7/7/2021 访问量:15857
我们可以在 FastAPI 中接收的最大上传文件大小是多少?
What is the maximum size of upload file we can receive in FastAPI?
答:
16赞
Simba
6/23/2021
#1
您的请求不会直接到达 ASGI 应用。在由 ASGI 应用程序处理之前,它会经过反向代理(Nginx、Apache)、ASGI 服务器(uvicorn、hypercorn、gunicorn)。
反向代理
对于 Nginx,body size 由 控制,默认为 1MB。client_max_body_size
对于 Apache,正文大小可以通过 控制,默认为 0。LimitRequestBody
ASGI 服务器
ASGI 服务器没有正文大小限制。至少 gunicorn、uvicorn、hypercorn 是这种情况。
引自 Hypercorn 文档。
大型请求正文
这种攻击属于第二种类型,旨在通过邀请服务器接收大型请求正文(从而将正文写入内存)来耗尽服务器的内存。配置不当的服务器对请求正文大小没有限制,并且可能允许单个请求耗尽服务器。
由框架来防范这种攻击。这是为了允许框架在需要时使用请求正文。
注意:Gunicorn 不限制请求正文的大小,但限制请求行和请求标头的大小。
--limit-request-line
,每个 req 行的大小限制,默认 4096--limit-request-fields
,标题字段数,默认值为 100--limit-request-field_size
,headef 字段的大小,默认值为 8190
ASGI 应用程序/框架
由于 FastAPI 基于 Starlette。如何阅读正文由 Starlette 处理。从源代码(0.14.3)读取,请求正文似乎也没有限制。
class Request(HTTPConnection):
...
async def stream(self) -> typing.AsyncGenerator[bytes, None]:
if hasattr(self, "_body"):
yield self._body
yield b""
return
if self._stream_consumed:
raise RuntimeError("Stream consumed")
self._stream_consumed = True
while True:
message = await self._receive()
if message["type"] == "http.request":
body = message.get("body", b"")
if body:
yield body
if not message.get("more_body", False):
break
elif message["type"] == "http.disconnect":
self._is_disconnected = True
raise ClientDisconnect()
yield b""
async def body(self) -> bytes:
if not hasattr(self, "_body"):
chunks = []
async for chunk in self.stream():
chunks.append(chunk)
self._body = b"".join(chunks)
return self._body
结论:如果出现“413 Payload Too Large”错误,请检查反向代理。
评论
Content-Length
.stream()
在块中读取请求正文,从而在您的应用程序中强制执行正文/文件大小限制。