socket.io-client
socket.io-client copied to clipboard
Subsequent new connections to previously closed namespaces results in new connections
Describe the bug
When using namespaces, new "channels" are created over a shared connection as expected.
But if a namespace calls socket.disconnect(); then later a new instance connects to the same namespace, a whole new connection will be made instead of multiplexing.
Before I get into it, I did find these existing issues: https://github.com/socketio/socket.io-client/issues/1514 https://github.com/socketio/socket.io-client/issues/1364 https://github.com/socketio/socket.io-client/issues/866 And finally the root cause: https://github.com/socketio/socket.io/issues/1956
After researching all of that, I believe this is a bug or more likely an unintended behavior. I understand #1956 and why opening a new connection to the same currently connected namespace is a thing, BUT, I really do not think this should happen if the previous channel was CLOSED.
I have a use case where my server code is using dynamic namespaces with regex, and the client is connecting to these dynamic namespaces using id's of various documents the user could browser to. So if my user loads document A, then B, then A again, it creates a new underlying connection. Since we have hundreds of possible id's and dynamic namespaces, caching each possible socket is not practical. This is just silly.
To Reproduce
(this code is not using dynamic namespaces as mentioned above, but it still demonstrates the issue)
Socket.IO server version: 4.5.1
Server
import { Server } from "socket.io";
const io = new Server(3000, {});
io.of("/namespace-a", (socket) => {
// some logic
});
io.of("/namespace-b", (socket) => {
// some logic
});
Client
import { io } from "socket.io-client";
const a = io("/namespace-a", {});
const b = io("/namespace-b", {});
// some time later
b.disconnect();
// some time later create a NEW connection to namespace-b
const newB = io("/namespace-b", {});
Expected behavior I expect all namespace channels to utilize a single connection.
Platform:
- Device: Mac. Chrome & Safari
- OS: MacOS & Docker Node 16.14.x
Simple workaround if this doesn't get addressed:
When manually disconnecting, remove the socket from the manager
socket.disconnect();
// @ts-ignore due to private property access
delete socket.io.nsps[socket.nsp];
Now when you create a new instance to the same namespace, multiplexing will work
For future readers:
I think trying to fix this problem will likely cause undesirable side effects, so I'm going to close this as "won't fix".
As a workaround, you can use the Manager directly:
import { Manager } from "socket.io-client";
const manager = new Manager("wss://example.com");
const a = manager.socket("/namespace-a", {});
const b = manager.socket("/namespace-b", {});
// some time later
b.disconnect();
// some time later create a NEW connection to namespace-b
const newB = manager.socket("/namespace-b", {});
See also:
- https://github.com/socketio/socket.io-client/pull/1545
- https://github.com/socketio/socket.io-client/commit/b7dd891e890461d33a104ca9187d5cd30d6f76af
- https://github.com/socketio/socket.io-client/commit/46213a647ea0d4453b00bca09268f69ffd259509