diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 4462fa639317f0..751e8b189b2462 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -3374,6 +3374,9 @@ class Http2SecureServer extends TLSServer { this.headersTimeout = 60_000; // Minimum between 60 seconds or requestTimeout this.requestTimeout = 300_000; // 5 minutes this.connectionsCheckingInterval = 30_000; // 30 seconds + this.shouldUpgradeCallback = function() { + return this.listenerCount('upgrade') > 0; + }; this.on('listening', setupConnectionsTracking); } if (typeof requestListener === 'function') diff --git a/test/common/websocket-server.js b/test/common/websocket-server.js index a3b12ab8d30d49..7f2447396972f7 100644 --- a/test/common/websocket-server.js +++ b/test/common/websocket-server.js @@ -8,9 +8,10 @@ const crypto = require('crypto'); class WebSocketServer { constructor({ port = 0, + server, }) { this.port = port; - this.server = http.createServer(); + this.server = server || http.createServer(); this.clients = new Set(); this.server.on('upgrade', this.handleUpgrade.bind(this)); @@ -44,6 +45,8 @@ class WebSocketServer { const opcode = buffer[0] & 0x0f; if (opcode === 0x8) { + // Send a minimal close frame in response: + socket.write(Buffer.from([0x88, 0x00])); socket.end(); this.clients.delete(socket); return; diff --git a/test/parallel/test-http2-allow-http1-upgrade-ws.js b/test/parallel/test-http2-allow-http1-upgrade-ws.js new file mode 100644 index 00000000000000..028dc4e4cde71c --- /dev/null +++ b/test/parallel/test-http2-allow-http1-upgrade-ws.js @@ -0,0 +1,39 @@ +// Flags: --expose-internals +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +if (!common.hasCrypto) common.skip('missing crypto'); + +const http2 = require('http2'); + +const undici = require('internal/deps/undici/undici'); +const WebSocketServer = require('../common/websocket-server'); + +(async function main() { + const server = http2.createSecureServer({ + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + allowHTTP1: true, + }); + + server.on('request', common.mustNotCall()); + new WebSocketServer({ server }); // Handles websocket 'upgrade' events + + await new Promise((resolve) => server.listen(0, resolve)); + + await new Promise((resolve, reject) => { + const ws = new WebSocket(`wss://localhost:${server.address().port}`, { + dispatcher: new undici.EnvHttpProxyAgent({ + connect: { rejectUnauthorized: false } + }) + }); + ws.addEventListener('open', common.mustCall(() => { + ws.close(); + resolve(); + })); + ws.addEventListener('error', reject); + }); + + server.close(); +})().then(common.mustCall());