🐛 Close FormData (uploaded files) after the request is done (#5465)

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
Adrian Garcia Badaracco 2022-11-03 07:06:52 -05:00 committed by GitHub
parent ed9425ef50
commit ac9f56ea5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 1 deletions

View File

@ -3,6 +3,7 @@ import dataclasses
import email.message import email.message
import inspect import inspect
import json import json
from contextlib import AsyncExitStack
from enum import Enum, IntEnum from enum import Enum, IntEnum
from typing import ( from typing import (
Any, Any,
@ -190,6 +191,9 @@ def get_request_handler(
if body_field: if body_field:
if is_body_form: if is_body_form:
body = await request.form() body = await request.form()
stack = request.scope.get("fastapi_astack")
assert isinstance(stack, AsyncExitStack)
stack.push_async_callback(body.close)
else: else:
body_bytes = await request.body() body_bytes = await request.body()
if body_bytes: if body_bytes:

View File

@ -1,6 +1,10 @@
from pathlib import Path
from typing import List
import pytest import pytest
from fastapi import UploadFile from fastapi import FastAPI, UploadFile
from fastapi.datastructures import Default from fastapi.datastructures import Default
from fastapi.testclient import TestClient
def test_upload_file_invalid(): def test_upload_file_invalid():
@ -20,3 +24,25 @@ def test_default_placeholder_bool():
placeholder_b = Default("") placeholder_b = Default("")
assert placeholder_a assert placeholder_a
assert not placeholder_b assert not placeholder_b
def test_upload_file_is_closed(tmp_path: Path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
app = FastAPI()
testing_file_store: List[UploadFile] = []
@app.post("/uploadfile/")
def create_upload_file(file: UploadFile):
testing_file_store.append(file)
return {"filename": file.filename}
client = TestClient(app)
with path.open("rb") as file:
response = client.post("/uploadfile/", files={"file": file})
assert response.status_code == 200, response.text
assert response.json() == {"filename": "test.txt"}
assert testing_file_store
assert testing_file_store[0].file.closed