2012-11-18 13 views
7

Mogę podłączyć moją aplikację węzła do Redis dobrze bez hasła, ale kiedy dodaję hasło, nic co robię jest słuszne.Błąd autouzupełniania z Node.js i gniazdem.io

Oto mój kod teraz, wzięty prosto z an example:

var redis = require('redis') 
    , sio = require('socket.io') 
    , RedisStore = sio.RedisStore 
    , io = sio.listen(); 

var port = 6379 
    , hostname = 'localhost' 
    , password = 'password'; 

var redisClient = redis.createClient(port, hostname); 
redisClient.auth(password, function (err) { if (err) throw err; }); 

var redisSubscriber = redis.createClient(port, hostname); 
redisSubscriber.auth(password, function (err) { if (err) throw err; }); 

io.set('store', new RedisStore({ redisPub: redisClient, redisSub: redisSubscriber, redisClient: redisClient })); 

Na uruchamiając aplikację, otrzymuję ten ślad stosu:

/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:506 
       throw callback_err; 
        ^
Error: Ready check failed: ERR operation not permitted 
    at RedisClient.on_info_cmd (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:319:35) 
    at Command.RedisClient.ready_check.send_anyway [as callback] (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:367:14) 
    at RedisClient.return_error (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:502:25) 
    at RedisReplyParser.RedisClient.init_parser (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:262:14) 
    at RedisReplyParser.EventEmitter.emit (events.js:93:17) 
    at RedisReplyParser.send_error (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:266:14) 
    at RedisReplyParser.execute (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:125:22) 
    at RedisClient.on_data (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:478:27) 
    at Socket.<anonymous> (/home/eric/christmas/sockets/node_modules/socket.io/node_modules/redis/index.js:79:14) 
    at Socket.EventEmitter.emit (events.js:93:17) 

Linia generowania to ostateczna jedno - jeśli Komentuję próbę ustawienia RedisStore, nie dostaję żadnych błędów.

Jestem pewien, że hasło jest prawidłowe (mogę je zweryfikować w witrynie redis-cli, a jeśli zmienię hasło na niewłaściwe, mogę sprawdzić, czy wywołania zwrotne nie są uruchamiane). Ten kod działa również po usunięciu hasła i skomentowaniu dwóch linii autoryzacji.

Wszystkie działające przykłady na blogach i dokumentach itp. Pokazują, że to powinno działać, i nie wiem, dlaczego moje nie jest. Nie wiem, na którą część stosu patrzeć.

Oto co monitor Redis-cli wygląda kiedy uruchomić powyższy kod:

1353227107.912512 [0 127.0.0.1:56759] "auth" "password" 
1353227107.912719 [0 127.0.0.1:56758] "auth" "password" 
1353227107.913470 [0 127.0.0.1:56759] "info" 
1353227107.913639 [0 127.0.0.1:56758] "info" 

A oto co Redis-cli Monitor pokazuje jeśli mogę wyłączyć hasło wykomentuj linie auth powyżej, pomyślnie uruchomić aplikację:

1353227252.401667 [0 127.0.0.1:56771] "info" 
1353227252.402020 [0 127.0.0.1:56770] "info" 
1353227252.402131 [0 127.0.0.1:56769] "info" 
1353227252.402423 [0 127.0.0.1:56768] "info" 
1353227252.402611 [0 127.0.0.1:56767] "info" 
1353227252.406254 [0 127.0.0.1:56770] "subscribe" "handshake" 
1353227252.406287 [0 127.0.0.1:56770] "subscribe" "connect" 
1353227252.406314 [0 127.0.0.1:56770] "subscribe" "open" 
1353227252.406321 [0 127.0.0.1:56770] "subscribe" "join" 
1353227252.406326 [0 127.0.0.1:56770] "subscribe" "leave" 
1353227252.406337 [0 127.0.0.1:56770] "subscribe" "close" 
1353227252.406354 [0 127.0.0.1:56770] "subscribe" "dispatch" 
1353227252.406372 [0 127.0.0.1:56770] "subscribe" "disconnect" 

pomyślne (bez podawania haseł) połączenie sprawia 5 „Info” polecenia, a nieudane polecenie mój (zabezpieczony hasłem) sprawia 2 - a potem umiera na wezwanie do „on_info_cmd” metody.

Czy ktokolwiek może to zrozumieć? Dziękuję za pomoc, którą możesz udzielić.

+0

Rozwiązałem to (odpowiedź poniżej) i zaktualizowałem wiki Socket.io, aby podać przykład RedisStore z autoryzacją: https://github.com/LearnBoost/socket.io/wiki/Configuring-Socket.IO – Konklone

Odpowiedz

9

Rozwiązałem to, przekazując sam moduł redis jako opcję do konstruktora RedisStore.

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

Było to konieczne dla obiektów klienta zdać test instanceof RedisClient i nie mogą być ponownie zainicjowany bez hasła. Najwyraźniej, gdy RedisStore wymaga ponownego modułu redis, klienci redis utworzeni za pomocą metody createClient są członkami jakiejś nowej klasy lub czegoś takiego.

Wyjaśniałem to, patrząc na powiązany problem, który ktoś miał na socket.io's issue #808.

+0

Wystąpił inny błąd, ale to samo pomogło ... Prawdopodobnie wystąpił błąd, ponieważ Redis jest również używany do sesji Express, a może inny moduł był używany do przechowywania i do klienta? – esp

1

Spróbuj zadzwonić pod numer redisClient.auth(password, function (err) { if (err) throw err; }); tylko raz, redis przechowuje informacje o auth dla każdego połączenia, a wywołanie go dwukrotnie może spowodować błąd.

+0

It jest właściwie wywoływany tylko raz dla każdego klienta - pierwszy raz jest na redisClient, a drugi na redisSubscriber, oddzielnej instancji. – Konklone

+1

Tak Rozumiem, ale klient "przechowuje" hasło, więc nie trzeba go wywoływać dla wielu wystąpień. Proszę spojrzeć na [Node_redis] (https://github.com/mranney/node_redis) i [przykład Auth] (https://github.com/mranney/node_redis/blob/master/examples/auth.js) – Sdedelbrock

+1

To nie jest poprawny - przechowuje go dla każdej instancji, nie dla całej klasy. Każdy przykład auta, jaki widziałem w systemie redis, który tworzy klienta pubu, sub i klienta sklepu, używa tego wzorca. Przykład: https://github.com/LearnBoost/socket.io/pull/551 – Konklone