Skip to content

HTTP client form upload should not send a chunked transfer encoding header on HTTP/3 - #6316

Open
jnbdz wants to merge 1 commit into
eclipse-vertx:masterfrom
SiteNetSoft:issue-5690-h3-multipart-transfer-encoding
Open

HTTP client form upload should not send a chunked transfer encoding header on HTTP/3#6316
jnbdz wants to merge 1 commit into
eclipse-vertx:masterfrom
SiteNetSoft:issue-5690-h3-multipart-transfer-encoding

Conversation

@jnbdz

@jnbdz jnbdz commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Motivation

HttpClientRequest#send(ClientForm) builds the body with Netty's HttpPostRequestEncoder, which produces an HTTP/1.1 request; the encoder headers are then copied on the request, including transfer-encoding: chunked when the form is streamed (file uploads). That header is a connection specific header forbidden by HTTP/2 (RFC 9113 §8.2.2) and HTTP/3 (RFC 9114 §4.2).

HTTP/2 client streams have sanitized it since a5afe84 (5.0.2), but HTTP/3 client streams do not: a chunked multipart form upload over HTTP/3 currently sends transfer-encoding: chunked on the wire (the Vert.x server tolerates it, which is why the existing HTTP/3 upload tests did not catch it).

Fixes #5690.

Changes

  • HttpClientRequestImpl#send(ClientForm): instead of copying the encoder's transfer-encoding: chunked header, the request is switched to chunked mode with setChunked(true). The HTTP/1.1 client connection still writes the header from the chunked flag, HTTP/2 and HTTP/3 never see it — this fixes the problem at the source for every protocol.
  • Http3ClientStream#writeHead: remove a transfer-encoding header before writing the request head, mirroring DefaultHttp2ClientStream, so a manually set header is sanitized as well.

Tests

  • The shared HttpClientFileUploadTest helper now asserts per protocol: HTTP/1.1 uploads carry transfer-encoding: chunked, HTTP/2 and HTTP/3 uploads carry no transfer-encoding header. Without the change, the 8 chunked upload cases of Http3ClientFileUploadTest fail with expected null, but was:<chunked>; HTTP/1.1, HTTP/2, HTTP/2 multiplex and h2c upgrade variants are unaffected.
  • Http3ClientTest#testChunkedTransferEncodingHeaderIsSanitized: a request with a manually set transfer-encoding: chunked header must not have it delivered to the server.

Http1xTest, Http2Test, the http3 and fileupload test packages pass locally.

…eader on HTTP/3

Motivation:

The client multipart form encoder produces an HTTP/1.1 request whose
headers are copied on the HttpClientRequest, including a chunked
transfer-encoding header when the form is streamed. That header is a
connection specific header forbidden by HTTP/2 and HTTP/3. HTTP/2 client
streams sanitize it since a5afe84, however HTTP/3 client streams do not
and a chunked multipart form upload sends transfer-encoding: chunked on
the wire. Fixes eclipse-vertx#5690.

Changes:

Translate the encoder chunked transfer-encoding header into a chunked
request with setChunked(true) instead of copying it: the HTTP/1.1 client
connection still writes the header from the chunked flag while HTTP/2 and
HTTP/3 never see it. Remove a transfer-encoding header in the HTTP/3 client
stream before writing the request head, like the HTTP/2 client stream does.

Assert in the shared client file upload tests that HTTP/1.1 uploads carry
the chunked transfer encoding and that HTTP/2 and HTTP/3 uploads carry no
transfer-encoding header, and add an HTTP/3 client test for a manually set
transfer-encoding header.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HttpClient post MultiPartForm for HTTP/2 sets illegal header transfer-encoding

1 participant