Skip to content

Commit df7de57

Browse files
committedJul 14, 2021
[major] Do not close existing connections
When `WebSocketServer.prototype.close()` is called, stop accepting new connections but do not close the existing ones. If the HTTP/S server was created internally, then close it and emit the `'close'` event when it closes. Otherwise, if client tracking is enabled, then emit the `'close'` event when the number of connections goes down to zero. Otherwise, emit it in the next tick. Refs: #1902
1 parent 78adf5f commit df7de57

File tree

5 files changed

+284
-141
lines changed

5 files changed

+284
-141
lines changed
 

‎doc/ws.md

+8-3
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,14 @@ added when the `clientTracking` is truthy.
207207

208208
### server.close([callback])
209209

210-
Close the HTTP server if created internally, terminate all clients and call
211-
callback when done. If an external HTTP server is used via the `server` or
212-
`noServer` constructor options, it must be closed manually.
210+
Prevent the server from accepting new connections and close the HTTP server if
211+
created internally. If an external HTTP server is used via the `server` or
212+
`noServer` constructor options, it must be closed manually. Existing connections
213+
are not closed automatically. The server emits a `'close'` event when all
214+
connections are closed unless an external HTTP server is used and client
215+
tracking is disabled. In this case the `'close'` event is emitted in the next
216+
tick. The optional callback is called when the `'close'` event occurs and
217+
receives an `Error` if the server is already closed.
213218

214219
### server.handleUpgrade(request, socket, head, callback)
215220

‎lib/websocket-server.js

+36-19
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ class WebSocketServer extends EventEmitter {
111111
}
112112

113113
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
114-
if (options.clientTracking) this.clients = new Set();
114+
if (options.clientTracking) {
115+
this.clients = new Set();
116+
this._shouldEmitClose = false;
117+
}
118+
115119
this.options = options;
116120
this._state = RUNNING;
117121
}
@@ -135,9 +139,10 @@ class WebSocketServer extends EventEmitter {
135139
}
136140

