Socket.io: Middleware (.use) não emite conexão ao usar um namespace personalizado

Criado em 11 out. 2017  ·  12Comentários  ·  Fonte: socketio/socket.io

Você quer:

  • [x] relatar um bug
  • [] solicitar um recurso

Comportamento atual

Ao usar um namespace personalizado com um middleware, o servidor obtém um evento de 'conexão', mas o cliente não recebe o evento de 'conexão'.

Isso funciona:

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

Isso não funciona:

// 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');
});

Sitenotes

Também muito estranho: se eu fizer o código a seguir, o namespace padrão não emitirá nenhum evento de 'conexão', mesmo que o middleware de / admin não esteja em execução.

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');
});

Para corrigir isso, tenho que adicionar .use((socket, next) => { next(); }) ao namespace padrão. Mas ainda assim / admin não emite 'conectar'.

Etapas para reproduzir (se o comportamento atual for um bug)

Por favor veja acima

Comportamento esperado

Na conexão, o cliente deve receber 'conectar'

Configuração

  • SO: macOS Sierra 10.12.6
  • navegador: Chrome
  • Nó: v8.2.1
  • NPM: 5.4.2
  • versão socket.io: 2.0.3
bug

Comentários muito úteis

@JanisRubens Obrigado pelo relatório detalhado: +1 https://github.com/socketio/socket.io/pull/3197

Todos 12 comentários

Oi! Como você está inicializando o cliente? O seguinte parece funcionar para mim:

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);
}

Resultado ( violino ):

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

Não, não está funcionando para mim. Código completo, exemplo de trabalho:

Servidor:

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');
  })
;

Cliente:

$(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}`);
        });
    });
});

Se eu remover o middleware, posso me conectar a ambos. Se eu adicionar o middleware apenas para admin, não recebo nenhum evento de conexão no namespace padrão nem / admin.

O servidor mostra tudo corretamente:

  • cliente conectado
  • middleware em execução ...
  • administrador conectado

Nada? :(

@MickL Alguma atualização sobre isso?
Também tive o mesmo problema.
Não tenho certeza se você viu isso. O único problema de conexão é com o namespace raiz e se você adicionar um middleware também para o caminho raiz, ele também poderá se conectar a ele. (isso pode ser uma solução rápida tbh)

Tudo se resume aos seguintes cenários:

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;

Não, eu usei uma solução alternativa. Ao invés de:

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

Eu escrevi:

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

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

Gastei muito nisso e parece que o cliente se conecta ao servidor, mas o cliente não obtém o evento de conexão.

Eu acho que isso pode funcionar. Mas é uma pena que não possamos usar o middleware corretamente para o uso pretendido.

@darrachequesne O exemplo que você forneceu e testou não é conforme o problema relatado.

Você precisa remover o middleware do namespace padrão e, em seguida, tentar se conectar.

Como isso:

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);
}

Agora deve falhar.
Veja os casos em que funciona / não funciona acima.

Felicidades.

@JanisRubens Obrigado pelo relatório detalhado: +1 https://github.com/socketio/socket.io/pull/3197

Eu ainda estou enfrentando isso!
Antes de criar o namespace, o cliente recebe eventos, mas depois de adicionar o namespace e usar o middleware, o cliente não está recebendo nenhum evento, no entanto, os frames estavam sendo exibidos no cromo.

+1

@adeelhussain @ElioTohm qual versão você está usando? Você consegue reproduzir o caso com o violino ?

usando socketio v2.1.1 e socket.io-redis v5.2.0
vou tentar reproduzi-lo com violino o mais rápido possível

Esta página foi útil?
0 / 5 - 0 avaliações