waffle
Version:
シンプルなWEBアプリケーションフレームワークです。(ALL YOUR NODE ARE BELONG TO US)
235 lines (213 loc) • 6.37 kB
JavaScript
/*
* Copyright 2012 Katsunori Koyanagi
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/**
* @overview セッション管理をサポートするフィルタです。
*/
"use strict";
var cookies = require("./cookies");
var util = require("../utils/Util");
var memoryStore = require("../extensions/memoryStore");
var dummy = function() {
};
/**
* セッションをコンテキストに設定します。
* <p>
* 関数として使用する場合は以下のオプションを受け付けて、セッションフィルタを構築することができます。 メンバーは全て省略可能です。
* </p>
* <table>
* <tr>
* <th>名前</th>
* <th>値</th>
* <th>デフォルト値</th>
* </tr>
* <tr>
* <td>store</td>
* <td>セッションの永続化ストア({@link SessionStore}のインスタンス)</td>
* <td>メモリセッションストア</td>
* </tr>
* <tr>
* <td>key</td>
* <td>クッキーもしくはURLパラメータからセッションIDを保存取得するためのキー</td>
* <td>"wafflesessid"</td>
* </tr>
* <tr>
* <td>timeout</td>
* <td>セッションタイムアウトまでのミリ秒の時間</td>
* <td>900000(15分)</td>
* </tr>
* </table>
* <p>
* スケーラビリティの観点から、セッションへの保存はクッキーへの保存を行う、{@link Extensions#cookieStore}を推奨します。
* サーバの資源を消費せず、またガベージコレクションを行う必要もありません。
* クッキーの場合は容量の制約を受けるため、極力セッションへの保存サイズは最低限になるように設計することを推奨します。
* </p>
*
* @function
* @name Filters#session
* @param {Object}
* options オプション
* @see Context#session
*/
var session = function(options) {
return {
pre : createFilter(options)
};
};
function createFilter(options) {
options = options || {};
var store = options.store ? options.store.instance : memoryStore.instance;
var key = options.key || "wafflesessid";
var timeout = parseInt(options.timeout, 10);
if (timeout * 0.0 != 0.0) {
timeout = 0;
}
if (timeout <= 0) {
timeout = 15 * 60 * 1000;
}
return function(context, next) {
if (!context.cookies) {
cookies.pre(context, dummy);
}
context.session = new SessionObject(store, key, timeout, context);
context.session.restore(next);
};
}
session.pre = createFilter(null);
/**
* セッションを表現します。
*
* @class セッションを表現します。
* @constructor
* @param {SessionStore}
* store セッションストア
* @param {String}
* key セッションキー
* @param {Number}
* timeout タイムアウトまでのミリ秒の時間
* @param {Context}
* context コンテキスト
* @see Filters#session
*/
function SessionObject(store, key, timeout, context) {
this.store = store;
this.key = key;
this.context = context;
this.timeout = timeout;
this.values = {};
this.onClose0 = this.onClose.bind(this);
var sessionId = context.cookies.get(key);
if (!sessionId) {
sessionId = context.getParameters()[key];
}
if (!sessionId) {
sessionId = this.generateSessionId();
}
this.sessionId = sessionId;
if (!this.store.header) {
context.on("close", this.onClose0);
} else {
context.res.on("writeHead", this.onClose0);
}
}
/**
* @private
*/
SessionObject.prototype.generateSessionId = function() {
var sessionId = "sess_" + util.generateUID();
this.context.cookies.set(this.key, sessionId);
return sessionId;
};
/**
* @private
*/
SessionObject.prototype.restore = function(callback) {
var self = this;
this.store.restore(this, function(values) {
if (values) {
values = JSON.parse(values);
for ( var name in values) {
self.values[name] = values[name];
}
} else {
self.sessionId = self.generateSessionId();
}
callback();
});
};
/**
* 指定の名前に該当するセッションの値を削除します。
*
* @param {String}
* name 名前
*/
SessionObject.prototype.remove = function(name) {
delete this.values[name];
};
/**
* 指定の名前に該当するセッションの値を取得して返します。
*
* @param {String}
* name 名前
* @return {Object} 値
*/
SessionObject.prototype.get = function(name) {
return this.values[name];
};
/**
* 指定の名前でセッションに値を設定します。
*
* @param {String}
* name 名前
* @param {Object}
* value 値
*/
SessionObject.prototype.set = function(name, value) {
this.values[name] = value;
};
/**
* セッションIDの再生成を行います。
*/
SessionObject.prototype.changeSessionId = function() {
this.store.clear(this);
this.sessionId = this.generateSessionId();
this.context.cookies.set(this.key, this.sessionId);
};
/**
* セッションの破棄を行います。このメソッドを呼び出した以降はセッションは無効になります。
*/
SessionObject.prototype.destroy = function() {
this.store.clear(this);
this.context.cookies.set(this.key);
this.sessionId = null;
this.values = null;
this.context.removeListener("close", this.onClose0);
this.context.res.removeListener("writeHead", this.onClose0);
};
/**
* @private
*/
SessionObject.prototype.onClose = function() {
if (!this.store.header) {
this.context.removeListener("close", this.onClose0);
} else {
this.context.res.removeListener("writeHead", this.onClose0);
}
this.store.store(this, JSON.stringify(this.values));
};
//
// expose
//
module.exports = session;