Code coverage report for thinkjs/lib/Lib/Behavior/ReadHtmlCacheBehavior.js

Statements: 100% (64 / 64)      Branches: 100% (31 / 31)      Functions: 100% (8 / 8)      Lines: 100% (64 / 64)      Ignored: none     

All files » thinkjs/lib/Lib/Behavior/ » ReadHtmlCacheBehavior.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142  2 2         2   2                   12 3   9 9 3   6 1   1   5             1 1 1 1 1 1 1 1                             22 22 22 22 22           22 22 43 43 17 17     22 5   17 2   17   17 17 15   17         17 7   17 17   17 17 17               16 16             12 12 6   6 6 6 3 1   2   2 1     4 1   3      
//获取模版文件
var WriteHtmlCacheBehavior = thinkRequire('WriteHtmlCacheBehavior');
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;
      var list = [
        group + ':' + controller + ':' + action,
        controller + ':' + action,
        action,
        '*'
      ];
      var html = [];
      for(var i = 0, length = list.length, item; i < length; i++){
        item = list[i];
        if (item in rules) {
          html = rules[item];
          break;
        }
      }
      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[0] + '/' + value[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 = WriteHtmlCacheBehavior.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;
    }
  };
});