Skip to content

Conversation

fredericDelaporte
Copy link
Contributor

@fredericDelaporte fredericDelaporte commented Oct 5, 2025

This relates to...

A discrepancy in behavior about empty POST request, when enabling or not enabling H2.
See #4594.

Rationale

This adds two tests:

  • [Fetch] Empty POST without h2 has Content-Length
  • [Fetch] Empty POST with h2 has no Content-Length

According to RFC 9110:

A user agent SHOULD send Content-Length in a request when the method defines a meaning for enclosed content and it is not sending Transfer-Encoding. For example, a user agent normally sends Content-Length in a POST request even when the value is 0 (indicating empty content).

So, the behavior of Undici sending a 0 Content-Length on empty POST request when H2 is not enabled is recommended by the RFC, while its behavior of sending no Content-Length on such requests when H2 is enabled does not match the recommendation. (It is still compliant since that is a "SHOULD", not a "MUST".)

Whether this should be changed or not, I do not know. Is there a good reason for this behavior with H2?

For your information, some servers cannot receive empty POST requests without a Content-Length. That is the case of Internet Information Server (IIS), the default web server of Windows OSes. Windows OSes underlying http.sys rejects such requests with a 411 Length required response.

Changes

Add two tests to demonstrate the current behavior of Undici.

Features

N/A

Bug Fixes

N/A

Breaking Changes and Deprecations

None

Status

@fredericDelaporte
Copy link
Contributor Author

I have not checked other verbs which semantics imply a content, like PUT, PATCH. If changing this behavior about POST, they should likely be checked too.

@codecov-commenter
Copy link

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.93%. Comparing base (96fb72c) to head (ff97f0c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4612      +/-   ##
==========================================
- Coverage   92.93%   92.93%   -0.01%     
==========================================
  Files         106      106              
  Lines       32973    32973              
==========================================
- Hits        30645    30644       -1     
- Misses       2328     2329       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

mcollina added a commit that referenced this pull request Oct 5, 2025
This change aligns HTTP/2 behavior with HTTP/1 by ensuring that empty
POST requests (and other methods that expect payloads) include a
Content-Length: 0 header.

According to RFC 9110, a user agent SHOULD send Content-Length in a
request when the method defines a meaning for enclosed content, even
when the value is 0 (indicating empty content).

Previously, HTTP/2 requests would omit the Content-Length header for
empty POST requests, while HTTP/1 requests correctly included it. This
inconsistency could cause issues with servers like IIS that reject
empty POST requests without a Content-Length header (returning 411
Length Required).

Changes:
- Modified lib/dispatcher/client-h2.js to only omit Content-Length when
  both contentLength is 0 AND the method doesn't expect a payload
- Updated the assertion to allow contentLength === 0 without a body
- Updated test to verify Content-Length: 0 is sent for empty POST with H2
- Updated test comments to reflect the corrected behavior

Fixes #4594
Ref #4612

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Matteo Collina <[email protected]>
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.

2 participants