Skip to content

Commit b04fa64

Browse files
fix(sio): allow to join a room in a middleware (uws)
Related: - #4810 - #5139
1 parent 7085f0e commit b04fa64

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

packages/socket.io/lib/namespace.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
AllButLast,
1111
Last,
1212
DecorateAcknowledgementsWithMultipleResponses,
13-
DecorateAcknowledgements,
1413
RemoveAcknowledgements,
1514
EventNamesWithAck,
1615
FirstNonErrorArg,
@@ -135,11 +134,23 @@ export class Namespace<
135134
>
136135
> {
137136
public readonly name: string;
137+
138+
/**
139+
* A map of currently connected sockets.
140+
*/
138141
public readonly sockets: Map<
139142
SocketId,
140143
Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>
141144
> = new Map();
142145

146+
/**
147+
* A map of currently connecting sockets.
148+
*/
149+
private _preConnectSockets: Map<
150+
SocketId,
151+
Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>
152+
> = new Map();
153+
143154
public adapter: Adapter;
144155

145156
/** @private */
@@ -327,6 +338,8 @@ export class Namespace<
327338
debug("adding socket to nsp %s", this.name);
328339
const socket = await this._createSocket(client, auth);
329340

341+
this._preConnectSockets.set(socket.id, socket);
342+
330343
if (
331344
// @ts-ignore
332345
this.server.opts.connectionStateRecovery?.skipMiddlewares &&
@@ -394,7 +407,7 @@ export class Namespace<
394407
socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>,
395408
) => void,
396409
) {
397-
// track socket
410+
this._preConnectSockets.delete(socket.id);
398411
this.sockets.set(socket.id, socket);
399412

400413
// it's paramount that the internal `onconnect` logic
@@ -417,11 +430,7 @@ export class Namespace<
417430
_remove(
418431
socket: Socket<ListenEvents, EmitEvents, ServerSideEvents, SocketData>,
419432
): void {
420-
if (this.sockets.has(socket.id)) {
421-
this.sockets.delete(socket.id);
422-
} else {
423-
debug("ignoring remove for %s", socket.id);
424-
}
433+
this.sockets.delete(socket.id) || this._preConnectSockets.delete(socket.id);
425434
}
426435

427436
/**

packages/socket.io/lib/uws.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export function patchAdapter(app /* : TemplatedApp */) {
1414
Adapter.prototype.addAll = function (id, rooms) {
1515
const isNew = !this.sids.has(id);
1616
addAll.call(this, id, rooms);
17-
const socket: Socket = this.nsp.sockets.get(id);
17+
const socket: Socket =
18+
this.nsp.sockets.get(id) || this.nsp._preConnectSockets.get(id);
1819
if (!socket) {
1920
return;
2021
}
@@ -34,7 +35,8 @@ export function patchAdapter(app /* : TemplatedApp */) {
3435

3536
Adapter.prototype.del = function (id, room) {
3637
del.call(this, id, room);
37-
const socket: Socket = this.nsp.sockets.get(id);
38+
const socket: Socket =
39+
this.nsp.sockets.get(id) || this.nsp._preConnectSockets.get(id);
3840
if (socket && socket.conn.transport.name === "websocket") {
3941
// @ts-ignore
4042
const sessionId = socket.conn.id;

packages/socket.io/test/middleware.ts

+9
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,22 @@ describe("middleware", () => {
197197
io.use((socket, next) => {
198198
expect(socket.connected).to.be(false);
199199
expect(socket.disconnected).to.be(true);
200+
201+
expect(io.of("/").sockets.size).to.eql(0);
202+
// @ts-expect-error
203+
expect(io.of("/")._preConnectSockets.size).to.eql(1);
204+
200205
next();
201206
});
202207

203208
io.on("connection", (socket) => {
204209
expect(socket.connected).to.be(true);
205210
expect(socket.disconnected).to.be(false);
206211

212+
expect(io.of("/").sockets.size).to.eql(1);
213+
// @ts-expect-error
214+
expect(io.of("/")._preConnectSockets.size).to.eql(0);
215+
207216
success(done, io, clientSocket);
208217
});
209218
});

packages/socket.io/test/uws.ts

+28-3
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ describe("socket.io with uWebSocket.js-based engine", () => {
5353
});
5454

5555
const partialDone = createPartialDone(done, 4);
56-
client.on("connect", partialDone);
56+
client.once("connect", partialDone);
5757
clientWSOnly.once("connect", partialDone);
58-
clientPollingOnly.on("connect", partialDone);
59-
clientCustomNamespace.on("connect", partialDone);
58+
clientPollingOnly.once("connect", partialDone);
59+
clientCustomNamespace.once("connect", partialDone);
6060
});
6161

6262
afterEach(() => {
@@ -176,6 +176,31 @@ describe("socket.io with uWebSocket.js-based engine", () => {
176176
io.except("room2").emit("hello");
177177
});
178178

179+
it("should work when joining a room in a middleware", (done) => {
180+
io.use((socket, next) => {
181+
socket.join("test");
182+
next();
183+
});
184+
185+
client.disconnect().connect();
186+
clientPollingOnly.disconnect().connect();
187+
clientWSOnly.disconnect().connect();
188+
clientCustomNamespace.disconnect().connect();
189+
190+
const partialDone = createPartialDone(done, 3);
191+
192+
client.on("hello", partialDone);
193+
clientWSOnly.on("hello", partialDone);
194+
clientPollingOnly.on("hello", partialDone);
195+
clientCustomNamespace.on("hello", shouldNotHappen(done));
196+
197+
io.on("connection", () => {
198+
if (io.of("/").sockets.size === 3) {
199+
io.to("test").emit("hello");
200+
}
201+
});
202+
});
203+
179204
it("should work even after leaving room", (done) => {
180205
const partialDone = createPartialDone(done, 2);
181206

0 commit comments

Comments
 (0)