2013-03-02 12 views
9

So versuche ich Sitzungen in meinem socket.on ('Verbindung', ...) zu arbeiten Ich versuche, dies mit den neuesten Versionen zu arbeiten: Socket.io - 0.9.13, Express - 3.1.0 und die neuesten Versionen anderer Module.Wie kann ich Sessions mit redis, express & socket.io arbeiten lassen?

Wie auch immer ich habe versucht, beide Module 'connect-redis' und 'session.socket.io' und sie beide haben ähnliche Probleme.

In meinem Code habe ich 2 Redis Stores (socketio.RedisStore und erfordern ('connect-redis') (Express)), jetzt läuft dieses Programm gut, aber weil Express und socket.io Sitzungsdaten teilen müssen, Ich habe mich gefragt, ob dieses Setup die Sitzungen korrekt verwenden wird? Müssen die Sitzungsspeicher für express/socketio dasselbe Objekt sein? Ein bisschen eine Grauzone für mich, weil die 2 RedisStore die gleiche db im Hintergrund verwenden?

Ich habe versucht, entweder die socket.io redisestore oder die connect-redis redisestore an beiden Orten, aber socket.io nicht wie die connect-redis redisestore und Express nicht wie die socketio.redisStore.

Wenn ich die connect-redis verwenden RedisStore dann socket.io/lib/manager.js klagt: this.store.subscribe (... Typeerror Objekt # hat keine Methode 'abonnieren'

Wenn ich benutze socketio.RedisStore und dann express/node_modules/connect/lib/middleware/session.js beklagt: TypeError: Objekt # hat keine Methode 'get'

* Hinweis Ich möchte lieber das session.socket.io Plugin funktionieren lassen, aber wenn ich das selbe setup mit diesem plugin mache, klagt express (auch): TypeError: Objekt # hat keine Methode 'get'

Also ist es in Ordnung, dass ich zwei verschiedene RedisStores für Sitzungen verwende, oder muss ich irgendwie die eine oder andere für beide arbeiten, und wenn ja, irgendwelche Ideen, wie zu beheben?

Meine aktuellen Code sieht wie folgt aus:

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

Antwort

4

innerhalb des io.configure, haben Sie die Buchse mit dem HTTP-Sitzung zu verknüpfen.

Hier ist ein Stück Code, der den Cookie extrahiert (Dies ist mit socket.io mit xhr-polling, ich weiß nicht, ob dies für Websocket funktionieren würde, obwohl ich vermute, dass es funktionieren würde).

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

Dann können Sie die Sitzung mit Zugang:

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

Dies hat auch den zusätzlichen Vorteil, dass sie überprüft, eine gültige Sitzung ist, so dass nur Benutzer Ihre angemeldet Sockets verwenden können. Sie können jedoch eine andere Logik verwenden.

+0

Vielen Dank für die schnelle Antwort, so ist dies die gleiche Lösung, wenn ich das session.socket.io Plugin verwenden wollte? oder ist das insgesamt ein anderes Problem? –

+0

Dies verwendet nicht das Plugin session.socket.io und arbeitet mit den neuesten Versionen von socket.io und express. –

+0

ahhh ok, ich könnte das mal ausprobieren, danke für die Hilfe. –

4

bei Ihrem letzten Note der Suche (wird seinen Zustand nicht über mehrere Prozesse in der Lage zu teilen mit redis) Ich hatte das gleiche Problem und eine Lösung gefunden:

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

Der Schlüssel hier ist 'app.io.set ('speichern', neue express.io.RedisStore ({'mit der express.io.RedisStore. Danke! – ruffrey

Verwandte Themen