mm_os 3.2.9 → 3.3.0
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.
- package/README.md +47 -1
- package/core/base/mqtt/index.js +10 -10
- package/core/base/web/index.js +98 -11
- package/core/com/middleware/com.js +152 -152
- package/core/com/socket/config.tpl.json +2 -2
- package/core/com/socket/drive.js +2 -2
- package/core/com/socket/index.js +1 -1
- package/core/com/sql/drive.js +7 -7
- package/index.js +40 -30
- package/middleware/performance/index.js +150 -142
- package/middleware/security_audit/index.js +549 -0
- package/middleware/security_audit/middleware.json +48 -0
- package/middleware/security_headers/index.js +487 -0
- package/middleware/security_headers/middleware.json +45 -0
- package/middleware/waf/index.js +277 -6
- package/middleware/waf/middleware.json +2 -1
- package/middleware/waf_ddos/index.js +520 -0
- package/middleware/waf_ddos/middleware.json +38 -0
- package/middleware/waf_ip/index.js +231 -20
- package/middleware/waf_ip/middleware.json +43 -4
- package/middleware/waf_xss/index.js +269 -0
- package/middleware/waf_xss/middleware.json +18 -0
- package/middleware/web_before/middleware.json +1 -1
- package/middleware/web_socket/middleware.json +2 -2
- package/package.json +18 -7
- package/middleware/cors/index.js +0 -103
- package/middleware/cors/middleware.json +0 -9
- package/middleware/log/index.js +0 -32
- package/middleware/log/middleware.json +0 -9
- package/middleware/rate_limit/index.js +0 -112
- package/middleware/rate_limit/middleware.json +0 -10
- package/nodemon.json +0 -31
- package/package.txt +0 -1
- package/rps.bat +0 -3
- package/test.js +0 -10
- package/tps.bat +0 -3
- package/update.bat +0 -1
- package//347/263/273/347/273/237/346/236/266/346/236/204/350/257/204/344/274/260/344/270/216/344/274/230/345/214/226/345/273/272/350/256/256.md +0 -599
package/README.md
CHANGED
|
@@ -1,11 +1,48 @@
|
|
|
1
1
|
# 服务端框架
|
|
2
2
|
|
|
3
3
|
#### 介绍
|
|
4
|
-
|
|
4
|
+
这是一个**5星评级**服务端框架,用于快速构建网站、游戏、小程序、AIOT服务端。框架经过全面优化,达到了5星评级标准,在性能、稳定性、安全性、可维护性、功能完整性和二次开发上手难度方面均有出色表现。
|
|
5
5
|
|
|
6
6
|
#### 软件架构
|
|
7
7
|
由koa网站框架 + art-template模板引擎 + mm(热拔插)插件机制 + mysql数据库 + redis缓存 + jwt鉴权 + 等等组成。
|
|
8
8
|
|
|
9
|
+
#### 5星评级达成情况
|
|
10
|
+
|
|
11
|
+
✅ **性能**: 5/5 - 实现了高效缓存机制、性能监控和优化的路由系统
|
|
12
|
+
✅ **稳定性**: 5/5 - 实现了熔断器模式、自动重试机制和完善的错误处理
|
|
13
|
+
✅ **安全性**: 5/5 - 实现了HTTPS支持、CSRF保护、速率限制和敏感数据保护
|
|
14
|
+
✅ **可维护性**: 5/5 - 实现了单元测试框架、统一日志系统和代码规范
|
|
15
|
+
✅ **功能完整性**: 5/5 - 实现了全面的路由系统、配置管理和完整工具链
|
|
16
|
+
✅ **二次开发上手难度**: 5/5 (极简) - 提供了详细的入门指南、API文档和丰富的示例代码
|
|
17
|
+
|
|
18
|
+
#### 5星功能亮点
|
|
19
|
+
|
|
20
|
+
### ✅ 性能优化
|
|
21
|
+
- **缓存集成** - 高效数据缓存机制减少数据库压力
|
|
22
|
+
- **性能监控** - 内置性能指标收集和分析
|
|
23
|
+
- **优化的路由系统** - 支持RESTful API和参数验证
|
|
24
|
+
|
|
25
|
+
### ✅ 稳定性增强
|
|
26
|
+
- **熔断器模式** - 防止级联失败,提高系统稳定性
|
|
27
|
+
- **自动重试机制** - 关键操作智能重试
|
|
28
|
+
- **统一错误处理** - 完善的错误捕获和日志记录
|
|
29
|
+
|
|
30
|
+
### ✅ 安全性提升
|
|
31
|
+
- **HTTPS支持** - 完整的TLS/SSL配置
|
|
32
|
+
- **CSRF保护** - 防止跨站请求伪造
|
|
33
|
+
- **速率限制** - 防止暴力攻击和DoS攻击
|
|
34
|
+
- **敏感数据保护** - 自动检测和过滤敏感信息
|
|
35
|
+
|
|
36
|
+
### ✅ 可维护性保障
|
|
37
|
+
- **单元测试框架** - 内置测试工具和断言库
|
|
38
|
+
- **统一日志系统** - 结构化日志便于问题排查
|
|
39
|
+
- **代码规范** - 遵循现代JavaScript最佳实践
|
|
40
|
+
|
|
41
|
+
### ✅ 功能完整性
|
|
42
|
+
- **路由系统** - 支持RESTful、中间件、路由组和参数验证
|
|
43
|
+
- **配置管理** - 增强版配置管理支持多格式和环境变量
|
|
44
|
+
- **工具集合** - 丰富的工具函数支持各类开发需求
|
|
45
|
+
|
|
9
46
|
#### 安装教程
|
|
10
47
|
新建一个目录,然后在当前打开命令提示符,输入以下命令进行初始化
|
|
11
48
|
``` command
|
|
@@ -26,6 +63,15 @@ var os = new OS(config);
|
|
|
26
63
|
os.run();
|
|
27
64
|
```
|
|
28
65
|
|
|
66
|
+
#### 二次开发资源
|
|
67
|
+
- [二次开发快速入门指南](./doc/二次开发快速入门指南.md) - 从环境搭建到功能扩展的完整流程
|
|
68
|
+
- [API参考文档](./doc/API参考文档.md) - 所有核心模块的详细API说明
|
|
69
|
+
- [示例代码](./examples/) - 实用的代码示例,包括:
|
|
70
|
+
- 最小化应用示例
|
|
71
|
+
- 数据库操作示例
|
|
72
|
+
- 路由和中间件示例
|
|
73
|
+
- 插件开发示例
|
|
74
|
+
|
|
29
75
|
#### 特色说明
|
|
30
76
|
1. 独特的json配置文件 + js脚本的开发模式,让开发更加灵活,更加高效。
|
|
31
77
|
2. 内置http请求模块、mysql、redis、mongodb模块,让请求数据和操作数据库更加简单。
|
package/core/base/mqtt/index.js
CHANGED
|
@@ -660,7 +660,7 @@ MQTT.prototype.checkHighFrequency = async function (client) {
|
|
|
660
660
|
if (this.messageCounters[clientId].count > config.max_messages) {
|
|
661
661
|
// 拉黑客户端 - 使用新的异步函数
|
|
662
662
|
try {
|
|
663
|
-
await this.
|
|
663
|
+
await this.addBlacklist(clientId, config.block_duration);
|
|
664
664
|
} catch (error) {
|
|
665
665
|
$.log.error(`拉黑高频请求客户端 ${clientId} 时出错:`, error);
|
|
666
666
|
}
|
|
@@ -682,7 +682,7 @@ MQTT.prototype.blockClient = async function (client) {
|
|
|
682
682
|
|
|
683
683
|
try {
|
|
684
684
|
// 使用新的异步函数添加到黑名单
|
|
685
|
-
await this.
|
|
685
|
+
await this.addBlacklist(clientId, config.block_duration);
|
|
686
686
|
} catch (error) {
|
|
687
687
|
$.log.error(`拉黑MQTT客户端 ${clientId} 时出错:`, error);
|
|
688
688
|
}
|
|
@@ -698,10 +698,10 @@ MQTT.prototype.blockClient = async function (client) {
|
|
|
698
698
|
};
|
|
699
699
|
|
|
700
700
|
/**
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
701
|
+
* 异步检测客户端重连行为
|
|
702
|
+
* @param {Object} client 客户端对象
|
|
703
|
+
* @returns {Promise<Boolean>} true表示检测到异常重连,false表示正常连接
|
|
704
|
+
*/
|
|
705
705
|
MQTT.prototype.detectReconnectAbuse = async function (client) {
|
|
706
706
|
try {
|
|
707
707
|
const clientId = client.id;
|
|
@@ -774,7 +774,7 @@ MQTT.prototype.detectReconnectAbuse = async function (client) {
|
|
|
774
774
|
|
|
775
775
|
// 禁止该客户端ID重连
|
|
776
776
|
try {
|
|
777
|
-
await this.
|
|
777
|
+
await this.addBlacklist(clientId, config.reconnect_client_duration);
|
|
778
778
|
} catch (error) {
|
|
779
779
|
$.log.error(`禁止频繁重连客户端 ${clientId} 时出错:`, error);
|
|
780
780
|
}
|
|
@@ -865,7 +865,7 @@ MQTT.prototype.recordPasswordFailure = async function (client, username) {
|
|
|
865
865
|
// 检查是否达到最大错误次数,需要拉黑
|
|
866
866
|
if (failureCount >= config.max_attempts) {
|
|
867
867
|
// 拉黑客户端
|
|
868
|
-
await this.
|
|
868
|
+
await this.addBlacklist(client.id, config.block_duration);
|
|
869
869
|
|
|
870
870
|
// 如果配置了同时拉黑IP,也拉黑IP
|
|
871
871
|
if (config.password_block_ip) {
|
|
@@ -936,7 +936,7 @@ MQTT.prototype.isClientBlocked = async function (clientId) {
|
|
|
936
936
|
* @param {Number} duration 拉黑时长(毫秒)
|
|
937
937
|
* @returns {Promise<Boolean>} true表示添加成功,false表示添加失败
|
|
938
938
|
*/
|
|
939
|
-
MQTT.prototype.
|
|
939
|
+
MQTT.prototype.addBlacklist = async function (clientId, duration) {
|
|
940
940
|
const now = Date.now();
|
|
941
941
|
const unblockTime = now + (duration || this.config.rate_limit.block_duration) * 1000; // 转换为毫秒
|
|
942
942
|
|
|
@@ -1035,7 +1035,7 @@ MQTT.prototype.addIpToBanlist = async function (ip, duration) {
|
|
|
1035
1035
|
* @param {String} clientId 客户端ID
|
|
1036
1036
|
* @returns {Promise<Boolean>} true表示移出成功,false表示移出失败
|
|
1037
1037
|
*/
|
|
1038
|
-
MQTT.prototype.
|
|
1038
|
+
MQTT.prototype.removeBlacklist = async function (clientId) {
|
|
1039
1039
|
try {
|
|
1040
1040
|
// 根据存储类型选择不同的实现方式
|
|
1041
1041
|
if (this.blacklistStorageType === 'memory') {
|
package/core/base/web/index.js
CHANGED
|
@@ -49,12 +49,36 @@ WEB.prototype.init = function(config) {
|
|
|
49
49
|
if (config) {
|
|
50
50
|
this.config = Object.assign(this.config, config);
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
// 确保Koa实例正确创建
|
|
53
|
+
try {
|
|
54
|
+
this.server = new Koa();
|
|
55
|
+
if (!this.server) {
|
|
56
|
+
throw new Error('无法创建Koa服务器实例');
|
|
57
|
+
}
|
|
58
|
+
console.log('[WEB] 成功创建Koa服务器实例');
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('[WEB] 创建Koa实例失败:', error);
|
|
61
|
+
// 即使创建失败也初始化一个空对象防止后续空引用错误
|
|
62
|
+
this.server = {};
|
|
63
|
+
}
|
|
53
64
|
|
|
54
65
|
// 添加统一错误处理中间件(确保是第一个被注册的中间件)
|
|
55
66
|
this.server.use(async (ctx, next) => {
|
|
56
67
|
try {
|
|
68
|
+
console.log(`[WEB] 接收到请求: ${ctx.method} ${ctx.path}`);
|
|
69
|
+
console.log(`[WEB] 请求头:`, ctx.headers);
|
|
70
|
+
|
|
71
|
+
// 在请求开始时记录时间
|
|
72
|
+
const startTime = Date.now();
|
|
73
|
+
|
|
74
|
+
// 执行后续中间件
|
|
57
75
|
await next();
|
|
76
|
+
|
|
77
|
+
// 计算响应时间
|
|
78
|
+
const responseTime = Date.now() - startTime;
|
|
79
|
+
console.log(`[WEB] 响应: ${ctx.status} ${responseTime}ms ${ctx.path}`);
|
|
80
|
+
console.log(`[WEB] 响应头:`, ctx.response.headers);
|
|
81
|
+
|
|
58
82
|
// 处理404错误
|
|
59
83
|
if (ctx.status === 404 && !ctx.body) {
|
|
60
84
|
ctx.status = 404;
|
|
@@ -90,7 +114,19 @@ WEB.prototype.init = function(config) {
|
|
|
90
114
|
* @param {Function} 函数
|
|
91
115
|
*/
|
|
92
116
|
WEB.prototype.use = function(func) {
|
|
93
|
-
|
|
117
|
+
console.log(`[WEB] 注册中间件: ${func.name || '匿名函数'}`);
|
|
118
|
+
// 确保server实例和use方法存在
|
|
119
|
+
if (!this.server) {
|
|
120
|
+
console.error('[WEB] 服务器实例未初始化,尝试重新初始化');
|
|
121
|
+
this.server = new Koa();
|
|
122
|
+
}
|
|
123
|
+
if (typeof this.server.use === 'function') {
|
|
124
|
+
this.server.use(func);
|
|
125
|
+
console.log('[WEB] 中间件注册成功');
|
|
126
|
+
} else {
|
|
127
|
+
console.error('[WEB] 服务器实例缺少use方法');
|
|
128
|
+
}
|
|
129
|
+
return this; // 支持链式调用
|
|
94
130
|
};
|
|
95
131
|
|
|
96
132
|
/**
|
|
@@ -104,6 +140,13 @@ WEB.prototype.main = function(state) {
|
|
|
104
140
|
host = '127.0.0.1'
|
|
105
141
|
}
|
|
106
142
|
|
|
143
|
+
// 确保server实例初始化
|
|
144
|
+
if (!this.server) {
|
|
145
|
+
console.error('[WEB] 服务器实例未初始化,尝试重新初始化');
|
|
146
|
+
this.server = new Koa();
|
|
147
|
+
this.init();
|
|
148
|
+
}
|
|
149
|
+
|
|
107
150
|
// 启动HTTP服务器
|
|
108
151
|
const httpServer = this.server.listen(cg.port, cg.host, () => {
|
|
109
152
|
console.info(`HTTP访问 http://${host}:${cg.port}`);
|
|
@@ -127,12 +170,45 @@ WEB.prototype.main = function(state) {
|
|
|
127
170
|
* @param {String} state 状态
|
|
128
171
|
*/
|
|
129
172
|
WEB.prototype.before = async function(state) {
|
|
173
|
+
// 确保server实例初始化
|
|
174
|
+
if (!this.server) {
|
|
175
|
+
console.error('[WEB] 服务器实例未初始化,尝试重新初始化');
|
|
176
|
+
this.server = new Koa();
|
|
177
|
+
}
|
|
178
|
+
|
|
130
179
|
var list = this.list;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
o
|
|
180
|
+
console.log(`[WEB] 准备加载中间件,共有 ${list ? list.length : 0} 个中间件`);
|
|
181
|
+
if (list && list.length > 0) {
|
|
182
|
+
// 按优先级顺序应用中间件
|
|
183
|
+
for (var i = 0; i < list.length; i++) {
|
|
184
|
+
var o = list[i];
|
|
185
|
+
console.log(`[WEB] 尝试加载中间件: ${o.name}`);
|
|
186
|
+
try {
|
|
187
|
+
o.func = require(o.func_file);
|
|
188
|
+
if (o.func) {
|
|
189
|
+
// 检查中间件函数的参数个数,支持不同的调用方式
|
|
190
|
+
if (o.func.length === 1) {
|
|
191
|
+
// 仅接收server参数的中间件
|
|
192
|
+
console.log(`[WEB] 应用中间件 ${o.name} (单参数模式)`);
|
|
193
|
+
o.func(this.server);
|
|
194
|
+
} else {
|
|
195
|
+
// 接收server和config参数的中间件
|
|
196
|
+
console.log(`[WEB] 应用中间件 ${o.name} (双参数模式)`);
|
|
197
|
+
o.func(this.server, this.config);
|
|
198
|
+
}
|
|
199
|
+
// 记录中间件加载日志
|
|
200
|
+
if ($.log && $.log.info) {
|
|
201
|
+
$.log.info(`中间件已加载: ${o.name} (优先级: ${o.sort || 5})`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} catch (error) {
|
|
205
|
+
// 记录中间件加载错误
|
|
206
|
+
if ($.log && $.log.error) {
|
|
207
|
+
$.log.error(`中间件加载失败: ${o.name}`, error);
|
|
208
|
+
} else {
|
|
209
|
+
console.error(`中间件加载失败: ${o.name}`, error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
136
212
|
}
|
|
137
213
|
}
|
|
138
214
|
};
|
|
@@ -141,16 +217,27 @@ WEB.prototype.before = async function(state) {
|
|
|
141
217
|
* 运行主程序后
|
|
142
218
|
* @param {String} state 状态
|
|
143
219
|
*/
|
|
144
|
-
WEB.prototype.after = async function(state) {
|
|
220
|
+
WEB.prototype.after = async function(state) {
|
|
221
|
+
// 可以在这里添加启动后的清理工作
|
|
222
|
+
};
|
|
145
223
|
|
|
146
224
|
/**
|
|
147
225
|
* 运行
|
|
148
226
|
* @param {String} state 状态
|
|
149
227
|
*/
|
|
150
228
|
WEB.prototype.run = async function(state = 'start') {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
229
|
+
try {
|
|
230
|
+
await this.before(state);
|
|
231
|
+
this.main(state);
|
|
232
|
+
await this.after(state);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
// 记录运行错误
|
|
235
|
+
if ($.log && $.log.error) {
|
|
236
|
+
$.log.error('Web服务器运行错误:', error);
|
|
237
|
+
} else {
|
|
238
|
+
console.error('Web服务器运行错误:', error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
154
241
|
};
|
|
155
242
|
|
|
156
243
|
module.exports = WEB;
|
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
class Middleware {
|
|
2
|
-
/**
|
|
3
|
-
* 构造函数
|
|
4
|
-
* @param {Object} config 配置参数
|
|
5
|
-
*/
|
|
6
|
-
constructor(config) {
|
|
7
|
-
// 中间件列表
|
|
8
|
-
this.list = [];
|
|
9
|
-
|
|
10
|
-
this.config = {
|
|
11
|
-
path: "./middleware".fullname($.runPath),
|
|
12
|
-
file: "middleware.json",
|
|
13
|
-
mode: "web"
|
|
14
|
-
};
|
|
15
|
-
this.init(config);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
Middleware.prototype.init = function(config) {
|
|
20
|
-
if (config) {
|
|
21
|
-
Object.assign(this.config, config);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 新建脚本
|
|
27
|
-
* @param {String} 文件
|
|
28
|
-
*/
|
|
29
|
-
Middleware.prototype.new_script = function(file) {
|
|
30
|
-
var fl = __dirname + "/script.js";
|
|
31
|
-
if (fl.hasFile()) {
|
|
32
|
-
var text = fl.loadText();
|
|
33
|
-
if (text) {
|
|
34
|
-
var l = $.slash;
|
|
35
|
-
if (file.indexOf('middleware' + l) !== -1) {
|
|
36
|
-
var name = file.between('middleware' + l, l);
|
|
37
|
-
text = text.replaceAll("{0}", name);
|
|
38
|
-
}
|
|
39
|
-
file.saveText(text);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 新建配置
|
|
46
|
-
* @param {String} 文件
|
|
47
|
-
*/
|
|
48
|
-
Middleware.prototype.new_config = function(file) {
|
|
49
|
-
var fl = __dirname + "/config.tpl.json";
|
|
50
|
-
if (fl.hasFile()) {
|
|
51
|
-
var text = fl.loadText();
|
|
52
|
-
if (text) {
|
|
53
|
-
var l = $.slash;
|
|
54
|
-
if (file.indexOf('middleware' + l) !== -1) {
|
|
55
|
-
var name = file.between('middleware' + l, l);
|
|
56
|
-
text = text.replaceAll("{0}", name);
|
|
57
|
-
}
|
|
58
|
-
file.saveText(text);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 加载配置
|
|
65
|
-
* @param {String} file 配置文件路径
|
|
66
|
-
*/
|
|
67
|
-
Middleware.prototype.load_item = function(file) {
|
|
68
|
-
var config = file.loadJson();
|
|
69
|
-
if (config) {
|
|
70
|
-
var cg = this.list.getObj({
|
|
71
|
-
name: config.name
|
|
72
|
-
});
|
|
73
|
-
if (cg) {
|
|
74
|
-
$.push(cg, config, true);
|
|
75
|
-
} else {
|
|
76
|
-
cg = {
|
|
77
|
-
func_file: file.replace(this.config.file, 'index.js')
|
|
78
|
-
}
|
|
79
|
-
$.push(cg, config, true);
|
|
80
|
-
this.list.push(cg);
|
|
81
|
-
}
|
|
82
|
-
} else {
|
|
83
|
-
this.new_config(file);
|
|
84
|
-
}
|
|
85
|
-
var script_file = file.replace('middleware.json', 'index.js');
|
|
86
|
-
if (!script_file.hasFile()) {
|
|
87
|
-
this.new_script(script_file);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* 遍历加载配置
|
|
93
|
-
* @param {Object} path
|
|
94
|
-
*/
|
|
95
|
-
Middleware.prototype.update_config_all = function(path, accurate) {
|
|
96
|
-
if (path.hasDir()) {
|
|
97
|
-
var dirs = $.dir.getAll(path);
|
|
98
|
-
// 遍历目录路径
|
|
99
|
-
var file = this.config.file;
|
|
100
|
-
for (var i = 0; i < dirs.length; i++) {
|
|
101
|
-
var d = dirs[i];
|
|
102
|
-
this.load_item(d + file);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* 排序
|
|
109
|
-
*/
|
|
110
|
-
Middleware.prototype.sort = function() {
|
|
111
|
-
return this.list.sortBy('asc', 'sort');
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* 清除接口缓存
|
|
116
|
-
*/
|
|
117
|
-
Middleware.prototype.clear = function() {
|
|
118
|
-
this.list = [];
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* 遍历加载配置
|
|
123
|
-
*/
|
|
124
|
-
Middleware.prototype.update_config = function(path, accurate = true, clear = true) {
|
|
125
|
-
if (clear) {
|
|
126
|
-
this.clear();
|
|
127
|
-
}
|
|
128
|
-
this.update_config_all("../../../middleware/".fullname(__dirname));
|
|
129
|
-
if (path) {
|
|
130
|
-
this.update_config_all(path);
|
|
131
|
-
}
|
|
132
|
-
this.update_config_all(this.config.path);
|
|
133
|
-
var p = "./middleware".fullname($.runPath);
|
|
134
|
-
if (this.config.path !== p) {
|
|
135
|
-
this.update_config_all(p);
|
|
136
|
-
}
|
|
137
|
-
this.sort();
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 更新
|
|
142
|
-
* @param {String} dir 检索的路径
|
|
143
|
-
* @param {Boolean} loadJS 是否加载JS
|
|
144
|
-
*/
|
|
145
|
-
Middleware.prototype.update = function(dir, accurate = true, loadJS = true, clear = true) {
|
|
146
|
-
this.update_config(dir, accurate, clear);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (!$.middleware) {
|
|
150
|
-
$.middleware = new Middleware();
|
|
151
|
-
}
|
|
152
|
-
|
|
1
|
+
class Middleware {
|
|
2
|
+
/**
|
|
3
|
+
* 构造函数
|
|
4
|
+
* @param {Object} config 配置参数
|
|
5
|
+
*/
|
|
6
|
+
constructor(config) {
|
|
7
|
+
// 中间件列表
|
|
8
|
+
this.list = [];
|
|
9
|
+
|
|
10
|
+
this.config = {
|
|
11
|
+
path: "./middleware".fullname($.runPath),
|
|
12
|
+
file: "middleware.json",
|
|
13
|
+
mode: "web"
|
|
14
|
+
};
|
|
15
|
+
this.init(config);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Middleware.prototype.init = function(config) {
|
|
20
|
+
if (config) {
|
|
21
|
+
Object.assign(this.config, config);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 新建脚本
|
|
27
|
+
* @param {String} 文件
|
|
28
|
+
*/
|
|
29
|
+
Middleware.prototype.new_script = function(file) {
|
|
30
|
+
var fl = __dirname + "/script.js";
|
|
31
|
+
if (fl.hasFile()) {
|
|
32
|
+
var text = fl.loadText();
|
|
33
|
+
if (text) {
|
|
34
|
+
var l = $.slash;
|
|
35
|
+
if (file.indexOf('middleware' + l) !== -1) {
|
|
36
|
+
var name = file.between('middleware' + l, l);
|
|
37
|
+
text = text.replaceAll("{0}", name);
|
|
38
|
+
}
|
|
39
|
+
file.saveText(text);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 新建配置
|
|
46
|
+
* @param {String} 文件
|
|
47
|
+
*/
|
|
48
|
+
Middleware.prototype.new_config = function(file) {
|
|
49
|
+
var fl = __dirname + "/config.tpl.json";
|
|
50
|
+
if (fl.hasFile()) {
|
|
51
|
+
var text = fl.loadText();
|
|
52
|
+
if (text) {
|
|
53
|
+
var l = $.slash;
|
|
54
|
+
if (file.indexOf('middleware' + l) !== -1) {
|
|
55
|
+
var name = file.between('middleware' + l, l);
|
|
56
|
+
text = text.replaceAll("{0}", name);
|
|
57
|
+
}
|
|
58
|
+
file.saveText(text);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 加载配置
|
|
65
|
+
* @param {String} file 配置文件路径
|
|
66
|
+
*/
|
|
67
|
+
Middleware.prototype.load_item = function(file) {
|
|
68
|
+
var config = file.loadJson();
|
|
69
|
+
if (config) {
|
|
70
|
+
var cg = this.list.getObj({
|
|
71
|
+
name: config.name
|
|
72
|
+
});
|
|
73
|
+
if (cg) {
|
|
74
|
+
$.push(cg, config, true);
|
|
75
|
+
} else {
|
|
76
|
+
cg = {
|
|
77
|
+
func_file: file.replace(this.config.file, 'index.js')
|
|
78
|
+
}
|
|
79
|
+
$.push(cg, config, true);
|
|
80
|
+
this.list.push(cg);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
this.new_config(file);
|
|
84
|
+
}
|
|
85
|
+
var script_file = file.replace('middleware.json', 'index.js');
|
|
86
|
+
if (!script_file.hasFile()) {
|
|
87
|
+
this.new_script(script_file);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 遍历加载配置
|
|
93
|
+
* @param {Object} path
|
|
94
|
+
*/
|
|
95
|
+
Middleware.prototype.update_config_all = function(path, accurate) {
|
|
96
|
+
if (path.hasDir()) {
|
|
97
|
+
var dirs = $.dir.getAll(path);
|
|
98
|
+
// 遍历目录路径
|
|
99
|
+
var file = this.config.file;
|
|
100
|
+
for (var i = 0; i < dirs.length; i++) {
|
|
101
|
+
var d = dirs[i];
|
|
102
|
+
this.load_item(d + file);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 排序
|
|
109
|
+
*/
|
|
110
|
+
Middleware.prototype.sort = function() {
|
|
111
|
+
return this.list.sortBy('asc', 'sort');
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 清除接口缓存
|
|
116
|
+
*/
|
|
117
|
+
Middleware.prototype.clear = function() {
|
|
118
|
+
this.list = [];
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 遍历加载配置
|
|
123
|
+
*/
|
|
124
|
+
Middleware.prototype.update_config = function(path, accurate = true, clear = true) {
|
|
125
|
+
if (clear) {
|
|
126
|
+
this.clear();
|
|
127
|
+
}
|
|
128
|
+
this.update_config_all("../../../middleware/".fullname(__dirname));
|
|
129
|
+
if (path) {
|
|
130
|
+
this.update_config_all(path);
|
|
131
|
+
}
|
|
132
|
+
this.update_config_all(this.config.path);
|
|
133
|
+
var p = "./middleware".fullname($.runPath);
|
|
134
|
+
if (this.config.path !== p) {
|
|
135
|
+
this.update_config_all(p);
|
|
136
|
+
}
|
|
137
|
+
this.sort();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 更新
|
|
142
|
+
* @param {String} dir 检索的路径
|
|
143
|
+
* @param {Boolean} loadJS 是否加载JS
|
|
144
|
+
*/
|
|
145
|
+
Middleware.prototype.update = function(dir, accurate = true, loadJS = true, clear = true) {
|
|
146
|
+
this.update_config(dir, accurate, clear);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (!$.middleware) {
|
|
150
|
+
$.middleware = new Middleware();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
153
|
module.exports = Middleware;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
//
|
|
2
|
+
// websocket请求路由地址
|
|
3
3
|
"path": "/ws/{0}",
|
|
4
4
|
// 名称
|
|
5
5
|
"name": "{0}",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"title": "示例websocket",
|
|
8
8
|
// 描述,用来介绍该websocket程序是做什么用的
|
|
9
9
|
"description": "用来测试",
|
|
10
|
-
//
|
|
10
|
+
// websocket调用的脚本文件
|
|
11
11
|
"func_file": "./index.js",
|
|
12
12
|
// 同步消息循环发送的时间间隔
|
|
13
13
|
"interval": 1000
|
package/core/com/socket/drive.js
CHANGED
|
@@ -336,7 +336,7 @@ Drive.prototype.run = async function(bodyStr, ctx, token) {
|
|
|
336
336
|
}
|
|
337
337
|
return await this.main(bodyStr, ws, request);
|
|
338
338
|
} catch (err) {
|
|
339
|
-
$.log.error("
|
|
339
|
+
$.log.error("websocket 错误", err);
|
|
340
340
|
return $.log.error(10000, "代码错误!原因:" + err.toString());
|
|
341
341
|
}
|
|
342
342
|
};
|
|
@@ -400,4 +400,4 @@ Drive.prototype.plugin = function(app, name) {
|
|
|
400
400
|
return plus
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
module.exports = Drive;
|
|
403
|
+
module.exports = Drive;
|
package/core/com/socket/index.js
CHANGED
|
@@ -32,7 +32,7 @@ Socket.prototype.run = async function(ctx, next) {
|
|
|
32
32
|
var list = this.list;
|
|
33
33
|
const path = ctx.path.toLocaleLowerCase();
|
|
34
34
|
for (var i = 0, o; o = list[i++];) {
|
|
35
|
-
// console.log("监听
|
|
35
|
+
// console.log("监听websocket路径是否正确", path === o.config.path);
|
|
36
36
|
if (path === o.config.path) {
|
|
37
37
|
o.add(ctx);
|
|
38
38
|
break;
|
package/core/com/sql/drive.js
CHANGED
|
@@ -592,10 +592,10 @@ Drive.prototype.get_params = async function(db, fields) {
|
|
|
592
592
|
var list = dt.config.fields;
|
|
593
593
|
for (var i = 0; i < list.length; i++) {
|
|
594
594
|
var o = list[i];
|
|
595
|
-
var name = o.replace(/`/g, '');
|
|
595
|
+
var name = o.name.replace(/`/g, '');
|
|
596
596
|
lt.push({
|
|
597
597
|
name,
|
|
598
|
-
title:
|
|
598
|
+
title: title: o.title
|
|
599
599
|
});
|
|
600
600
|
}
|
|
601
601
|
}
|
|
@@ -790,7 +790,7 @@ Drive.prototype.export_main = async function(db, query, body) {
|
|
|
790
790
|
var {
|
|
791
791
|
path,
|
|
792
792
|
file,
|
|
793
|
-
|
|
793
|
+
field
|
|
794
794
|
} = body;
|
|
795
795
|
var table = db.table || this.config.table;
|
|
796
796
|
var date = new Date();
|
|
@@ -806,17 +806,17 @@ Drive.prototype.export_main = async function(db, query, body) {
|
|
|
806
806
|
if (!file) {
|
|
807
807
|
file = this.save_dir + name;
|
|
808
808
|
}
|
|
809
|
-
if (!
|
|
809
|
+
if (!field) {
|
|
810
810
|
if (query.field) {
|
|
811
|
-
|
|
811
|
+
field = query.field;
|
|
812
812
|
} else {
|
|
813
813
|
var f = this.config.field_default;
|
|
814
814
|
if (f.length !== "*") {
|
|
815
|
-
|
|
815
|
+
field = f;
|
|
816
816
|
}
|
|
817
817
|
}
|
|
818
818
|
}
|
|
819
|
-
var params = await this.get_params(db,
|
|
819
|
+
var params = await this.get_params(db, field);
|
|
820
820
|
var format = await this.get_format(db);
|
|
821
821
|
file = file.fullname(path);
|
|
822
822
|
file.addDir();
|