From cdf3fa241c82f154366d7e175fc6544c76b90d03 Mon Sep 17 00:00:00 2001 From: Shima Ryuhei <65934663+islandryu@users.noreply.github.com> Date: Sat, 5 Apr 2025 00:07:09 +0900 Subject: [PATCH] http2: skip writeHead if stream is closed Fixes: https://github.com/nodejs/node/issues/57416 PR-URL: https://github.com/nodejs/node/pull/57686 Reviewed-By: Luigi Pinca Reviewed-By: Tim Perry Reviewed-By: Matteo Collina Reviewed-By: Rafael Gonzaga Reviewed-By: Jake Yuesong Li --- lib/internal/http2/compat.js | 2 +- ...est-http2-compat-write-head-after-close.js | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-http2-compat-write-head-after-close.js diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index 24370094866..a02d3b0c584 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -706,7 +706,7 @@ class Http2ServerResponse extends Stream { writeHead(statusCode, statusMessage, headers) { const state = this[kState]; - if (state.closed || this.stream.destroyed) + if (state.closed || this.stream.destroyed || this.stream.closed) return this; if (this[kStream].headersSent) throw new ERR_HTTP2_HEADERS_SENT(); diff --git a/test/parallel/test-http2-compat-write-head-after-close.js b/test/parallel/test-http2-compat-write-head-after-close.js new file mode 100644 index 00000000000..b082400537b --- /dev/null +++ b/test/parallel/test-http2-compat-write-head-after-close.js @@ -0,0 +1,23 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) { common.skip('missing crypto'); } +const h2 = require('http2'); + +const server = h2.createServer((req, res) => { + const stream = req.stream; + stream.close(); + res.writeHead(200, { 'content-type': 'text/plain' }); +}); + +server.listen(0, common.mustCall(() => { + const port = server.address().port; + const client = h2.connect(`http://localhost:${port}`); + const req = client.request({ ':path': '/' }); + req.on('response', common.mustNotCall('head after close should not be sent')); + req.on('end', common.mustCall(() => { + client.close(); + server.close(); + })); + req.end(); +}));