Skip to content

Comments

http: include Content-Length in HEAD responses for keep-alive#61919

Open
erdinccurebal wants to merge 1 commit intonodejs:mainfrom
erdinccurebal:fix/head-response-content-length
Open

http: include Content-Length in HEAD responses for keep-alive#61919
erdinccurebal wants to merge 1 commit intonodejs:mainfrom
erdinccurebal:fix/head-response-content-length

Conversation

@erdinccurebal
Copy link

Summary

HEAD responses from http.createServer do not include a Content-Length header by default when res.end() is called without explicit headers. This breaks HTTP keep-alive for HEAD requests because the client-side HTTP parser cannot determine message boundaries.

GET responses already include Content-Length: 0 by default. This change applies the same behavior to HEAD (and other bodyless) responses.

Before

GET / β†’ headers: { 'content-length': '0', connection: 'keep-alive', ... }
HEAD / β†’ headers: { connection: 'keep-alive', ... }  // missing content-length!

After

GET / β†’ headers: { 'content-length': '0', connection: 'keep-alive', ... }
HEAD / β†’ headers: { 'content-length': '0', connection: 'keep-alive', ... }

Changes

  • lib/_http_outgoing.js: In _storeHeader(), when the response has no body (!this._hasBody), also emit Content-Length header if the content length is known and was not explicitly removed by the user.
  • test/parallel/test-http-head-response-content-length-keep-alive.js: New test verifying that both GET and HEAD responses include Content-Length: 0 when res.end() is called.

Reproduction

const http = require('http');
const server = http.createServer((req, res) => res.end());
server.listen(2333);
const agent = new http.Agent({ keepAlive: true });
http.request({ port: 2333, method: 'HEAD', agent }, (res) => {
  console.log(res.headers); // no content-length β†’ keep-alive broken
}).end();

Fixes: #28438

When an HTTP server responds to a HEAD request with res.end(),
the response does not include a Content-Length header by default.
This causes the HTTP parser on the client side to be unable to
determine message boundaries, which breaks keep-alive connections
for HEAD requests.

GET responses already include Content-Length: 0 by default when
res.end() is called without data. This change applies the same
behavior to HEAD responses (and other bodyless responses) by
adding Content-Length when known and not explicitly removed.

Fixes: nodejs#28438
@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 Feb 21, 2026
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

http server respond with inappropriate default headers for HEAD method

3 participants