[node.js]socket.io上でsessionを使う

# セッションをsocket.io上でつかう＠Node.js
nodeでチャットアプリケーションを作っていて、セッションをwebsocketのイベント上で使いたかったので。
[前回](http://qiita.com/hika7719/items/3282ab2ebcdaf080912e)はexpress-sessionを使って、ログインを行った際に、ユーザー名をセッションに保存した。
socket.ioのイベントでチャットが送信されたらチャット情報をMongoDBに保存するのだがその際にユーザー名をセッションから取り出したい。
最初はhttpのセッションを何もせずに使えると思ったが、意外と準備が必要だった。
ハンドシェイクがどうとか書いてある記事もあったが、[スタックオーバーフローの記事](http://stackoverflow.com/questions/25532692/how-to-share-sessions-with-socket-io-1-x-and-express-4-x)で
それよりも簡単に宣言を行えるものがあったのでそれを採用した。

## 問題点とやったこと
app.js上でsocket.ioとexpress-sessionを宣言する記事が多かったが、自分は最初にディレクトリを作る際に` express-generator`コマンドを使って、ひな形を生成したのでapp.jsと/bin/wwwができてしまった。
これがあだとなって、大変だった。

自分は/bin/wwwでsoket.io宣言とセッション使用をした。
おそらく非推奨

## app.jsでexpress-session宣言、下準備
まず、app.js上でセッションの宣言、wwwでセッション情報を使うための下準備。
オプション等は[前の記事](http://qiita.com/hika7719/items/3282ab2ebcdaf080912e)に書いてある。  

```js:app.js
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上で使えるように

``` js:www
//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に保存する作業。

``` js:www
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に保存してその情報をクライアントに送り返しているのがこのプログラム。

## 結果
![スクリーンショット (64).png](https://qiita-image-store.s3.amazonaws.com/0/136442/d35024eb-bd58-beb8-245c-22e00a3516a8.png)

チャットのヘッダーのところにsessionから取り出したユーザー名が表示されているので完了。

## gituhub
Mongoのモデルとか、mongoose,socket.ioの使い方等はgithubにあげているので参照して下さい。
>https://github.com/hikaru7719/chat_app

## 参考文献
スタックオーバーフロー
>http://stackoverflow.com/questions/25532692/how-to-share-sessions-with-socket-io-1-x-and-express-4-x