Skip to content

bug: multipart/formdata boundary is not sent in header #885

@Kludex

Description

@Kludex

Originally opened by @Anton-Shutik on 2025-03-03 14:01:37 in encode/httpx

python==3.12
httpx==0.28.1

I'm having and issue while sending data with "Content-Type": "multipart/form-data", while sending same data with "Content-Type": "multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW" works fine.

Take a look at full example:

from curlify2 import Curlify

headers = {
    "Authorization": f"Bearer {self.api_token}",
    "Content-Type": "multipart/form-data",
    # "Content-Type": "multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW",
}

# Prepare form data as tuples for multipart/form-data
files = [("image_url", (None, url)) for url in photo_urls]

async with httpx.AsyncClient() as client:
    try:
        req = await client.post(endpoint, headers=headers, files=files, )
        response = Curlify(req.request)
        print("#" * 20, "Start", "#" * 20)
        print(response.to_curl())
        print("#" * 20, "End", "#" * 20)

Prints this:

# #################### Start ####################
# curl -X POST -H "host: <3rdparty>" -H "accept: */*" -H "accept-encoding: gzip, deflate, zstd" -H "connection: keep-alive" -H "user-agent: python-httpx/0.28.1" -H "authorization: Bearer <token>" -H "content-type: multipart/form-data" -H "content-length: 186" -d '--d21e39e0c438fedf66c71fa2514f0ac5
# Content-Disposition: form-data; name="image_url"
# 
# https://<storage>/logo_3.webp
# --d21e39e0c438fedf66c71fa2514f0ac5--
# ' https://<3rdparty>/endpoint
# #################### End ####################
# Fails with: fastapi.exceptions.HTTPException: 400: error: {"error":{"code":400,"message":"missing form parameter 'image_url'"}}

Now, with the boundary (just switched them in headers dict) explicitly provided in the header. Works fine

# #################### Start ####################
# curl -X POST -H "host: <3rd party>" -H "accept: */*" -H "accept-encoding: gzip, deflate, zstd" -H "connection: keep-alive" -H "user-agent: python-httpx/0.28.1" -H "authorization: Bearer <token>" -H "content-type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW" -H "content-length: 188" -d '--WebKitFormBoundary7MA4YWxkTrZu0gW
# Content-Disposition: form-data; name="image_url"
# 
# https://alxdev.blob.core.windows.net/volvo-v90/logo_3.webp
# --WebKitFormBoundary7MA4YWxkTrZu0gW--
# ' https://<3rdparty>/endpoints
# #################### End ####################

Notice, that in the second case boundary is present in the header, while in the first isn't. I think this is a bug

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions