Socket.io: Middleware (.use) no emite connect cuando se usa un espacio de nombres personalizado

Creado en 11 oct. 2017  ·  12Comentarios  ·  Fuente: socketio/socket.io

Tú quieres:

  • [x] informar un error
  • [] solicitar una función

Comportamiento actual

Cuando se usa un espacio de nombres personalizado con un middleware, el servidor obtiene un evento de "conexión", pero el cliente no recibe el evento de "conexión".

Esto funciona:

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

Esto no 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

También es muy extraño: si hago el siguiente código, el espacio de nombres predeterminado no emite ningún evento de 'conexión', incluso aunque el middleware de / admin no se esté ejecutando.

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 solucionar este problema, tengo que agregar .use((socket, next) => { next(); }) al espacio de nombres predeterminado. Pero aún / admin no emite 'conectar'.

Pasos para reproducir (si el comportamiento actual es un error)

Por favor ver arriba

Comportamiento esperado

Al conectarse, el cliente debe recibir 'conectar'

Preparar

  • SO: macOS Sierra 10.12.6
  • navegador: Chrome
  • Nodo: v8.2.1
  • NPM: 5.4.2
  • versión socket.io: 2.0.3
bug

Comentario más útil

@JanisRubens Gracias por el informe detallado: +1:, finalmente pude reproducirlo. Corregido por https://github.com/socketio/socket.io/pull/3197

Todos 12 comentarios

¡Hola! ¿Cómo está inicializando el cliente? Lo siguiente parece funcionar para mí:

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

Salida ( violín ):

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

No, no me está funcionando. Código completo, ejemplo de trabajo:

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

Si elimino el middleware, puedo conectarme a ambos. Si agrego el middleware solo al administrador, no obtengo ningún evento de conexión en el espacio de nombres predeterminado ni / admin.

El servidor muestra todo correctamente:

  • cliente conectado
  • middleware ejecutándose ...
  • administrador conectado

¿Nada? :(

@MickL ¿ Alguna actualización sobre esto?
También encontré el mismo problema.
No estoy seguro de haber visto esto. El único problema de conexión es con el espacio de nombres raíz y si agrega un middleware también para la ruta raíz, también podrá conectarse a él. (esto puede ser una solución rápida tbh)

Se reduce a los siguientes escenarios:

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;

No, utilicé una solución alternativa. En vez de:

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

Escribí:

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

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

Gasté mucho en esto y parece que el cliente se conecta al servidor, pero el cliente no obtiene el evento de conexión.

Supongo que esto puede funcionar. Pero es una pena que no podamos utilizar el middleware correctamente para el uso previsto.

@darrachequesne El ejemplo que proporcionó y en el que probó no corresponde al problema informado.

Debe eliminar el middleware del espacio de nombres predeterminado y luego intentar conectarse.

Me gusta esto:

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

Ahora debería fallar.
Vea los casos en los que funciona / no funciona arriba.

Salud.

@JanisRubens Gracias por el informe detallado: +1:, finalmente pude reproducirlo. Corregido por https://github.com/socketio/socket.io/pull/3197

¡Todavía estoy enfrentando esto!
Antes de crear el espacio de nombres, el cliente recibe eventos, pero después de agregar el espacio de nombres y usar middleware, el cliente no recibe ningún evento, pero los marcos se muestran en Chrome.

+1

@adeelhussain @ElioTohm ¿ qué versión estás usando? ¿Eres capaz de reproducir el caso con el violín ?

usando socketio v2.1.1 y socket.io-redis v5.2.0
Intentaré reproducirlo con violín lo antes posible

¿Fue útil esta página
0 / 5 - 0 calificaciones