diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index 464f1141066c3a..adf6b1da628881 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -568,6 +568,11 @@ class Http2ServerResponse extends Stream { if (this[kStream].headersSent) throw new ERR_HTTP2_HEADERS_SENT(); + // If the stream is destroyed, we return false, + // like require('http'). + if (this.stream.destroyed) + return false; + if (typeof statusMessage === 'string') statusMessageWarn(); diff --git a/test/parallel/test-http2-compat-write-head-destroyed.js b/test/parallel/test-http2-compat-write-head-destroyed.js new file mode 100644 index 00000000000000..4576119ee7d435 --- /dev/null +++ b/test/parallel/test-http2-compat-write-head-destroyed.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const http2 = require('http2'); + +// Check that writeHead, write and end do not crash in compatibility mode + +const server = http2.createServer(common.mustCall((req, res) => { + // destroy the stream first + req.stream.destroy(); + + res.writeHead(200); + res.write('hello '); + res.end('world'); +})); + +server.listen(0, common.mustCall(() => { + const client = http2.connect(`http://localhost:${server.address().port}`); + + const req = client.request(); + req.on('response', common.mustNotCall()); + req.on('close', common.mustCall((arg) => { + client.close(); + server.close(); + })); + req.resume(); +}));