From 7afa5336aed999a62e4943e6000a239585b2e2ea Mon Sep 17 00:00:00 2001
From: Joseph Hackman <josephhackman@gmail.com>
Date: Fri, 3 Jul 2020 22:41:15 -0400
Subject: [PATCH] http: make HEAD method to work with keep-alive

Fixes: https://github.com/nodejs/node/issues/28438

PR-URL: https://github.com/nodejs/node/pull/34231
Reviewed-By: James M Snell <jasnell@gmail.com>
---
 lib/_http_outgoing.js                   |  3 +-
 test/parallel/test-http-reuse-socket.js | 51 +++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 test/parallel/test-http-reuse-socket.js

diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js
index 8b2959986af8e0..50ef063241b173 100644
--- a/lib/_http_outgoing.js
+++ b/lib/_http_outgoing.js
@@ -457,7 +457,8 @@ function _storeHeader(firstLine, headers) {
   }
 
   if (!state.contLen && !state.te) {
-    if (!this._hasBody) {
+    if (!this._hasBody && (this.statusCode === 204 ||
+                           this.statusCode === 304)) {
       // Make sure we don't end the 0\r\n\r\n at the end of the message.
       this.chunkedEncoding = false;
     } else if (!this.useChunkedEncodingByDefault) {
diff --git a/test/parallel/test-http-reuse-socket.js b/test/parallel/test-http-reuse-socket.js
new file mode 100644
index 00000000000000..f5cd002fdbf519
--- /dev/null
+++ b/test/parallel/test-http-reuse-socket.js
@@ -0,0 +1,51 @@
+'use strict';
+const common = require('../common');
+const http = require('http');
+const assert = require('assert');
+const Countdown = require('../common/countdown');
+
+// The HEAD:204, GET:200 is the most pathological test case.
+// GETs following a 204 response with a content-encoding header failed.
+// Responses without bodies and without content-length or encoding caused
+// the socket to be closed.
+const codes = [204, 200, 200, 304, 200];
+const methods = ['HEAD', 'HEAD', 'GET', 'HEAD', 'GET'];
+
+const sockets = [];
+const agent = new http.Agent();
+agent.maxSockets = 1;
+
+const countdown = new Countdown(codes.length, () => server.close());
+
+const server = http.createServer(common.mustCall((req, res) => {
+  const code = codes.shift();
+  assert.strictEqual(typeof code, 'number');
+  assert.ok(code > 0);
+  res.writeHead(code, {});
+  res.end();
+}, codes.length));
+
+function nextRequest() {
+  const request = http.request({
+    port: server.address().port,
+    path: '/',
+    agent: agent,
+    method: methods.shift()
+  }, common.mustCall((response) => {
+    response.on('end', common.mustCall(() => {
+      if (countdown.dec()) {
+        nextRequest();
+      }
+      assert.strictEqual(sockets.length, 1);
+    }));
+    response.resume();
+  }));
+  request.on('socket', common.mustCall((socket) => {
+    if (!sockets.includes(socket)) {
+      sockets.push(socket);
+    }
+  }));
+  request.end();
+}
+
+server.listen(0, common.mustCall(nextRequest));