socket.io 1.0 では connect っぽく middleware として書けるようになりました。
socket.io 1.0 のハンドシェイク!
socket.request
で Request
オブジェクトが受け取れるのでそれを利用します。
(以下、Express 4.x の場合)
Session = require('express-session').session.Session
COOKIE_SECRET = 'himitsu-dayo'
COOKIE_KEY = 'sid'
#
# 途中省略
#
# Socket.io
io = require('socket.io')(server)
# セッション共有
io.use (socket, next)->
# クッキーからセッション ID を取得する
cookie = require('cookie').parse socket.request.headers.cookie
cookie = require('cookie-parser/lib/parse').signedCookies cookie, COOKIE_SECRET
sessionID = cookie[COOKIE_KEY]
# セッション情報を取得する
sessionStore.get sessionID, (err, sessionData)->
# セッション情報の取得成功!
if !err and sessionData
# 新しく Session を作成
socket.session = new Session({sessionID: sessionID, sessionStore: sessionStore}, sessionData)
next()
# セッション情報の取得失敗 :(
else
next if err then err.message else 'ハンドシェイク失敗だよ!'
# 接続
io.on 'connection', (socket)->
# セッション!
session = socket.session
#
# 以下いろいろ
#
※ 0.9 までの connect.utils.parseSignedCookies
は使えなくなったようです。 cookie-parser
モジュールを使いましょう。
ちなみに・・・ socket.io 0.9 までのハンドシェイクは
0.9 までは下のように、 io.set('authorization', fun);
のように書いていました。
io.set 'authorization', (handshakeData, callback)->
# クッキーからセッション ID を取得する
cookie = require('cookie').parse decodeURIComponent handshakeData.headers.cookie
cookie = connect.utils.parseSignedCookies cookie, COOKIE_SECRET
sessionID = cookie[COOKIE_KEY]
# セッション情報を取得する
sessionStore.get sessionID, (err, sessionData)->
# セッション情報の取得成功!
if !err and sessionData
# 新しく Session を作成
handshakeData.session = new Session sessionID: sessionID, sessionStore: sessionStore, sessionData
callback(null, true)
# セッション情報の取得失敗 :(
else
callback (if err then err.message else 'ハンドシェイク失敗だよ!'), false
#
# 以下省略
#
並べてみるとあまり変わらないように見えるけど、 middleware として書けることでセッション共有以外にもいろいろやりやすくなったと思います。
私のプロジェクトではハンドシェイクの後に middleware でユーザ情報を取り出したりとか書いたりしてます。
Store
タイトルのハンドシェイクとはあまり関係ないけど Store についても軽く触れておきます。
別のプロセスやサーバ間で共有するための store は Adapter という仕組みで実現します。
0.9 までは socket.io
に Redis
用のクラスが最初から用意されてたけど、1.0 (pre4) では用意されてないようです。
現状、 Redis
を使う場合は別の開発者の socket.io-redis
がよさそうです。
こんな感じで、
# Redis アダプタ
RedisAdapter = require('socket.io-redis')(host: 'localhost', port: 6379)
# Socket.io
io = require('socket.io')(server, { adapter: RedisAdapter })
ソースを軽く覗いたら Pub/Sub とか勝手にやってくれそうな感じ。
最後に
この記事はまだ正式リリース前の socket.io 1.0.0-pre5 をベースに書いています。
たぶん正式版でも動く...はず!
1.0.2 で動きました。
こちらからは以上です。