Fix multipart/form-data boundary issue in HTTP Call node (#23903)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Guangdong Liu
2025-08-14 10:01:27 +08:00
committed by GitHub
parent cc4d82f932
commit d4756ba659
2 changed files with 19 additions and 8 deletions

View File

@@ -279,14 +279,22 @@ class Executor:
headers[authorization.config.header] = authorization.config.api_key or ""
# Handle Content-Type for multipart/form-data requests
# Fix for issue #22880: Missing boundary when using multipart/form-data
# Fix for issue #23829: Missing boundary when using multipart/form-data
body = self.node_data.body
if body and body.type == "form-data":
# For multipart/form-data with files, let httpx handle the boundary automatically
# by not setting Content-Type header when files are present
if not self.files or all(f[0] == "__multipart_placeholder__" for f in self.files):
# Only set Content-Type when there are no actual files
# This ensures httpx generates the correct boundary
# For multipart/form-data with files (including placeholder files),
# remove any manually set Content-Type header to let httpx handle
# For multipart/form-data, if any files are present (including placeholder files),
# we must remove any manually set Content-Type header. This is because httpx needs to
# automatically set the Content-Type and boundary for multipart encoding whenever files
# are included, even if they are placeholders, to avoid boundary issues and ensure correct
# file upload behaviour. Manually setting Content-Type can cause httpx to fail to set the
# boundary, resulting in invalid requests.
if self.files:
# Remove Content-Type if it was manually set to avoid boundary issues
headers = {k: v for k, v in headers.items() if k.lower() != "content-type"}
else:
# No files at all, set Content-Type manually
if "content-type" not in (k.lower() for k in headers):
headers["Content-Type"] = "multipart/form-data"
elif body and body.type in BODY_TYPE_TO_CONTENT_TYPE:

View File

@@ -243,8 +243,6 @@ def test_executor_with_form_data():
# Check the executor's data
assert executor.method == "post"
assert executor.url == "https://api.example.com/upload"
assert "Content-Type" in executor.headers
assert "multipart/form-data" in executor.headers["Content-Type"]
assert executor.params is None
assert executor.json is None
# '__multipart_placeholder__' is expected when no file inputs exist,
@@ -252,6 +250,11 @@ def test_executor_with_form_data():
assert executor.files == [("__multipart_placeholder__", ("", b"", "application/octet-stream"))]
assert executor.content is None
# After fix for #23829: When placeholder files exist, Content-Type is removed
# to let httpx handle Content-Type and boundary automatically
headers = executor._assembling_headers()
assert "Content-Type" not in headers or "multipart/form-data" not in headers.get("Content-Type", "")
# Check that the form data is correctly loaded in executor.data
assert isinstance(executor.data, dict)
assert "text_field" in executor.data