Redis, Node.js y Socket.io: autenticación de servidor cruzado y comprensión de node.js
Tengo una aplicación de una sola página ejecutándose en Rails y Backbone.js. Estoy usando Node.js a través de Redis para enviar y sincronizar datos a los clientes. Estoy tratando de entender, asegurar y optimizar las comunicaciones de sockets.
Al escribir con console.log, veo algunas líneas de registro (console.log('Redis connection on ..')
) se están duplicando (ver más abajo).
¿Alguien me puede explicar por qué? ¿Hay algunos comportamientos específicos de Node.js que no entiendo, a través de la implementación de mi código?
Aquí está mi código Node.js:
var io = require('socket.io').listen(3003);
var redis = require('redis');
var cookie = require("cookie");
var redis_subs = redis.createClient(6379, "localhost");
var redis_auth = redis.createClient(6379, "localhost");
var authenticated = false;
var authentication_status = function (status) {
if (status === true) {
console.log('Authentication status is true.');
}
else {
console.log('Authentication status is false.');
}
authenticated = status;
};
redis_subs.subscribe('application_channel');
io.configure(function () {
io.set('authorization', function (data, callback) {
console.log('Cross authentication...');
if (data.headers.cookie) {
data.cookie = cookie.parse(data.headers.cookie);
data.sessionID = data.cookie['_validation_token_key'];
redis_auth.hget(["sessionStore", data.sessionID], function (err, session) {
if (err || !session) {
console.log('Socket.io authorization say false');
return callback(authentication_status(false), false);
}
else {
data.session = JSON.parse(session);
console.log('Socket.io authorization say true');
return callback(authentication_status(true), true);
}
});
}
else {
console.log('Socket.io authorization say false');
return callback(authentication_status(false), false);
}
});
});
io.on('connection', function(socket){
if (socket.handshake.session) {
var user_socket_channel = socket.handshake.session['user_socket_channel']
redis_subs.on('message', function(redis_channel, rawdata) {
console.log('Redis connection on '+redis_channel);
console.log('Handshaked Session, authenticated user. All channels allowed.');
var data = JSON.parse(rawdata);
if (data.channel) { var socket_channel = data.channel; }
else { var socket_channel = user_socket_channel; }
var rails_data = data.data;
console.log('Socket.io emiting on ['+socket_channel+']')
socket.emit(socket_channel, rails_data);
});
}
else {
redis_subs.on('message', function(redis_channel, rawdata) {
console.log('Redis connection on '+redis_channel);
console.log('No handshaked Session, unauthenticated user. Public channels allowed.');
var data = JSON.parse(rawdata);
var rails_data = data.data;
console.log('Socket.io emiting on [public]')
socket.emit('public', rails_data);
});
}
});
Aquí está la forma en que lo estoy probando, y el caso de uso específico donde el registro se está duplicando:
Cargando la página mientras está conectado, con el navegador web1 (por ejemplo: Firefox); salida:
info - socket.io started
Cross authentication...
Socket.io authorization say true
Authentication status is true.
debug - authorized
info - handshake authorized bJxm_IcWl2mKZT4Ed-kV
debug - setting request GET /socket.io/1/websocket/bJxm_IcWl2mKZT4Ed-kV
debug - set heartbeat interval for client bJxm_IcWl2mKZT4Ed-kV
debug - client authorized for
debug - websocket writing 1::
Carga de la misma página que se ha cerrado con el navegador2 (por ejemplo, Chrome)
Cross authentication...
Socket.io authorization say false
Authentication status is false.
debug - authorized
info - handshake unauthorized
Envío de algunos datos a través de la página / navegador1 (Firefox) -> Rails -> Redis, salida:
Redis connection on application_channel
Handshaked Session, authenticated user. All channels allowed.
Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=]
debug - websocket writing 5:::{"name":"hLTYXuvP+13aQlIT9CZiYc1i9eg=","args":[null]}
Recargar la página en el navegador2 (Chrome, desconectado), aún salida
Cross authentication...
Socket.io authorization say false
Authentication status is false.
debug - authorized
info - handshake unauthorized
Recargando la página en el navegador1 / Firefox y enviando más datos a Redis a través de la página y Rails, salida:
Redis connection on application_channel
Handshaked Session, authenticated user. All channels allowed.
Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=]
Redis connection on application_channel
Handshaked Session, authenticated user. All channels allowed.
Socket.io emiting on [hLTYXuvP+13aQlIT9CZiYc1i9eg=]
debug - websocket writing 5:::{"name":"hLTYXuvP+13aQlIT9CZiYc1i9eg=","args":[null]}
Como puede ver, el evento se duplicó y el oyente Redis ahora captura dos conexiones; Cada vez que vuelva a cargar page1 / Firefox, lo duplicará una vez más (3,4,5 ...).
No entiendo este comportamiento. ¿Qué me estoy perdiendo? Por cierto, como puede ver, realmente no entiendo el objetivo de Socket.ioconfigure
, set authorization
ycallback
, devolviendo verdadero o falso, a medida que Node está llegando aio.on('connection')
y Redis oyentes de todos modos.