137141
/**
138-
* Close the server.
142+
* Stop the server from accepting new connections and emit the `'close'` event
143+
* when all existing connections are closed.
139144
*
140-
* @param {Function} [cb] Callback
145+
* @param {Function} [cb] A one-time listener for the `'close'` event
141146
* @public
142147
*/
143148
close(cb) {
@@ -151,29 +156,35 @@ class WebSocketServer extends EventEmitter {
151156
if (this._state === CLOSING) return;
152157
this._state = CLOSING;
153158

154-
//
155-
// Terminate all associated clients.
156-
//
157-
if (this.clients) {
158-
for (const client of this.clients) client.terminate();
159-
}
159+
if (this.options.noServer || this.options.server) {
160+
if (this._server) {
161+
this._removeListeners();
162+
this._removeListeners = this._server = null;
163+
}
160164

161-
const server = this._server;
165+
if (this.clients) {
166+
if (!this.clients.size) {
167+
process.nextTick(emitClose, this);
168+
} else {
169+
this._shouldEmitClose = true;
170+
}
171+
} else {
172+
process.nextTick(emitClose, this);
173+
}
174+
} else {
175+
const server = this._server;
162176

163-
if (server) {
164177
this._removeListeners();
165178
this._removeListeners = this._server = null;
166179

167180
//
168-
// Close the http server if it was internally created.
181+
// The HTTP/S server was created internally. Close it, and rely on its
182+
// `'close'` event.
169183
//
170-
if (this.options.port != null) {
171-
server.close(emitClose.bind(undefined, this));
172-
return;
173-
}
184+
server.close(() => {
185+
emitClose(this);
186+
});
174187
}
175-
176-
process.nextTick(emitClose, this);
177188
}
178189

179190
/**
@@ -373,7 +384,13 @@ class WebSocketServer extends EventEmitter {
373384

374385
if (this.clients) {
375386
this.clients.add(ws);
376-
ws.on('close', () => this.clients.delete(ws));
387+
ws.on('close', () => {
388+
this.clients.delete(ws);
389+
390+
if (this._shouldEmitClose && !this.clients.size) {
391+
process.nextTick(emitClose, this);
392+
}
393+
});
377394
}
378395

379396
cb(ws, req);

‎test/sender.test.js

+25
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,31 @@ describe('Sender', () => {
266266
});
267267

268268
describe('#close', () => {
269+
it('throws an error if the first argument is invalid', () => {
270+
const mockSocket = new MockSocket();
271+
const sender = new Sender(mockSocket);
272+
273+
assert.throws(
274+
() => sender.close('error'),
275+
/^TypeError: First argument must be a valid error code number$/
276+
);
277+
278+
assert.throws(
279+
() => sender.close(1004),
280+
/^TypeError: First argument must be a valid error code number$/
281+
);
282+
});
283+
284+
it('throws an error if the message is greater than 123 bytes', () => {
285+
const mockSocket = new MockSocket();
286+
const sender = new Sender(mockSocket);
287+
288+
assert.throws(
289+
() => sender.close(1000, 'a'.repeat(124)),
290+
/^RangeError: The message must not be greater than 123 bytes$/
291+
);
292+
});
293+
269294
it('should consume all data before closing', (done) => {
270295
const perMessageDeflate = new PerMessageDeflate({ threshold: 0 });
271296

‎test/websocket-server.test.js

+62-38
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ describe('WebSocketServer', () => {
7575
},
7676
() => {
7777
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
78+
79+
ws.on('open', ws.close);
7880
}
7981
);
8082

@@ -103,6 +105,8 @@ describe('WebSocketServer', () => {
103105
const port = 1337;
104106
const wss = new WebSocket.Server({ port }, () => {
105107
const ws = new WebSocket(`ws://localhost:${port}`);
108+
109+
ws.on('open', ws.close);
106110
});
107111

108112
wss.on('connection', () => wss.close(done));
@@ -120,12 +124,14 @@ describe('WebSocketServer', () => {
120124

121125
server.listen(0, () => {
122126
const wss = new WebSocket.Server({ server });
123-
const ws = new WebSocket(`ws://localhost:${server.address().port}`);
124127

125128
wss.on('connection', () => {
126-
wss.close();
127129
server.close(done);
128130
});
131+
132+
const ws = new WebSocket(`ws://localhost:${server.address().port}`);
133+
134+
ws.on('open', ws.close);
129135
});
130136
});
131137

@@ -169,7 +175,11 @@ describe('WebSocketServer', () => {
169175
assert.strictEqual(req.url, '/foo?bar=bar');
170176
} else {
171177
assert.strictEqual(req.url, '/');
172-
wss.close();
178+
179+
for (const client of wss.clients) {
180+
client.close();
181+
}
182+
173183
server.close(done);
174184
}
175185
});
@@ -209,30 +219,13 @@ describe('WebSocketServer', () => {
209219
});
210220

211221
describe('#close', () => {
212-
it('does not throw when called twice', (done) => {
222+
it('does not throw if called multiple times', (done) => {
213223
const wss = new WebSocket.Server({ port: 0 }, () => {
224+
wss.on('close', done);
225+
214226
wss.close();
215227
wss.close();
216228
wss.close();
217-
218-
done();
219-
});
220-
});
221-
222-
it('closes all clients', (done) => {
223-
let closes = 0;
224-
const wss = new WebSocket.Server({ port: 0 }, () => {
225-
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
226-
ws.on('close', () => {
227-
if (++closes === 2) done();
228-
});
229-
});
230-
231-
wss.on('connection', (ws) => {
232-
ws.on('close', () => {
233-
if (++closes === 2) done();
234-
});
235-
wss.close();
236229
});
237230
});
238231

@@ -254,6 +247,8 @@ describe('WebSocketServer', () => {
254247

255248
server.listen(0, () => {
256249
const ws = new WebSocket(`ws://localhost:${server.address().port}`);
250+
251+
ws.on('open', ws.close);
257252
});
258253
});
259254

@@ -309,6 +304,16 @@ describe('WebSocketServer', () => {
309304
});
310305
});
311306

307+
it("emits the 'close' event if client tracking is disabled", (done) => {
308+
const wss = new WebSocket.Server({
309+
noServer: true,
310+
clientTracking: false
311+
});
312+
313+
wss.on('close', done);
314+
wss.close();
315+
});
316+
312317
it("emits the 'close' event if the server is already closed", (done) => {
313318
const wss = new WebSocket.Server({ port: 0 }, () => {
314319
wss.close(() => {
@@ -324,7 +329,10 @@ describe('WebSocketServer', () => {
324329
it('returns a list of connected clients', (done) => {
325330
const wss = new WebSocket.Server({ port: 0 }, () => {
326331
assert.strictEqual(wss.clients.size, 0);
332+
327333
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
334+
335+
ws.on('open', ws.close);
328336
});
329337

330338
wss.on('connection', () => {
@@ -404,17 +412,17 @@ describe('WebSocketServer', () => {
404412
const wss = new WebSocket.Server({ noServer: true });
405413

406414
server.on('upgrade', (req, socket, head) => {
407-
wss.handleUpgrade(req, socket, head, (client) =>
408-
client.send('hello')
409-
);
415+
wss.handleUpgrade(req, socket, head, (ws) => {
416+
ws.send('hello');
417+
ws.close();
418+
});
410419
});
411420

412421
const ws = new WebSocket(`ws://localhost:${server.address().port}`);
413422

414423
ws.on('message', (message, isBinary) => {
415424
assert.deepStrictEqual(message, Buffer.from('hello'));
416425
assert.ok(!isBinary);
417-
wss.close();
418426
server.close(done);
419427
});
420428
});
@@ -683,6 +691,7 @@ describe('WebSocketServer', () => {
683691

684692
socket.once('data', (chunk) => {
685693
assert.strictEqual(chunk[0], 0x88);
694+
socket.destroy();
686695
wss.close(done);
687696
});
688697
});
@@ -742,7 +751,6 @@ describe('WebSocketServer', () => {
742751
});
743752

744753
wss.on('connection', () => {
745-
wss.close();
746754
server.close(done);
747755
});
748756

@@ -751,6 +759,8 @@ describe('WebSocketServer', () => {
751759
headers: { Origin: 'https://example.com', foo: 'bar' },
752760
rejectUnauthorized: false
753761
});
762+
763+
ws.on('open', ws.close);
754764
});
755765
});
756766

@@ -762,6 +772,8 @@ describe('WebSocketServer', () => {
762772
},
763773
() => {
764774
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
775+
776+
ws.on('open', ws.close);
765777
}
766778
);
767779

@@ -959,24 +971,30 @@ describe('WebSocketServer', () => {
959971
wss.close(done);
960972
});
961973
});
974+
975+
wss.on('connection', (ws) => {
976+
ws.close();
977+
});
962978
});
963979
});
964980

965981
it("emits the 'headers' event", (done) => {
966982
const wss = new WebSocket.Server({ port: 0 }, () => {
967983
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
968984

969-
wss.on('headers', (headers, request) => {
970-
assert.deepStrictEqual(headers.slice(0, 3), [
971-
'HTTP/1.1 101 Switching Protocols',
972-
'Upgrade: websocket',
973-
'Connection: Upgrade'
974-
]);
975-
assert.ok(request instanceof http.IncomingMessage);
976-
assert.strictEqual(request.url, '/');
985+
ws.on('open', ws.close);
986+
});
977987

978-
wss.on('connection', () => wss.close(done));
979-
});
988+
wss.on('headers', (headers, request) => {
989+
assert.deepStrictEqual(headers.slice(0, 3), [
990+
'HTTP/1.1 101 Switching Protocols',
991+
'Upgrade: websocket',
992+
'Connection: Upgrade'
993+
]);
994+
assert.ok(request instanceof http.IncomingMessage);
995+
assert.strictEqual(request.url, '/');
996+
997+
wss.on('connection', () => wss.close(done));
980998
});
981999
});
9821000
});
@@ -985,6 +1003,8 @@ describe('WebSocketServer', () => {
9851003
it('is disabled by default', (done) => {
9861004
const wss = new WebSocket.Server({ port: 0 }, () => {
9871005
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
1006+
1007+
ws.on('open', ws.close);
9881008
});
9891009

9901010
wss.on('connection', (ws, req) => {
@@ -1016,6 +1036,10 @@ describe('WebSocketServer', () => {
10161036
});
10171037
}
10181038
);
1039+
1040+
wss.on('connection', (ws) => {
1041+
ws.close();
1042+
});
10191043
});
10201044
});
10211045
});

‎test/websocket.test.js

+153-81
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ describe('WebSocket', () => {
105105
});
106106
}
107107
);
108+
109+
wss.on('connection', (ws) => {
110+
ws.close();
111+
});
108112
});
109113

110114
it('throws an error when using an invalid `protocolVersion`', () => {
@@ -230,6 +234,10 @@ describe('WebSocket', () => {
230234
wss.close(done);
231235
};
232236
});
237+
238+
wss.on('connection', (ws) => {
239+
ws.close();
240+
});
233241
});
234242

235243
it('takes into account the data in the sender queue', (done) => {
@@ -258,6 +266,10 @@ describe('WebSocket', () => {
258266
});
259267
}
260268
);
269+
270+
wss.on('connection', (ws) => {
271+
ws.close();
272+
});
261273
});
262274

263275
it('takes into account the data in the socket queue', (done) => {
@@ -526,6 +538,10 @@ describe('WebSocket', () => {
526538
wss.close(done);
527539
});
528540
});
541+
542+
wss.on('connection', (ws) => {
543+
ws.close();
544+
});
529545
});
530546

531547
it("emits a 'ping' event", (done) => {
@@ -534,7 +550,10 @@ describe('WebSocket', () => {
534550
ws.on('ping', () => wss.close(done));
535551
});
536552

537-
wss.on('connection', (ws) => ws.ping());
553+
wss.on('connection', (ws) => {
554+
ws.ping();
555+
ws.close();
556+
});
538557
});
539558

540559
it("emits a 'pong' event", (done) => {
@@ -543,7 +562,10 @@ describe('WebSocket', () => {
543562
ws.on('pong', () => wss.close(done));
544563
});
545564

546-
wss.on('connection', (ws) => ws.pong());
565+
wss.on('connection', (ws) => {
566+
ws.pong();
567+
ws.close();
568+
});
547569
});
548570
});
549571

@@ -977,7 +999,13 @@ describe('WebSocket', () => {
977999
const port = wss.address().port;
9781000
const ws = new WebSocket(`ws://localhost:${port}/?token=qwerty`);
9791001

980-
ws.on('open', () => wss.close(done));
1002+
ws.on('open', () => {
1003+
wss.close(done);
1004+
});
1005+
});
1006+
1007+
wss.on('connection', (ws) => {
1008+
ws.close();
9811009
});
9821010
});
9831011

@@ -986,7 +1014,13 @@ describe('WebSocket', () => {
9861014
const port = wss.address().port;
9871015
const ws = new WebSocket(`ws://localhost:${port}?token=qwerty`);
9881016

989-
ws.on('open', () => wss.close(done));
1017+
ws.on('open', () => {
1018+
wss.close(done);
1019+
});
1020+
});
1021+
1022+
wss.on('connection', (ws) => {
1023+
ws.close();
9901024
});
9911025
});
9921026
});
@@ -1084,7 +1118,10 @@ describe('WebSocket', () => {
10841118
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
10851119

10861120
ws.on('open', () => {
1087-
ws.ping(() => ws.ping());
1121+
ws.ping(() => {
1122+
ws.ping();
1123+
ws.close();
1124+
});
10881125
});
10891126
});
10901127

@@ -1103,7 +1140,10 @@ describe('WebSocket', () => {
11031140
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
11041141

11051142
ws.on('open', () => {
1106-
ws.ping('hi', () => ws.ping('hi', true));
1143+
ws.ping('hi', () => {
1144+
ws.ping('hi', true);
1145+
ws.close();
1146+
});
11071147
});
11081148
});
11091149

@@ -1120,7 +1160,10 @@ describe('WebSocket', () => {
11201160
const wss = new WebSocket.Server({ port: 0 }, () => {
11211161
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
11221162

1123-
ws.on('open', () => ws.ping(0));
1163+
ws.on('open', () => {
1164+
ws.ping(0);
1165+
ws.close();
1166+
});
11241167
});
11251168

11261169
wss.on('connection', (ws) => {
@@ -1144,6 +1187,10 @@ describe('WebSocket', () => {
11441187
wss.close(done);
11451188
});
11461189
});
1190+
1191+
wss.on('connection', (ws) => {
1192+
ws.close();
1193+
});
11471194
});
11481195
});
11491196

@@ -1240,7 +1287,10 @@ describe('WebSocket', () => {
12401287
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
12411288

12421289
ws.on('open', () => {
1243-
ws.pong(() => ws.pong());
1290+
ws.pong(() => {
1291+
ws.pong();
1292+
ws.close();
1293+
});
12441294
});
12451295
});
12461296

@@ -1259,7 +1309,10 @@ describe('WebSocket', () => {
12591309
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
12601310

12611311
ws.on('open', () => {
1262-
ws.pong('hi', () => ws.pong('hi', true));
1312+
ws.pong('hi', () => {
1313+
ws.pong('hi', true);
1314+
ws.close();
1315+
});
12631316
});
12641317
});
12651318

@@ -1276,7 +1329,10 @@ describe('WebSocket', () => {
12761329
const wss = new WebSocket.Server({ port: 0 }, () => {
12771330
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
12781331

1279-
ws.on('open', () => ws.pong(0));
1332+
ws.on('open', () => {
1333+
ws.pong(0);
1334+
ws.close();
1335+
});
12801336
});
12811337

12821338
wss.on('connection', (ws) => {
@@ -1300,6 +1356,10 @@ describe('WebSocket', () => {
13001356
wss.close(done);
13011357
});
13021358
});
1359+
1360+
wss.on('connection', (ws) => {
1361+
ws.close();
1362+
});
13031363
});
13041364
});
13051365

@@ -1413,6 +1473,7 @@ describe('WebSocket', () => {
14131473
ws.on('message', (msg, isBinary) => {
14141474
assert.ok(isBinary);
14151475
ws.send(msg);
1476+
ws.close();
14161477
});
14171478
});
14181479
});
@@ -1432,6 +1493,7 @@ describe('WebSocket', () => {
14321493
wss.on('connection', (ws) => {
14331494
ws.on('message', (msg, isBinary) => {
14341495
ws.send(msg, { binary: isBinary });
1496+
ws.close();
14351497
});
14361498
});
14371499
});
@@ -1443,6 +1505,7 @@ describe('WebSocket', () => {
14431505
ws.on('open', () => {
14441506
ws.send('fragment', { fin: false });
14451507
ws.send('fragment', { fin: true });
1508+
ws.close();
14461509
});
14471510
});
14481511

@@ -1459,7 +1522,10 @@ describe('WebSocket', () => {
14591522
const wss = new WebSocket.Server({ port: 0 }, () => {
14601523
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
14611524

1462-
ws.on('open', () => ws.send(0));
1525+
ws.on('open', () => {
1526+
ws.send(0);
1527+
ws.close();
1528+
});
14631529
});
14641530

14651531
wss.on('connection', (ws) => {
@@ -1488,7 +1554,11 @@ describe('WebSocket', () => {
14881554

14891555
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
14901556

1491-
ws.on('open', () => ws.send(partial));
1557+
ws.on('open', () => {
1558+
ws.send(partial);
1559+
ws.close();
1560+
});
1561+
14921562
ws.on('message', (message, isBinary) => {
14931563
assert.deepStrictEqual(message, buf);
14941564
assert.ok(isBinary);
@@ -1514,7 +1584,11 @@ describe('WebSocket', () => {
15141584

15151585
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
15161586

1517-
ws.on('open', () => ws.send(array.buffer));
1587+
ws.on('open', () => {
1588+
ws.send(array.buffer);
1589+
ws.close();
1590+
});
1591+
15181592
ws.onmessage = (event) => {
15191593
assert.ok(event.data.equals(Buffer.from(array.buffer)));
15201594
wss.close(done);
@@ -1534,7 +1608,10 @@ describe('WebSocket', () => {
15341608
const buf = Buffer.from('foobar');
15351609
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
15361610

1537-
ws.on('open', () => ws.send(buf));
1611+
ws.on('open', () => {
1612+
ws.send(buf);
1613+
ws.close();
1614+
});
15381615

15391616
ws.onmessage = (event) => {
15401617
assert.deepStrictEqual(event.data, buf);
@@ -1561,13 +1638,20 @@ describe('WebSocket', () => {
15611638
});
15621639
});
15631640
});
1641+
1642+
wss.on('connection', (ws) => {
1643+
ws.close();
1644+
});
15641645
});
15651646

15661647
it('works when the `data` argument is falsy', (done) => {
15671648
const wss = new WebSocket.Server({ port: 0 }, () => {
15681649
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
15691650

1570-
ws.on('open', () => ws.send());
1651+
ws.on('open', () => {
1652+
ws.send();
1653+
ws.close();
1654+
});
15711655
});
15721656

15731657
wss.on('connection', (ws) => {
@@ -1743,51 +1827,6 @@ describe('WebSocket', () => {
17431827
});
17441828
});
17451829

1746-
it('throws an error if the first argument is invalid (1/2)', (done) => {
1747-
const wss = new WebSocket.Server({ port: 0 }, () => {
1748-
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
1749-
1750-
ws.on('open', () => {
1751-
assert.throws(
1752-
() => ws.close('error'),
1753-
/^TypeError: First argument must be a valid error code number$/
1754-
);
1755-
1756-
wss.close(done);
1757-
});
1758-
});
1759-
});
1760-
1761-
it('throws an error if the first argument is invalid (2/2)', (done) => {
1762-
const wss = new WebSocket.Server({ port: 0 }, () => {
1763-
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
1764-
1765-
ws.on('open', () => {
1766-
assert.throws(
1767-
() => ws.close(1004),
1768-
/^TypeError: First argument must be a valid error code number$/
1769-
);
1770-
1771-
wss.close(done);
1772-
});
1773-
});
1774-
});
1775-
1776-
it('throws an error if the message is greater than 123 bytes', (done) => {
1777-
const wss = new WebSocket.Server({ port: 0 }, () => {
1778-
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
1779-
1780-
ws.on('open', () => {
1781-
assert.throws(
1782-
() => ws.close(1000, 'a'.repeat(124)),
1783-
/^RangeError: The message must not be greater than 123 bytes$/
1784-
);
1785-
1786-
wss.close(done);
1787-
});
1788-
});
1789-
});
1790-
17911830
it('sends the close status code only when necessary', (done) => {
17921831
let sent;
17931832
const wss = new WebSocket.Server({ port: 0 }, () => {
@@ -2206,7 +2245,11 @@ describe('WebSocket', () => {
22062245
const wss = new WebSocket.Server({ port: 0 }, () => {
22072246
const ws = new WebSocket(`ws://localhost:${wss.address().port}`);
22082247

2209-
ws.addEventListener('open', () => ws.send('hi'));
2248+
ws.addEventListener('open', () => {
2249+
ws.send('hi');
2250+
ws.close();
2251+
});
2252+
22102253
ws.addEventListener('message', (messageEvent) => {
22112254
assert.strictEqual(messageEvent.data, 'hi');
22122255
wss.close(done);
@@ -2262,7 +2305,7 @@ describe('WebSocket', () => {
22622305
ws.addEventListener('message', (messageEvent) => {
22632306
assert.strictEqual(messageEvent.type, 'message');
22642307
assert.strictEqual(messageEvent.target, ws);
2265-
wss.close();
2308+
ws.close();
22662309
});
22672310
ws.addEventListener('close', (closeEvent) => {
22682311
assert.strictEqual(closeEvent.type, 'close');
@@ -2275,7 +2318,7 @@ describe('WebSocket', () => {
22752318
assert.strictEqual(errorEvent.target, ws);
22762319
assert.strictEqual(errorEvent.error, err);
22772320

2278-
done();
2321+
wss.close(done);
22792322
});
22802323
});
22812324

@@ -2292,7 +2335,10 @@ describe('WebSocket', () => {
22922335
};
22932336
});
22942337

2295-
wss.on('connection', (ws) => ws.send(new Uint8Array(4096)));
2338+
wss.on('connection', (ws) => {
2339+
ws.send(new Uint8Array(4096));
2340+
ws.close();
2341+
});
22962342
});
22972343

22982344
it('ignores `binaryType` for text messages', (done) => {
@@ -2307,7 +2353,10 @@ describe('WebSocket', () => {
23072353
};
23082354
});
23092355

2310-
wss.on('connection', (ws) => ws.send('foo'));
2356+
wss.on('connection', (ws) => {
2357+
ws.send('foo');
2358+
ws.close();
2359+
});
23112360
});
23122361

23132362
it('allows to update `binaryType` on the fly', (done) => {
@@ -2337,7 +2386,10 @@ describe('WebSocket', () => {
23372386
ws.onopen = () => {
23382387
testType('nodebuffer', () => {
23392388
testType('arraybuffer', () => {
2340-
testType('fragments', () => wss.close(done));
2389+
testType('fragments', () => {
2390+
ws.close();
2391+
wss.close(done);
2392+
});
23412393
});
23422394
});
23432395
};
@@ -2361,14 +2413,15 @@ describe('WebSocket', () => {
23612413
const wss = new WebSocket.Server({ server });
23622414

23632415
wss.on('connection', () => {
2364-
wss.close();
23652416
server.close(done);
23662417
});
23672418

23682419
server.listen(0, () => {
23692420
const ws = new WebSocket(`wss://127.0.0.1:${server.address().port}`, {
23702421
rejectUnauthorized: false
23712422
});
2423+
2424+
ws.on('open', ws.close);
23722425
});
23732426
});
23742427

@@ -2392,7 +2445,6 @@ describe('WebSocket', () => {
23922445
wss.on('connection', () => {
23932446
assert.ok(success);
23942447
server.close(done);
2395-
wss.close();
23962448
});
23972449

23982450
server.listen(0, () => {
@@ -2401,6 +2453,8 @@ describe('WebSocket', () => {
24012453
key: fs.readFileSync('test/fixtures/client-key.pem'),
24022454
rejectUnauthorized: false
24032455
});
2456+
2457+
ws.on('open', ws.close);
24042458
});
24052459
});
24062460

@@ -2435,7 +2489,6 @@ describe('WebSocket', () => {
24352489
assert.deepStrictEqual(message, Buffer.from('foobar'));
24362490
assert.ok(!isBinary);
24372491
server.close(done);
2438-
wss.close();
24392492
});
24402493
});
24412494

@@ -2444,7 +2497,10 @@ describe('WebSocket', () => {
24442497
rejectUnauthorized: false
24452498
});
24462499

2447-
ws.on('open', () => ws.send('foobar'));
2500+
ws.on('open', () => {
2501+
ws.send('foobar');
2502+
ws.close();
2503+
});
24482504
});
24492505
});
24502506

@@ -2460,6 +2516,7 @@ describe('WebSocket', () => {
24602516
ws.on('message', (message, isBinary) => {
24612517
assert.ok(isBinary);
24622518
ws.send(message);
2519+
ws.close();
24632520
});
24642521
});
24652522

@@ -2474,7 +2531,6 @@ describe('WebSocket', () => {
24742531
assert.ok(isBinary);
24752532

24762533
server.close(done);
2477-
wss.close();
24782534
});
24792535
});
24802536
}).timeout(4000);
@@ -2712,7 +2768,11 @@ describe('WebSocket', () => {
27122768
perMessageDeflate: { threshold: 0 }
27132769
});
27142770

2715-
ws.on('open', () => ws.send('hi', { compress: true }));
2771+
ws.on('open', () => {
2772+
ws.send('hi', { compress: true });
2773+
ws.close();
2774+
});
2775+
27162776
ws.on('message', (message, isBinary) => {
27172777
assert.deepStrictEqual(message, Buffer.from('hi'));
27182778
assert.ok(!isBinary);
@@ -2745,7 +2805,11 @@ describe('WebSocket', () => {
27452805
perMessageDeflate: { threshold: 0 }
27462806
});
27472807

2748-
ws.on('open', () => ws.send(array, { compress: true }));
2808+
ws.on('open', () => {
2809+
ws.send(array, { compress: true });
2810+
ws.close();
2811+
});
2812+
27492813
ws.on('message', (message, isBinary) => {
27502814
assert.deepStrictEqual(message, Buffer.from(array.buffer));
27512815
assert.ok(isBinary);
@@ -2779,7 +2843,11 @@ describe('WebSocket', () => {
27792843
perMessageDeflate: { threshold: 0 }
27802844
});
27812845

2782-
ws.on('open', () => ws.send(array.buffer, { compress: true }));
2846+
ws.on('open', () => {
2847+
ws.send(array.buffer, { compress: true });
2848+
ws.close();
2849+
});
2850+
27832851
ws.on('message', (message, isBinary) => {
27842852
assert.deepStrictEqual(message, Buffer.from(array.buffer));
27852853
assert.ok(isBinary);
@@ -2918,7 +2986,11 @@ describe('WebSocket', () => {
29182986
perMessageDeflate: false
29192987
});
29202988

2921-
ws.on('open', () => ws.send('hi', { compress: true }));
2989+
ws.on('open', () => {
2990+
ws.send('hi', { compress: true });
2991+
ws.close();
2992+
});
2993+
29222994
ws.on('message', (message, isBinary) => {
29232995
assert.deepStrictEqual(message, Buffer.from('hi'));
29242996
assert.ok(!isBinary);
@@ -2934,10 +3006,10 @@ describe('WebSocket', () => {
29343006
});
29353007

29363008
it('calls the callback if the socket is closed prematurely', (done) => {
3009+
const called = [];
29373010
const wss = new WebSocket.Server(
29383011
{ perMessageDeflate: true, port: 0 },
29393012
() => {
2940-
const called = [];
29413013
const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
29423014
perMessageDeflate: { threshold: 0 }
29433015
});
@@ -2966,15 +3038,15 @@ describe('WebSocket', () => {
29663038
);
29673039
});
29683040
});
2969-
2970-
ws.on('close', () => {
2971-
assert.deepStrictEqual(called, [1, 2]);
2972-
wss.close(done);
2973-
});
29743041
}
29753042
);
29763043

29773044
wss.on('connection', (ws) => {
3045+
ws.on('close', () => {
3046+
assert.deepStrictEqual(called, [1, 2]);
3047+
wss.close(done);
3048+
});
3049+
29783050
ws._socket.end();
29793051
});
29803052
});

0 commit comments

Comments
 (0)
Please sign in to comment.