Skip to content

Commit 31da417

Browse files
authored
[fix] Make server.handleUpgrade() work with any duplex stream (#2165)
1 parent 347aab6 commit 31da417

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

lib/websocket.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,13 @@ class WebSocket extends EventEmitter {
223223
receiver.on('ping', receiverOnPing);
224224
receiver.on('pong', receiverOnPong);
225225

226-
socket.setTimeout(0);
227-
socket.setNoDelay();
226+
// These methods may not be available if `socket` is actually just a stream:
227+
if (socket.setTimeout) {
228+
socket.setTimeout(0);
229+
}
230+
if (socket.setNoDelay) {
231+
socket.setNoDelay();
232+
}
228233

229234
if (head.length > 0) socket.unshift(head);
230235

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"eslint-config-prettier": "^9.0.0",
5959
"eslint-plugin-prettier": "^5.0.0",
6060
"mocha": "^8.4.0",
61+
"native-duplexpair": "^1.0.0",
6162
"nyc": "^15.0.0",
6263
"prettier": "^3.0.0",
6364
"utf-8-validate": "^6.0.0"

test/websocket-server.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const path = require('path');
1010
const net = require('net');
1111
const fs = require('fs');
1212
const os = require('os');
13+
const DuplexPair = require('native-duplexpair');
1314

1415
const Sender = require('../lib/sender');
1516
const WebSocket = require('..');
@@ -514,6 +515,35 @@ describe('WebSocketServer', () => {
514515
});
515516
});
516517
});
518+
519+
it('can complete a WebSocket upgrade over any duplex stream', (done) => {
520+
const server = http.createServer();
521+
522+
server.listen(0, () => {
523+
const wss = new WebSocket.Server({ noServer: true });
524+
525+
server.on('upgrade', (req, socket, head) => {
526+
// Put a stream between the raw socket and our websocket processing:
527+
const { socket1: stream1, socket2: stream2 } = new DuplexPair();
528+
socket.pipe(stream1);
529+
stream1.pipe(socket);
530+
531+
// Pass the other side of the stream as the socket to upgrade:
532+
wss.handleUpgrade(req, stream2, head, (ws) => {
533+
ws.send('hello');
534+
ws.close();
535+
});
536+
});
537+
538+
const ws = new WebSocket(`ws://localhost:${server.address().port}`);
539+
540+
ws.on('message', (message, isBinary) => {
541+
assert.deepStrictEqual(message, Buffer.from('hello'));
542+
assert.ok(!isBinary);
543+
server.close(done);
544+
});
545+
});
546+
});
517547
});
518548

519549
describe('#completeUpgrade', () => {

0 commit comments

Comments
 (0)