diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 7bd30eeaf10a10..b585d61cd1db92 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1129,6 +1129,8 @@ class Http2Session extends EventEmitter { if (!socket._handle || !socket._handle.isStreamBase) { socket = new JSStreamSocket(socket); } + socket.on('error', socketOnError); + socket.on('close', socketOnClose); // No validation is performed on the input parameters because this // constructor is not exported directly for users. @@ -2909,9 +2911,6 @@ function connectionListener(socket) { return; } - socket.on('error', socketOnError); - socket.on('close', socketOnClose); - // Set up the Session const session = new ServerHttp2Session(options, socket, this); @@ -3132,9 +3131,6 @@ function connect(authority, options, listener) { } } - socket.on('error', socketOnError); - socket.on('close', socketOnClose); - const session = new ClientHttp2Session(options, socket); session[kAuthority] = `${options.servername || host}:${port}`; diff --git a/test/parallel/test-http2-client-jsstream-destroy.js b/test/parallel/test-http2-client-jsstream-destroy.js new file mode 100644 index 00000000000000..f881eac47aa809 --- /dev/null +++ b/test/parallel/test-http2-client-jsstream-destroy.js @@ -0,0 +1,55 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const h2 = require('http2'); +const tls = require('tls'); +const fixtures = require('../common/fixtures'); +const { Duplex } = require('stream'); + +const server = h2.createSecureServer({ + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem') +}); + +class JSSocket extends Duplex { + constructor(socket) { + super({ emitClose: true }); + socket.on('close', () => this.destroy()); + socket.on('data', (data) => this.push(data)); + this.socket = socket; + } + + _write(data, encoding, callback) { + this.socket.write(data, encoding, callback); + } + + _read(size) { + } + + _final(cb) { + cb(); + } +} + +server.listen(0, common.mustCall(function() { + const socket = tls.connect({ + rejectUnauthorized: false, + host: 'localhost', + port: this.address().port, + ALPNProtocols: ['h2'] + }, () => { + const proxy = new JSSocket(socket); + const client = h2.connect(`https://localhost:${this.address().port}`, { + createConnection: () => proxy + }); + const req = client.request(); + + setTimeout(() => socket.destroy(), common.platformTimeout(100)); + setTimeout(() => client.close(), common.platformTimeout(200)); + setTimeout(() => server.close(), common.platformTimeout(300)); + + req.on('close', common.mustCall(() => { })); + }); +}));