From f64dc24f83a7f73775c587530fe71bb28acb371d Mon Sep 17 00:00:00 2001 From: Roozbeh Yadollahi Date: Tue, 28 Oct 2025 17:07:24 -0400 Subject: [PATCH] [Fix] [Issue 13533]: Multiple regressions in the handling of forms & form validation --- fastapi/dependencies/utils.py | 3 ++- tests/test_form_regression.py | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/test_form_regression.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index aa06dd2a9..c8a058745 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -930,8 +930,9 @@ async def _extract_form_body( value = serialize_sequence_value(field=field, value=results) if value is not None: values[field.alias] = value + processed_fields = {field.alias for field in body_fields} for key, value in received_body.items(): - if key not in values: + if key not in processed_fields and key not in values: values[key] = value return values diff --git a/tests/test_form_regression.py b/tests/test_form_regression.py new file mode 100644 index 000000000..61f9a6109 --- /dev/null +++ b/tests/test_form_regression.py @@ -0,0 +1,41 @@ +from typing import Optional + +import pytest +from fastapi import FastAPI, File, Form +from fastapi.testclient import TestClient +from typing_extensions import Annotated + +app = FastAPI() + + +@app.post("/") +def root( + file: Annotated[Optional[bytes], File()] = None, + form: Annotated[Optional[str], Form(embed=True)] = None, +): + return {"file": file, "form": form} + + +client = TestClient(app) + + +@pytest.mark.parametrize( + "file_data, form_data, expected_response", + [ + (None, None, {"file": None, "form": None}), + ("", None, {"file": None, "form": None}), + (None, "", {"file": None, "form": None}), + ("", "", {"file": None, "form": None}), + ("file", "form", {"file": "file", "form": "form"}), + ], +) +def test_empty_string_to_none(file_data, form_data, expected_response): + data = {} + if file_data is not None: + data["file"] = file_data + if form_data is not None: + data["form"] = form_data + + response = client.post("/", data=data) + assert response.status_code == 200 + assert response.json() == expected_response