From c3212f4b8b5641d9bd1e069c5fc511a16545ea12 Mon Sep 17 00:00:00 2001 From: islandryu Date: Mon, 5 May 2025 17:26:10 +0900 Subject: [PATCH 1/2] http: fix keep-alive not timing out after post-request empty line Fixes: https://github.com/nodejs/node/issues/58140 --- lib/_http_server.js | 2 - .../test-http-keep-alive-empty-line.mjs | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-http-keep-alive-empty-line.mjs diff --git a/lib/_http_server.js b/lib/_http_server.js index e00d3cac0490e5..1da38808c0f8b8 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -916,8 +916,6 @@ function socketOnError(e) { } function onParserExecuteCommon(server, socket, parser, state, ret, d) { - resetSocketTimeout(server, socket, state); - if (ret instanceof Error) { prepareError(ret, parser, d); debug('parse error', ret); diff --git a/test/parallel/test-http-keep-alive-empty-line.mjs b/test/parallel/test-http-keep-alive-empty-line.mjs new file mode 100644 index 00000000000000..60d5a21bd531bd --- /dev/null +++ b/test/parallel/test-http-keep-alive-empty-line.mjs @@ -0,0 +1,41 @@ +import * as common from '../common/index.mjs'; +import assert from 'node:assert'; +import { createServer } from 'node:http'; +import { connect } from 'node:net'; + +const server = createServer({ + connectionsCheckingInterval: 100, + headersTimeout: 100, + keepAliveTimeout: 300 +}, (req, res) => { + res.writeHead(404); + res.end(); + + req.socket.on('close', common.mustCall(() => { + server.close(); + })); +}); + +server.listen(0); + +const client = connect({ + host: 'localhost', + port: server.address().port, +}, () => { + client.write( + 'GET / HTTP/1.1\r\n' + + 'Host: localhost:3000\r\n' + + 'Content-Length: 0\r\n' + + '\r\n' + ); + + setTimeout(() => { + client.write('\r\n'); + }, 100); + + client.on('data', (data) => { + const status = data.toString().split(' ')[1]; + assert.strictEqual(status, '404'); + }); + client.on('end', common.mustCall()); +}); From 350b680fc0868baa857d5aaa6b8f066e10effe4e Mon Sep 17 00:00:00 2001 From: islandryu Date: Wed, 7 May 2025 10:06:01 +0900 Subject: [PATCH 2/2] fix test --- .../test-http-keep-alive-empty-line.mjs | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/test/parallel/test-http-keep-alive-empty-line.mjs b/test/parallel/test-http-keep-alive-empty-line.mjs index 60d5a21bd531bd..a104a0dff2dc25 100644 --- a/test/parallel/test-http-keep-alive-empty-line.mjs +++ b/test/parallel/test-http-keep-alive-empty-line.mjs @@ -16,26 +16,35 @@ const server = createServer({ })); }); -server.listen(0); +server.listen(0, () => { + const client = connect({ + host: 'localhost', + port: server.address().port, + }, () => { + client.write( + 'GET / HTTP/1.1\r\n' + + 'Host: localhost:3000\r\n' + + 'Content-Length: 0\r\n' + + '\r\n' + ); -const client = connect({ - host: 'localhost', - port: server.address().port, -}, () => { - client.write( - 'GET / HTTP/1.1\r\n' + - 'Host: localhost:3000\r\n' + - 'Content-Length: 0\r\n' + - '\r\n' - ); + setTimeout(() => { + client.write('\r\n'); + }, 100); - setTimeout(() => { - client.write('\r\n'); - }, 100); + let responseBuffer = ''; - client.on('data', (data) => { - const status = data.toString().split(' ')[1]; - assert.strictEqual(status, '404'); + client.on('data', (chunk) => { + responseBuffer += chunk.toString(); + + // Check if we've received the full header (ending with \r\n\r\n) + if (responseBuffer.includes('\r\n\r\n')) { + const statusLine = responseBuffer.split('\r\n')[0]; + const status = statusLine.split(' ')[1]; + assert.strictEqual(status, '404'); + client.end(); + } + }); + client.on('end', common.mustCall()); }); - client.on('end', common.mustCall()); });