mm_statics 1.9.5 → 1.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,13 @@
1
1
  {
2
2
  // 路由路径,注意:这里是泛路径,相当于/*
3
+ // 注册域, 即本资源注册到 require('mm_xxx').admin 的哪个域
4
+ "scope": "${scope || 'os'}",
5
+ // 所属应用
6
+ "app": "${app || 'os'}",
7
+ // 所属插件, 应用级资源为空
8
+ "plugin": "${plugin || ''}",
3
9
  "path": "${path || '/${name}'}",
10
+
4
11
  // 名称, 由中英文和下“_”组成, 用于修改或卸载 例如: demo
5
12
  "name": "${name || 'static'}",
6
13
  // 标题, 用于查询时
package/lib/manager.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const Manager = require("mm_machine").Manager;
2
2
  const Static = require("./static");
3
+ const StaticHandle = require("./static_handle");
3
4
  const { URLSearchParams } = require('url');
4
5
 
5
6
  /**
@@ -37,7 +38,13 @@ class StaticManager extends Manager {
37
38
  * 资源清单文件名(update 扫描目录时使用)
38
39
  * @type {string}
39
40
  */
40
- filename: "static.json"
41
+ filename: "static.json",
42
+ /**
43
+ * 忽略的请求路径(管理器级,命中后不再遍历任何驱动),
44
+ * 支持 * 通配,如 ['/api*', '/apis*'];驱动级 ignore 可再各自补充
45
+ * @type {Array<string|RegExp>}
46
+ */
47
+ ignore: []
41
48
  };
42
49
 
43
50
  /**
@@ -69,6 +76,10 @@ class StaticManager extends Manager {
69
76
  */
