thinkjs/lib/Lib/Behavior/ReadHtmlCacheBehavior.js

141 lines
4.1 KiB
JavaScript

//获取模版文件
var getViewFile = thinkRequire('WriteHtmlCacheBehavior').getViewFile;
var fs = require('fs');
/**
* 读取HTML缓存
* @return {[type]} [description]
*/
module.exports = Behavior(function(){
'use strict';
return {
options:{
'html_cache_on': false, //是否开启缓存
'html_cache_timeout': 3600, //缓存时间
'html_cache_rules': {}, //缓存规则
'html_cache_path': '',
'html_cache_file_callback': undefined, //生成缓存文件的回调函数
'html_cache_file_suffix': '.html', //缓存文件扩展名
},
run: function(){
if (!this.options.html_cache_on || isEmpty(this.options.html_cache_rules)) {
return false;
}
var cacheTime = this.getCacheTime();
if (cacheTime === false) {
return false;
}
if (this.checkCacheTime(cacheTime)) {
this.responseCacheContent();
//return a pending promise
return getDefer().promise;
}
return false;
},
/**
* 返回缓存内容
* @return {[type]} [description]
*/
responseCacheContent: function(){
var http = this.http;
var fileStream = fs.createReadStream(this.options.html_cache_path + '/' + http.html_filename);
http.setHeader('Content-Type', 'text/html');
http.sendTime('Exec-Time');
http.sendCookie();
fileStream.pipe(http.res);
fileStream.on('end', function(){
http.end();
});
},
/**
* 获取缓存时间
* @return {[type]} [description]
*/
getCacheTime: function(){
/**
* rules数据格式
* {
* 'index:index': ['index_home', 1800, html_cache_callback]
* }
* @type {[type]}
*/
var rules = this.options.html_cache_rules;
var group = this.http.group.toLowerCase();
var controller = this.http.controller.toLowerCase();
var action = this.http.action.toLowerCase();
var list = [
group + ':' + controller + ':' + action,
controller + ':' + action,
action,
'*'
];
var html = [];
list.some(function(item){
if (item in rules) {
html = rules[item];
return true;
}
});
if (isEmpty(html)) {
return false;
}
if (!isArray(html)) {
html = [html];
}
var rule = html[0];
//将cookie变量传递进去
var cookiePars = {};
for(var name in this.http.cookie){
cookiePars['cookie.' + name] = this.http.cookie[name];
}
var pars = extend({}, this.http.get, cookiePars, {
':group': group,
':controller': controller,
':action': action
});
rule = rule.replace(/\{([\w\:]+)\}/g, function(a, name){
return pars[name] || '';
});
var callback = html[2] || C('html_cache_file_callback') || this.getCacheFilename;
var filename = callback(rule, this.http) + this.options.html_cache_file_suffix;
//静态缓存文件名
this.http.html_filename = filename;
var cacheTime = html[1] || this.options.html_cache_timeout;
return cacheTime;
},
/**
*
* @param {[type]} key [description]
* @return {[type]} [description]
*/
getCacheFilename: function(key){
var value = md5(key);
return value.substr(0, 1) + '/' + value;
},
/**
* [checkCacheTime description]
* @return {[type]} [description]
*/
checkCacheTime: function(cacheTime){
var cacheFile = this.options.html_cache_path + '/' + this.http.html_filename;
if (!isFile(cacheFile)) {
return false;
}
var cacheFileMtime = fs.statSync(cacheFile).mtime.getTime();
var tplFile = getViewFile(this.http);
if (tplFile) {
if (!isFile(tplFile)) {
return false;
}
var tplFileMtime = fs.statSync(tplFile).mtime.getTime();
//模版文件有更新
if (tplFileMtime > cacheFileMtime) {
return false;
}
}
if (Date.now() > (cacheFileMtime + cacheTime * 1000)) {
return false;
}
return true;
}
};
});