2013-03-02 10 views
9

Staram się, aby sesje działały w moim socket.on ("połączenie", ...) Próbuję uzyskać to działa przy użyciu najnowszych wersji: Socket.io - 0.9.13, Express - 3.1.0 i najnowsze wersje innych modułów.Jak mogę przekonwertować sesje do pracy za pomocą redis, express & socket.io?

W każdym razie próbowałem używać obu modułów 'connect-redis' i 'session.socket.io' i oba mają podobne problemy.

W moim kodzie mam 2 redis stores (socketio.RedisStore i require ('connect-redis') (express)), teraz ten program działa dobrze, ale ponieważ express i socket.io muszą udostępniać dane sesji, Zastanawiam się, czy ta konfiguracja poprawnie użyje sesji? czy magazyny sesji muszą być tym samym obiektem dla express/socketio? Trochę szarej strefy do mnie, ponieważ 2 RedisStore używa tej samej bazy danych w tle?

Próbowałem używać zarówno red.tore w socket.io jak i redisStore connect-redis w obu miejscach, ale socket.io nie lubi redisStore connect-redis i express nie przypomina socketio.redisStore.

Jeśli używam connect-Redis RedisStore następnie socket.io/lib/manager.js narzeka: this.store.subscribe (... TypeError Obiekt # ma metody 'Subskrybuj'

Gdybym użyj socketio.RedisStore następnie express/node_modules/connect/lib/middleware/session.js narzeka: TypeError: Object # nie ma metody 'get'

* Uwaga Wolałbym, aby wtyczka session.socket.io działała, ale kiedy robię to samo ustawienie z tą wtyczką, express (także) narzeka: TypeError: Object # nie ma metody 'get'

Czy można używać 2 różnych RedisStores dla sesji?

Mój bieżący kod wygląda następująco:

var 
    CONST = { 
     port: 80, 
     sessionKey: 'your secret sauce' 
    }; 

var 
    redis = require('redis'); 

var 
    express = require('express'), 
    socketio = require('socket.io'), 
    RedisStore = require('connect-redis')(express); 

var 
    redisStore = new RedisStore(), 
    socketStore = new socketio.RedisStore(); 

var 
    app = express(), 
    server = require('http').createServer(app), 
    io = socketio.listen(server); 

app.configure(function(){ 
    app.use(express.cookieParser(CONST.sessionKey)); 
    app.use(express.session({ secret: CONST.sessionKey, store: redisStore })); 
    app.use(express.static(__dirname + '/test')); 
    app.get('/', function (req, res) {res.sendfile(__dirname + '/test/' + 'index.htm');}); 
}); 

io.configure(function(){ 
    io.set('log level', 1); 
    io.enable('browser client minification'); 
    io.enable('browser client etag'); 
    io.enable('browser client gzip'); 
    io.set('store', socketStore); 
}); 

io.sockets.on('connection', function(socket){ 
    socket.emit('message', 'Test 1 from server') 
}); 

server.listen(CONST.port); 

console.log('running...'); 

Odpowiedz

4

wewnątrz io.configure, trzeba połączyć gniazdo z sesji http.

Oto fragment kodu, który wyodrębnia plik cookie (to jest użycie socket.io z xhr-polling, nie wiem, czy to działałoby dla websocket, chociaż podejrzewam, że zadziała).

var cookie = require('cookie'); 
var connect = require('connect'); 

var sessionStore = new RedisStore({ 
    client: redis // the redis client 
}); 

socketio.set('authorization', function(data, cb) { 
    if (data.headers.cookie) { 
    var sessionCookie = cookie.parse(data.headers.cookie); 
    var sessionID = connect.utils.parseSignedCookie(sessionCookie['connect.sid'], secret); 
    sessionStore.get(sessionID, function(err, session) { 
     if (err || !session) { 
     cb('Error', false); 
     } else { 
     data.session = session; 
     data.sessionID = sessionID; 
     cb(null, true); 
     } 
    }); 
    } else { 
    cb('No cookie', false); 
    } 
}); 

Następnie można uzyskać dostęp do sesji przy użyciu:

socket.on("selector", function(data, reply) { 
    var session = this.handshake.session; 
    ... 
} 

Ma też dodatkową zaletę, że sprawdza jest ważna sesja, więc tylko swoją zalogowani użytkownicy mogą korzystać z gniazdek. Możesz jednak użyć innej logiki.

+0

Dzięki za szybką odpowiedź, więc jest to to samo rozwiązanie, jeśli chcę użyć wtyczki session.socket.io? czy jest to zupełnie inny problem? –

+0

To nie używa wtyczki session.socket.io i działa na najnowszych wersjach pliku socket.io i express. –

+0

ahhh ok, mógłbym dać to, dzięki za pomoc. –

4

Patrząc na swojej ostatniej nuty (nie będzie w stanie podzielić swój stan na wiele procesów wykorzystujących Redis) Miałem ten sam problem i znalazł rozwiązanie:

var express = require("express.io"); 
var swig = require('swig'); 
var redis = require('redis'); 
var RedisStore = require('connect-redis')(express); 

workers = function() { 
    var app = express().http().io(); 

    app.use(express.cookieParser()); 
    app.use(express.session({ 
     secret: 'very cool secretcode', 
     store: new RedisStore({ client: redis.createClient() }) 
    })); 

    app.io.set('store', new express.io.RedisStore({ 
     redisPub: redis.createClient(), 
     redisSub: redis.createClient(), 
     redisClient: redis.createClient() 
    })); 


    app.get('/', function(req, res) { 
     res.render('index'); 
    }); 

    app.listen(3000); 


    app.io.route('ready', function(req){ 
     //setup session stuff, use session stuff, etc. Or make new routes 
    }); 
}; 

cluster = require('cluster'); 
numCPUs = require('os').cpus().length; 

if (cluster.isMaster) 
{ 
    for (var i = 0; i < numCPUs; i++) 
    { 
     cluster.fork(); 
    } 
} 
else 
{ 
    workers(); 
} 
+0

Kluczem tutaj jest 'app.io.set ('store', new express.io.RedisStore ({'przy użyciu express.io.RedisStore. Dzięki! – ruffrey

Powiązane problemy