Skip to content

Commit 0731c0d

Browse files
authored
fix: clean up child namespace when client is rejected in middleware (#4773)
Related: #4772
1 parent 03046a6 commit 0731c0d

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

Diff for: lib/socket.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,6 @@ export class Socket<
758758
}
759759

760760
this._cleanup();
761-
this.nsp._remove(this);
762761
this.client._remove(this);
763762
this.connected = false;
764763
this.emitReserved("disconnect", reason, description);
@@ -772,6 +771,7 @@ export class Socket<
772771
*/
773772
_cleanup() {
774773
this.leaveAll();
774+
this.nsp._remove(this);
775775
this.join = noop;
776776
}
777777

Diff for: package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/namespaces.ts

+70
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,76 @@ describe("namespaces", () => {
653653
io.of(/^\/dynamic-\d+$/);
654654
});
655655

656+
it("should NOT clean up namespace when cleanupEmptyChildNamespaces is OFF and client is rejected in middleware", (done) => {
657+
const io = new Server(0, { cleanupEmptyChildNamespaces: false });
658+
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
659+
next(new Error("You shall not pass!"));
660+
});
661+
const c1 = createClient(io, "/dynamic-101");
662+
663+
c1.on("connect", () => {
664+
done(new Error("Should not connect"));
665+
});
666+
667+
c1.on("connect_error", () => {
668+
setTimeout(() => {
669+
expect(io._nsps.has("/dynamic-101")).to.be(true);
670+
expect(io._nsps.get("/dynamic-101")!.sockets.size).to.be(0);
671+
success(done, io, c1);
672+
}, 100);
673+
});
674+
});
675+
676+
it("should clean up namespace when cleanupEmptyChildNamespaces is ON and client is rejected in middleware", (done) => {
677+
const io = new Server(0, { cleanupEmptyChildNamespaces: true });
678+
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
679+
next(new Error("You shall not pass!"));
680+
});
681+
const c1 = createClient(io, "/dynamic-101");
682+
683+
c1.on("connect", () => {
684+
done(new Error("Should not connect"));
685+
});
686+
687+
c1.on("connect_error", () => {
688+
setTimeout(() => {
689+
expect(io._nsps.has("/dynamic-101")).to.be(false);
690+
success(done, io, c1);
691+
}, 100);
692+
});
693+
});
694+
695+
it("should NOT clean up namespace when cleanupEmptyChildNamespaces is ON and client is rejected in middleware but there are other clients connected", (done) => {
696+
const io = new Server(0, { cleanupEmptyChildNamespaces: true });
697+
let clientIdxToReject = 0;
698+
io.of(/^\/dynamic-\d+$/).use((socket, next) => {
699+
if (clientIdxToReject) {
700+
next(new Error("You shall not pass!"));
701+
} else {
702+
next();
703+
}
704+
clientIdxToReject++;
705+
});
706+
const c1 = createClient(io, "/dynamic-101");
707+
708+
c1.on("connect", () => {
709+
const c2 = createClient(io, "/dynamic-101");
710+
c2.on("connect", () => {
711+
done(new Error("Client 2 should not connect"));
712+
});
713+
c2.on("connect_error", () => {
714+
setTimeout(() => {
715+
expect(io._nsps.has("/dynamic-101")).to.be(true);
716+
expect(io._nsps.get("/dynamic-101")!.sockets.size).to.be(1);
717+
success(done, io, c1, c2);
718+
}, 100);
719+
});
720+
});
721+
c1.on("connect_error", () => {
722+
done(new Error("Client 1 should not get an error"));
723+
});
724+
});
725+
656726
it("should attach a child namespace to its parent upon manual creation", () => {
657727
const io = new Server(0);
658728
const parentNamespace = io.of(/^\/dynamic-\d+$/);

0 commit comments

Comments
 (0)