waffle
Version:
シンプルなWEBアプリケーションフレームワークです。(ALL YOUR NODE ARE BELONG TO US)
211 lines (178 loc) • 5.08 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 ファイルにセッションを保存するストアです。
*/
;
var SessionStore = require("../utils/SessionStore");
var fs = require("fs");
var waffle = require("../Waffle");
var hexMap = {};
for ( var i = 0x00; i <= 0xff; i++) {
hexMap[i] = (i < 0x10 ? "0" : "") + i.toString(16);
}
function createSessionStore(dir) {
var tmp = dir || waffle.tmp;
var handler = {
clear : function(session) {
deleteSession(session.sessionId, tmp, function(err) {
if (err) {
waffle.log.error(1, err);
}
});
},
store : function(session, values) {
writeSession(session.sessionId, tmp, values, function(err) {
if (err) {
waffle.log.error(2, err);
}
});
},
restore : function(session, callback) {
readSession(session.sessionId, tmp, session.timeout, function(err,
values) {
if (err) {
waffle.log.error(3, err);
}
callback(values);
});
}
};
return new SessionStore(handler, false);
}
function getDir(file, tmp) {
var h = 0;
for ( var i = 0, j = file.length; i < j; i++) {
h = (31 * h + file.charCodeAt(i)) & 0xffffffff;
}
var d1 = ((h & 0xff000000) >> 24) & 0xff;
var d2 = (h & 0xff0000) >> 16;
var d3 = (h & 0xff00) >> 8;
var d4 = h & 0xff;
return fs.join(tmp, hexMap[d1], hexMap[d2], hexMap[d3], hexMap[d4]);
}
function mkdirs(path, callback) {
var paths = [];
while (true) {
paths.push(path);
var p = fs.dirname(path);
if (p === path) {
break;
}
path = p;
}
paths.reverse();
mkdir(paths, callback);
}
function mkdir(paths, callback) {
if (paths.length === 0) {
callback(null);
return;
}
fs.exists(paths[0], function(exists) {
console.log(exists, paths[0]);
if (exists) {
paths.shift();
mkdir(paths, callback);
return;
}
fs.mkdir(paths[0], function(err) {
if (err) {
callback(err);
return;
}
paths.shift();
mkdir(paths, callback);
});
});
}
function writeSession(sessionId, tmp, values, callback) {
var dir = getDir(sessionId, tmp);
mkdirs(dir, function(err) {
if (err) {
callback(err);
return;
}
var filename = fs.join(dir, sessionId);
fs.writeFile(filename, values, "UTF-8", callback);
});
}
function deleteSession(sessionId, tmp, callback) {
var dir = getDir(sessionId, tmp);
var filename = fs.join(dir, sessionId);
fs.unlink(filename, callback);
}
function readSession(sessionId, tmp, timeout, callback) {
var dir = getDir(sessionId, tmp);
var filename = fs.join(dir, sessionId);
fs.exists(filename, function(exists) {
if (!exists) {
callback(null, null);
return;
}
fs.stat(filename, function(err, stats) {
if (err) {
callback(err, null);
return;
}
var timestamp = stats.mtime.getTime();
var now = Date.now();
if (timestamp + timeout < now) {
fs.unlink(filename);
return;
}
fs.readFile(filename, "UTF-8", function(err, values) {
if (err) {
callback(err, null);
} else {
callback(null, values);
}
if (process.platform == "win32") {
fs.writeFile(filename, values);
} else {
fs.utimes(filename, now, now);
}
});
});
});
}
/**
* ファイルにセッションを保存するストアです。
* <p>
* 既に無効になったセッションに関連するファイルは自動で削除されません。 ファイルのタイムスタンプに基づいてcronなどで削除してください。
* セッションタイムアウトを1時間に設定してある場合は、ファイルのタイムスタンプが1時間前であれば、安全に削除することができます。
* </p>
* <p>
* ファイルの保存場所は{@link Waffle.tmp}になります。関数として使用する場合にディレクトリを指定して変更することも可能です。
* セッションの実体は、複数階層のディレクトリ以下にセッションIDのファイル名で作成され、内容はJSONになります。
* </p>
*
* @function
* @param {String}
* dir ディレクトリ
* @name Extensions#fileStore
* @see Filters#session
*/
var store = function(dir) {
return {
instance : createSessionStore(dir)
};
};
store.instance = createSessionStore(null);
//
// expose
//
module.exports = store;