セッションをsocket.io上でつかう@Node.js
nodeでチャットアプリケーションを作っていて、セッションをwebsocketのイベント上で使いたかったので。
前回はexpress-sessionを使って、ログインを行った際に、ユーザー名をセッションに保存した。
socket.ioのイベントでチャットが送信されたらチャット情報をMongoDBに保存するのだがその際にユーザー名をセッションから取り出したい。
最初はhttpのセッションを何もせずに使えると思ったが、意外と準備が必要だった。
ハンドシェイクがどうとか書いてある記事もあったが、スタックオーバーフローの記事で
それよりも簡単に宣言を行えるものがあったのでそれを採用した。
問題点とやったこと
app.js上でsocket.ioとexpress-sessionを宣言する記事が多かったが、自分は最初にディレクトリを作る際に express-generator
コマンドを使って、ひな形を生成したのでapp.jsと/bin/wwwができてしまった。
これがあだとなって、大変だった。
自分は/bin/wwwでsoket.io宣言とセッション使用をした。
おそらく非推奨
app.jsでexpress-session宣言、下準備
まず、app.js上でセッションの宣言、wwwでセッション情報を使うための下準備。
オプション等は前の記事に書いてある。
var express = require('express');
var app = express();
var session = require('express-session');
var sessionMiddleware = session({
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie:{
httpOnly: false,
secure: false,
maxage: 1000 * 60 * 30
}});
app.session = sessionMiddleware;
app.use(sessionMiddleware);
...
module.exports = app;
最後の module.exports
でapp変数が他のファイルでも参照できるようにしている。
また、sessionMiddleware変数をwwwファイルで使いたいので
app.session = sessionMiddleware;
appのプロパティとして渡している。
/bin/wwwでセッションをsocket上で使えるように
//app変数の取り出し
var app = require('../app');
//sessionMiddlewareの取り出し
var sessionMiddleware = app.session;
var debug = require('debug')('chat-app:server');
var http = require('http');
var mongoose = require('mongoose');
var Chat = mongoose.model('Chat');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
var io = require('socket.io')(server);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
//セッションをsocket上で使えるように
io.use(function(socket, next){
sessionMiddleware(socket.request, socket.request.res, next);
});
長々と準備の文を書いたが、大事なので最初の2行とio.useのところ。これでセッションをつかえるようにしている。
app.jsで渡したappを取り出している。app.jsのモジュールエクスポートが重要。
##セッションの使い方
基本的にここまでくれば
socket.request.session.プロパティ名
でセッション情報が取り出せる。
今回は前記事で書いたようにrequest.session.usernameにユーザー名が入っているのでこれを取り出している。
でそのほかはmongoooseでmongodbに保存する作業。
io.sockets.on('connection',function(socket){
console.log('connected');
socket.on('chat message',function(message){
var chat = new Chat();
chat.message = message;
chat.chat_id = "one";
chat.user = socket.request.session.username ;
chat.save(function(error,chat){
console.log(message);
if(error){
console.log(error);
}else{
console.log("chat saved");
}
});
io.sockets.emit('send message', chat);
});
});
クライアントからメッセージが来たらMongoDBに保存してその情報をクライアントに送り返しているのがこのプログラム。
結果
チャットのヘッダーのところにsessionから取り出したユーザー名が表示されているので完了。
gituhub
Mongoのモデルとか、mongoose,socket.ioの使い方等はgithubにあげているので参照して下さい。
参考文献
スタックオーバーフロー
http://stackoverflow.com/questions/25532692/how-to-share-sessions-with-socket-io-1-x-and-express-4-x