使用带中间件的动态命名空间时Socket.io重复处理首个客户端
Socket.io动态命名空间中间件异常:重复调用首个客户端Socket对象
异常现象
在Socket.io中注册动态命名空间时,中间件会重复输出首个客户端的Cookie信息,而非对应新连接客户端的内容;仅保留首个客户端连接时,输出结果正常。
复现环境
- Socket.io服务端/客户端 4.5.4
- Node.js v16.15.0
复现代码
const { io } = require('socket.io-client'); const { Server } = require('socket.io'); const server = new Server(4321, {}); function middleware(socket, next) { console.log(socket.nsp.name, socket.handshake.headers.cookie); } server.on('new_namespace', (namespace) => { namespace.use(middleware); }) const nsps = server.of(/^\/\w+$/); const clientOne = io.connect('http://localhost:4321/firstNamespace', { extraHeaders: { Cookie: "client=one" } }); const clientTwo = io.connect('http://localhost:4321/secondNamespace', { extraHeaders: { Cookie: "client=two" } }); const clientThree = io.connect('http://localhost:4321/thirdNamespace', { extraHeaders: { Cookie: "client=three" } });
运行输出
/firstNamespace client=one /secondNamespace client=one /thirdNamespace client=one
原因分析与解决方案
异常原因
原代码错误地通过new_namespace事件为每个动态生成的命名空间绑定中间件。Socket.io中,正则匹配的动态命名空间由server.of(/^\/\w+$/)返回的DynamicNamespace统一管理,new_namespace事件会在每个具体命名空间(如/firstNamespace)创建时触发,但此时绑定中间件会导致Socket.io内部复用首个客户端的socket上下文,从而输出错误的握手信息。
解决方案
直接给动态命名空间实例绑定中间件,而非通过new_namespace事件逐个绑定:
const { io } = require('socket.io-client'); const { Server } = require('socket.io'); const server = new Server(4321, {}); function middleware(socket, next) { console.log(socket.nsp.name, socket.handshake.headers.cookie); next(); // 必须调用next()完成中间件流程,否则客户端连接会挂起 } // 直接为动态命名空间绑定中间件 const dynamicNsp = server.of(/^\/\w+$/); dynamicNsp.use(middleware); const clientOne = io.connect('http://localhost:4321/firstNamespace', { extraHeaders: { Cookie: "client=one" } }); const clientTwo = io.connect('http://localhost:4321/secondNamespace', { extraHeaders: { Cookie: "client=two" } }); const clientThree = io.connect('http://localhost:4321/thirdNamespace', { extraHeaders: { Cookie: "client=three" } });
修改后控制台会输出正确结果:
/firstNamespace client=one /secondNamespace client=two /thirdNamespace client=three
内容的提问来源于stack exchange,提问作者Carcigenicate
相关产品推荐
相关产品推荐

