Repository navigation
Multipart custom header names containing Content-Type suppress the MIME header #3800
Unanswered
skyon0522-ai
asked this question in
Potential Issue
Replies: 1 comment
|
Confirmed on 0.28.1 from PyPI, explicit and guessed types both get dropped. It's the substring check that came in with the custom multipart headers support (#1936): Lines 151 to 156 in b5addb6 Any key containing "content-type" counts as an override, so Until that lands, put the real type in the headers dict yourself. That path is used as-is: files={
"file": (
"test.txt",
b"<file content>",
None,
{"Content-Type": "application/json", "X-Content-Type": "custom"},
)
} |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
A custom header on a multipart file, such as
X-Content-Type, causes HTTPX to omit the actualContent-Typeof that part. This happens even when the third file-tuple element explicitly supplies the MIME type.Reproduced on current
master,b5addb64f0161ff6bfe94c124ef76f6a1fba5254:The part contains
X-Content-Type: custom, but noContent-Type: application/json. There is no exception; the MIME header is silently omitted. No HTTP request or server is needed to reproduce this, since it occurs while encoding the multipart body.FileField.__init__checks"content-type" in key.lower()when deciding whether the fourth tuple element overrides the MIME type. Matching the complete field name with==preserves case-insensitiveContent-Typeoverrides while keeping similarly named custom headers separate. The same problem affects inferred MIME types. This is separate from the caller-owned mapping mutation reported in discussion #3789.A small candidate changes that comparison and adds regression coverage for prefixed/suffixed names, inferred/explicit types, and mixed-case genuine overrides. Before the change, four regression cases fail and three override controls pass; afterward all 44 multipart tests pass. Formatting, mypy and Ruff pass. The full suite has 1421 passes, two failures and one skip; the unmodified base has 1415 passes with the same two failures and skip (Click's
isolated_filesystemdeprecation and Trio's unclosed-generator warning).Environment: CPython 3.12.3, Ubuntu under WSL, HTTPX 0.28.1 checkout. AI tools assisted the investigation, implementation and local validation. Feedback on the proposed correction is welcome.
The tested patch is available in this exact commit comparison. GitHub rejected pull-request creation with
skyon0522-ai does not have the correct permissions to execute CreatePullRequest. No pull request has been opened.All reactions