From b21b649ea246eec87af121ffe676c876b001de05 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Thu, 6 Oct 2022 08:08:02 +0200 Subject: [PATCH] fix: handle late HTTP server binding The following example: ```js const io = new Server(); // without port or HTTP server instrument(io, { auth: false }); io.listen(3000); ``` will now work properly. Related: https://github.com/socketio/socket.io-admin-ui/issues/49 --- lib/index.ts | 19 ++++++++++++++++--- test/index.ts | 11 +++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 83f894c..5beb75f 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -142,7 +142,7 @@ const initStatsEmitter = ( "server_stats", Object.assign({}, baseStats, { uptime: process.uptime(), - clientsCount: io.engine.clientsCount, + clientsCount: io.engine?.clientsCount, pollingClientsCount: io._pollingClientsCount, aggregatedEvents: io._eventBuffer.getValuesAndClear(), namespaces, @@ -489,7 +489,7 @@ const registerEngineListeners = (io: Server) => { io._eventBuffer = new EventBuffer(); io._pollingClientsCount = 0; - io.engine.on("connection", (rawSocket: any) => { + const onConnection = (rawSocket: any) => { io._eventBuffer.push("rawConnection"); if (rawSocket.transport.name === "polling") { @@ -524,7 +524,20 @@ const registerEngineListeners = (io: Server) => { rawSocket.on("close", (reason: string) => { io._eventBuffer.push("rawDisconnection", reason); }); - }); + }; + + if (io.engine) { + io.engine.on("connection", onConnection); + } else { + // io.engine might be undefined if instrument() is called before binding the Socket.IO server to the HTTP server + process.nextTick(() => { + if (io.engine) { + io.engine.on("connection", onConnection); + } else { + debug("WARN: no engine"); + } + }); + } }; export function instrument(io: Server, opts: Partial) { diff --git a/test/index.ts b/test/index.ts index ff91704..851f795 100644 --- a/test/index.ts +++ b/test/index.ts @@ -67,6 +67,17 @@ describe("Socket.IO Admin (server instrumentation)", () => { }); }); + it("should work with io.listen()", () => { + const io = new Server(); + + instrument(io, { + auth: false, + }); + + io.listen(0); + io.close(); + }); + describe("authentication", () => { it("prevents anonymous connection", (done) => { instrument(io, {