70
77
  async run(params, ctx, options) {
71
78
  var path = this._requestPath(params, ctx);
79
+ // 管理器级忽略:命中即视为未命中,跳过全部驱动的匹配(接口类请求不再空跑一圈)
80
+ if (StaticHandle.isIgnored(path, this.config.ignore)) {
81
+ return false;
82
+ }
72
83
  var infos = this._getInfos();
73
84
  var len = infos.length;
74
85
  if (path.indexOf(".") !== -1) {
package/lib/static.js CHANGED
@@ -31,6 +31,8 @@ class Static extends Item {
31
31
  'gzip': true,
32
32
  // 允许访问的拓展名
33
33
  'extensions': null,
34
+ // 忽略的请求路径(本驱动不参与的路径),支持 * 通配,如 ['/api*']
35
+ 'ignore': null,
34
36
  // 是否将ES6转换AMD
35
37
  'convert_amd': true,
36
38
  // 主程序文件 - 默认为空
@@ -10,6 +10,79 @@ const { marked } = require('marked');
10
10
 
11
11
  var vueCompiler = new VueSFCCompiler();
12
12
 
13
+ /**
14
+ * 通配规则编译缓存(规则串 -> 正则),避免热路径上重复构造正则
15
+ * @type {Map<string, RegExp>}
16
+ */
17
+ var rule_cache = new Map();
18
+
19
+ /**
20
+ * 将忽略规则编译为正则(支持 * 通配,等价于任意字符)
21
+ * @param {string} rule 规则串,如 /api*、*.map、/apis*
22
+ * @returns {RegExp} 匹配整个路径的正则
23
+ */
24
+ function _compileRule(rule) {
25
+ var re = rule_cache.get(rule);
26
+ if (re) {
27
+ return re;
28
+ }
29
+ // 先转义正则元字符,再把 * 还原为通配
30
+ var escaped = rule.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
31
+ re = new RegExp('^' + escaped + '$');
32
+ rule_cache.set(rule, re);
33
+ return re;
34
+ }
35
+
36
+ /**
37
+ * 判断请求路径是否命中忽略规则
38
+ *
39
+ * 规则形态(可传单个规则、逗号分隔字符串或数组,数组元素可为字符串或正则):
40
+ * - 前缀通配:/api* ,忽略 /api、/api/user 等
41
+ * - 后缀通配:*.map ,忽略所有 .map 文件
42
+ * - 包含通配:*manage* ,忽略路径中含 manage 的请求
43
+ * - 无通配:/api ,按「路径段前缀」匹配,忽略 /api 与 /api/xxx,但不影响 /apixyz
44
+ * @param {string} target 请求路径
45
+ * @param {string|Array<string|RegExp>} rules 忽略规则
46
+ * @returns {boolean} 命中返回 true
47
+ */
48
+ function isIgnored(target, rules) {
49
+ if (!rules || !target) {
50
+ return false;
51
+ }
52
+ var list = Array.isArray(rules) ? rules : String(rules).split(',');
53
+ for (var i = 0; i < list.length; i++) {
54
+ var raw = list[i];
55
+ if (!raw) {
56
+ continue;
57
+ }
58
+ if (raw instanceof RegExp) {
59
+ if (raw.test(target)) {
60
+ return true;
61
+ }
62
+ continue;
63
+ }
64
+ var rule = String(raw).trim();
65
+ if (!rule) {
66
+ continue;
67
+ }
68
+ if (rule.indexOf('*') === -1) {
69
+ // 无通配:精确或路径段前缀
70
+ if (target === rule) {
71
+ return true;
72
+ }
73
+ var prefix = rule.endsWith('/') ? rule : rule + '/';
74
+ if (target.startsWith(prefix)) {
75
+ return true;
76
+ }
77
+ continue;
78
+ }
79
+ if (_compileRule(rule).test(target)) {
80
+ return true;
81
+ }
82
+ }
83
+ return false;
84
+ }
85
+
13
86
  /**
14
87
  * 静态文件处理类
15
88
  */
@@ -56,7 +129,9 @@ class StaticHandle {
56
129
  // 是否开启文件监听
57
130
  watch: false,
58
131
  // 监听的文件扩展名
59
- watch_files: ['.js', '.css', '.html', '.vue', '.json', '.md']
132
+ watch_files: ['.js', '.css', '.html', '.vue', '.json', '.md'],
133
+ // 忽略的请求路径(不参与静态匹配),支持 * 通配,如 ['/api*', '/apis*', '*.map']
134
+ ignore: []
60
135
  };
61
136
 
62
137
  /**
@@ -633,9 +708,72 @@ StaticHandle.prototype._getHeaders = function (file_type) {
633
708
  case 'swf':
634
709
  headers['content-type'] = 'application/x-shockwave-flash';
635
710
  break;
636
- default:
711
+ case 'jpg':
712
+ case 'jpeg':
713
+ headers['content-type'] = 'image/jpeg';
714
+ break;
715
+ case 'png':
716
+ headers['content-type'] = 'image/png';
717
+ break;
718
+ case 'gif':
719
+ headers['content-type'] = 'image/gif';
720
+ break;
721
+ case 'webp':
722
+ headers['content-type'] = 'image/webp';
723
+ break;
724
+ case 'avif':
725
+ headers['content-type'] = 'image/avif';
726
+ break;
727
+ case 'bmp':
728
+ headers['content-type'] = 'image/bmp';
729
+ break;
730
+ case 'svg':
731
+ headers['content-type'] = 'image/svg+xml';
732
+ break;
733
+ case 'ico':
734
+ headers['content-type'] = 'image/x-icon';
735
+ break;
736
+ case 'mp4':
737
+ headers['content-type'] = 'video/mp4';
738
+ break;
739
+ case 'webm':
740
+ headers['content-type'] = 'video/webm';
741
+ break;
742
+ case 'mov':
743
+ headers['content-type'] = 'video/quicktime';
744
+ break;
745
+ case 'woff':
746
+ headers['content-type'] = 'font/woff';
747
+ break;
748
+ case 'woff2':
749
+ headers['content-type'] = 'font/woff2';
750
+ break;
751
+ case 'ttf':
752
+ headers['content-type'] = 'font/ttf';
753
+ break;
754
+ case 'otf':
755
+ headers['content-type'] = 'font/otf';
756
+ break;
757
+ case 'eot':
758
+ headers['content-type'] = 'application/vnd.ms-fontobject';
759
+ break;
760
+ case 'pdf':
761
+ headers['content-type'] = 'application/pdf';
762
+ break;
763
+ case 'json':
764
+ headers['content-type'] = 'application/json; charset=utf-8';
765
+ break;
766
+ case 'txt':
637
767
  headers['content-type'] = 'text/plain; charset=utf-8';
638
768
  break;
769
+ case 'xml':
770
+ headers['content-type'] = 'application/xml; charset=utf-8';
771
+ break;
772
+ default:
773
+ // 二进制兜底改为 application/octet-stream:text/plain 会诱导浏览器按文本
774
+ // 处理未知类型(开启 nosniff 的部署下图片/字体直接拒载)
775
+ headers['content-type'] = 'application/octet-stream';
776
+ break;
639
777
  }
640
778
  return headers;
641
779
  };
@@ -829,6 +967,10 @@ StaticHandle.prototype.main = async function (params, ctx, options) {
829
967
  if (!this._isReadable(this._requestMethod(params, ctx))) {
830
968
  return '';
831
969
  }
970
+ // 命中忽略规则(如 /api*)直接放行,由事件链处理,不做静态匹配
971
+ if (this._isIgnored(p)) {
972
+ return '';
973
+ }
832
974
  // 无扩展名的路径交给目录分支与后续事件处理
833
975
  if (p.indexOf('.') === -1) {
834
976
  return '';
@@ -857,6 +999,15 @@ StaticHandle.prototype.main = async function (params, ctx, options) {
857
999
  }
858
1000
  };
859
1001
 
1002
+ /**
1003
+ * 判断请求路径是否命中本驱动的忽略规则
1004
+ * @param {string} path 请求路径
1005
+ * @returns {boolean} 命中返回 true
1006
+ */
1007
+ StaticHandle.prototype._isIgnored = function (path) {
1008
+ return isIgnored(path, this.config.ignore);
1009
+ };
1010
+
860
1011
  /**
861
1012
  * 关闭文件监听器
862
1013
  */
@@ -867,4 +1018,6 @@ StaticHandle.prototype.closeWatcher = function () {
867
1018
  }
868
1019
  };
869
1020
 
870
- module.exports = StaticHandle;
1021
+ module.exports = StaticHandle;
1022
+ // 忽略规则匹配函数,供静态管理器(manager.js)复用
1023
+ module.exports.isIgnored = isIgnored;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_statics",
3
- "version": "1.9.5",
3
+ "version": "1.9.6",
4
4
  "description": "这是超级美眉statics函数模块,用于web服务端statics缓存",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -55,7 +55,7 @@
55
55
  "mm_corejs": "^1.1.5",
56
56
  "mm_es6_to_amd": "^1.5.9",
57
57
  "mm_helper": "^1.0.0",
58
- "mm_machine": "^3.5.4",
58
+ "mm_machine": "^3.6.0",
59
59
  "prettier": "^3.9.10"
60
60
  },
61
61
  "devDependencies": {
@@ -63,7 +63,6 @@
63
63
  "eslint-plugin-jsdoc": "^65.3.4",
64
64
  "koa": "^3.2.1",
65
65
  "mm_eslint": "^1.7.7",
66
- "mm_expand": "^2.5.4",
67
66
  "mocha": "^12.0.3",
68
67
  "supertest": "^7.3.1"
69
68
  }