Skip to content

Commit c5d910a

Browse files
pimterrytargos
authored andcommitted
http2: fix allowHttp1+Upgrade, broken by shouldUpgradeCallback
This is required to use HTTP/1 websockets on an HTTP/2 server, which is fairly common as websockets over HTTP/2 is much less widely supported. This was broken by the recent shouldUpgradeCallback HTTP/1 addition, which wasn't correctly added to the corresponding allowHttp1 part of the HTTP/2 implementation. PR-URL: #59924 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 6e586a1 commit c5d910a

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

lib/internal/http2/core.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,6 +3374,9 @@ class Http2SecureServer extends TLSServer {
33743374
this.headersTimeout = 60_000; // Minimum between 60 seconds or requestTimeout
33753375
this.requestTimeout = 300_000; // 5 minutes
33763376
this.connectionsCheckingInterval = 30_000; // 30 seconds
3377+
this.shouldUpgradeCallback = function() {
3378+
return this.listenerCount('upgrade') > 0;
3379+
};
33773380
this.on('listening', setupConnectionsTracking);
33783381
}
33793382
if (typeof requestListener === 'function')

test/common/websocket-server.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ const crypto = require('crypto');
88
class WebSocketServer {
99
constructor({
1010
port = 0,
11+
server,
1112
}) {
1213
this.port = port;
13-
this.server = http.createServer();
14+
this.server = server || http.createServer();
1415
this.clients = new Set();
1516

1617
this.server.on('upgrade', this.handleUpgrade.bind(this));
@@ -44,6 +45,8 @@ class WebSocketServer {
4445
const opcode = buffer[0] & 0x0f;
4546

4647
if (opcode === 0x8) {
48+
// Send a minimal close frame in response:
49+
socket.write(Buffer.from([0x88, 0x00]));
4750
socket.end();
4851
this.clients.delete(socket);
4952
return;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
const common = require('../common');
5+
const fixtures = require('../common/fixtures');
6+
if (!common.hasCrypto) common.skip('missing crypto');
7+
8+
const http2 = require('http2');
9+
10+
const undici = require('internal/deps/undici/undici');
11+
const WebSocketServer = require('../common/websocket-server');
12+
13+
(async function main() {
14+
const server = http2.createSecureServer({
15+
key: fixtures.readKey('agent1-key.pem'),
16+
cert: fixtures.readKey('agent1-cert.pem'),
17+
allowHTTP1: true,
18+
});
19+
20+
server.on('request', common.mustNotCall());
21+
new WebSocketServer({ server }); // Handles websocket 'upgrade' events
22+
23+
await new Promise((resolve) => server.listen(0, resolve));
24+
25+
await new Promise((resolve, reject) => {
26+
const ws = new WebSocket(`wss://localhost:${server.address().port}`, {
27+
dispatcher: new undici.EnvHttpProxyAgent({
28+
connect: { rejectUnauthorized: false }
29+
})
30+
});
31+
ws.addEventListener('open', common.mustCall(() => {
32+
ws.close();
33+
resolve();
34+
}));
35+
ws.addEventListener('error', reject);
36+
});
37+
38+
server.close();
39+
})().then(common.mustCall());

0 commit comments

Comments
 (0)