Socket.io: 使用自定义名称空间时,中间件(.use)不会发出连接

创建于 2017-10-11  ·  12评论  ·  资料来源: socketio/socket.io

你想要:

  • [x]报告错误
  • []请求功能

当前行为

将自定义名称空间与中间件一起使用时,服务器会收到“连接”事件,但客户端不会收到“连接”事件。

这有效:

io.use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

这不起作用:

// Following works, but client does not receive 'connect' or 'connection':
io.of('/admin').use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

网站说明

也很奇怪:如果我执行以下代码,那么即使/ admin的中间件未运行,默认名称空间也不会发出任何“ connect”事件。

io.on('connection', socket => {
  console.log('client connected');
});

io.of('/admin').use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

要解决此问题,我必须将.use((socket, next) => { next(); })到默认名称空间。 但是/ admin仍然不会发出“连接”。

重现步骤(如果当前行为是错误)

请看上面

预期行为

连接后,客户端应收到“连接”

设定

  • 作业系统:macOS Sierra 10.12.6
  • 浏览器:Chrome
  • 节点:v8.2.1
  • NPM:5.4.2
  • socket.io版本:2.0.3

最有用的评论

@JanisRubens感谢您提供详尽的报告:+1 https://github.com/socketio/socket.io/pull/3197修复

所有12条评论

嗨! 您如何初始化客户端? 以下内容似乎对我有用:

io.use((socket, next) => {
   console.log('(default) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(default) client connected');
});

// Following works, but client does not receive 'connect' or 'connection':
io.of('/admin').use((socket, next) => {
   console.log('(admin) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(admin) client connected');
});

// client
const socket = require('socket.io-client')('http://localhost:3000/admin');

socket.on('connect', onConnect);

function onConnect(){
  console.log('connect ' + socket.id);
}

输出(小提琴):

server listening on port 3000
(default) middleware running...
(default) client connected
(admin) middleware running...
(admin) client connected

不,它对我不起作用。 完整代码,工作示例:

服务器:

let express = require('express'),
    app = new express(),
    server = app.listen(3005, 'localhost'),
    io = require('socket.io')(server)
;

io.on('connection', socket => {
  console.log('client connected');
});

io.of('/admin')
  .use((socket, next) => {
    console.log('middleware running...');
    next();
  })
  .on('connection', socket => {
    console.log('admin connected');
  })
;

客户:

$(function () {
    let socket;

    $('#btn-connect').click(() => {
        console.log('Connecting ...');

        socket = io('http://localhost:3005');

        socket.on('connect', () => {
            console.log(`Connected to ${url} with id: ${socket.id}`);
        });

        socket.on('disconnect', reason => {
            console.log(`Disconnected. Reason: ${reason}`);
        });
    });

    $('#btn-connect-admin').click(() => {
        console.log('Connecting to admin ...');

        socket = io('http://localhost:3005/admin');

        socket.on('connect', () => {
            console.log(`Connected to ${url} with id: ${socket.id}`);
        });

        socket.on('disconnect', reason => {
            console.log(`Disconnected. Reason: ${reason}`);
        });
    });
});

如果我删除了中间件,我可以同时连接两者。 如果仅将中间件添加到admin,则默认名称空间或/ admin都不会发生连接事件。

服务器正确显示所有内容:

  • 客户端连接
  • 中间件正在运行...
  • 管理员已连接

没有? :(

@MickL对此有任何更新吗?
也遇到了同样的问题。
不知道您是否发现了这一点。 唯一的连接问题是与根名称空间有关,如果您还为根路径添加了中间件,则该中间件也将能够与其连接。 (这可以是一个快速解决方法,待定)

可以归结为以下几种情况:

If namespace A('/)' and B('/otherPath') has no middleware it connects to both fine;
If namespace A has no middleware and B has. It connects to A on server side, but client sides 'connect' event listener never gets called, B namespace connects fine;
If namespace A and B both has middleware it can connect to both;

不,我使用了一种解决方法。 代替:

io.of('/admin')
  .use((socket, next) => {
    if(tokenValid()) {
       next();
    } else {
      next(new Error('Authentication error'));
    }
  })
  .on('connection', socket => {
    console.log('admin connected');
  })
;

我写:

io.of('/admin')
  .on('connection', socket => {
    if(!tokenValid()) {
       socket.disconnect();
    }

    console.log('admin connected');
  })
;

我花了很多钱,似乎客户端确实连接到服务器,但是客户端没有获得连接事件。

我想这可以工作。 遗憾的是,我们无法正确地将中间件用于其预期用途。

@darrachequesne您提供和测试的示例与报告的问题不同。

您需要从默认名称空间中删除中间件,然后尝试连接。

像这样:

io.on('connection', socket => {
  console.log('(default) client connected');
});

io.of('/admin').use((socket, next) => {
   console.log('(admin) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(admin) client connected');
});

// client
const socket = require('socket.io-client')('http://localhost:3000/');
const socket_two = require('socket.io-client')('http://localhost:3000/admin');
//wont trigger
socket.on('connect', onConnect);
//will trigger
socket_two.on('connect', onConnect);

function onConnect(){
  console.log('connect ' + socket.id);
}

现在应该失败了。
请参阅上面的说明,了解其有效/无效的情况。

干杯。

@JanisRubens感谢您提供详尽的报告:+1 https://github.com/socketio/socket.io/pull/3197修复

我仍然面对这个!
在创建名称空间之前,客户端会接收事件,但在添加名称空间并使用中间件之后,客户端不会接收任何事件,但是框架会显示在chrome上。

+1

@adeelhussain @ElioTohm您使用的是哪个版本? 您能用小提琴来重现案件吗?

使用socketio v2.1.1和socket.io-redis v5.2.0
我会尝试用小提琴尽快复制它

此页面是否有帮助?
0 / 5 - 0 等级