Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http: return Content-Length header for HEADs #56681

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

qwerzl
Copy link

@qwerzl qwerzl commented Jan 21, 2025

In the current http library, all responses without body will not return the Content-Length header.

Fixes: #56680

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Jan 21, 2025
@qwerzl qwerzl changed the title fix(http): return Content-Length header for HEADs http: return Content-Length header for HEADs Jan 21, 2025
@geeksilva97
Copy link
Contributor

Can you add a test that covers this change?

Copy link

codecov bot commented Jan 21, 2025

Codecov Report

Attention: Patch coverage is 50.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 89.20%. Comparing base (fdad2fa) to head (ece7877).
Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
lib/_http_outgoing.js 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #56681   +/-   ##
=======================================
  Coverage   89.20%   89.20%           
=======================================
  Files         662      662           
  Lines      191899   191934   +35     
  Branches    36940    36951   +11     
=======================================
+ Hits       171184   171224   +40     
  Misses      13546    13546           
+ Partials     7169     7164    -5     
Files with missing lines Coverage Δ
lib/_http_outgoing.js 95.15% <50.00%> (-0.08%) ⬇️

... and 33 files with indirect coverage changes

In the current http library, all responses without body will not return
the Content-Length header.

Fixes: nodejs#56680
@qwerzl qwerzl force-pushed the fix/head-content-length branch from 4183136 to 8c4c5fc Compare January 22, 2025 02:28
@qwerzl
Copy link
Author

qwerzl commented Jan 22, 2025

Can you add a test that covers this change?

@geeksilva97 Sure! I've modified the test file for HEADs to make sure that Content-Length is received. Also I've changed the message of the first commit to adhere to the guideline.

Copy link
Contributor

@LiviaMedeiros LiviaMedeiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, the specs do not require us to include this header.

8.6. Content-Length says:

A server MAY send a Content-Length header field in a response to a HEAD request (Section 9.3.2); a server MUST NOT send Content-Length in such a response unless its field value equals the decimal number of octets that would have been sent in the content of a response if the same request had used the GET method.

9.3.2. HEAD says:

The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request method had been GET. However, a server MAY omit header fields for which a value is determined only while generating the content. For example, some servers buffer a dynamic response to GET until a minimum amount of data is generated so that they can more efficiently delimit small responses or make late decisions with regard to content selection. Such a response to GET might contain Content-Length and Vary fields, for example, that are not generated within a HEAD response. These minor inconsistencies are considered preferable to generating and discarding the content for a HEAD request, since HEAD is usually requested for the sake of efficiency.

This PR aligns with the recommendations, but we might need to revisit this once HEAD will not touch the body and therefore will not know much about it.

The code LGTM with fixing linter error.

Also it would be great to have more specific test for this (for example, HEAD -> HEAD -> GET -> GET -> HEAD sequence of requests for different response bodies, making sure the value of Content-Length stays correct.

@@ -18,6 +19,8 @@ server.on('listening', common.mustCall(function() {
method: 'HEAD',
path: '/'
}, common.mustCall(function(res) {
assert.notStrictEqual(res.headers['content-length'], undefined, 'Expected Content-Length header to be present');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe check for an actual value rather than just making sure it's not undefined...?

Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little worried this change might add some incorrect extra stuff at the end of HEAD replies which clients might interpret as body.

@@ -547,7 +547,7 @@ function _storeHeader(firstLine, headers) {
}

if (!state.contLen && !state.te) {
if (!this._hasBody) {
if (!this._hasBody && this.req.method !== 'HEAD') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm understanding the logic correctly, the first if condition applies to those that should return neither of the Transfer-Encoding and Content-Length headers. While it's true for other requests that don't have a body, HEADs should match the 3rd condition (i.e. the !state.trailer && !this._removedContLen && typeof this._contentLength === 'number' one).

Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments above. Can we add a test that check that the RAW http message is correct, i.e. no extra tralining line delimiters etc...

@mcollina mcollina added the needs-citgm PRs that need a CITGM CI run. label Jan 22, 2025
@mcollina
Copy link
Member

We should do a quick check if we are breaking anything in the ecosystem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. needs-citgm PRs that need a CITGM CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[http]: Missing Content-Length Header when Responding to HEAD Requests
6 participants