abler-api 0.1.16 → 0.1.19
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 +7 -2
- package/dist/cjs/pp-util.js +416 -64
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ API服务相关工具
|
|
|
5
5
|
安装
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
npm i abler-api
|
|
8
|
+
npm i abler-api@latest -s
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
|
|
@@ -13,8 +13,13 @@ npm i abler-api-util@latest -s
|
|
|
13
13
|
引用
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
const {apiUtil} = require("abler-api");
|
|
16
|
+
const {apiUtil, preconditions} = require("abler-api");
|
|
17
17
|
apiUtil.config(conf,errCfg,dbSql);
|
|
18
18
|
...
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### preconditions
|
|
24
|
+
|
|
25
|
+
API服务启动时前置条件检查,使用
|
package/dist/cjs/pp-util.js
CHANGED
|
@@ -3,20 +3,27 @@
|
|
|
3
3
|
var require$$0 = require('crypto');
|
|
4
4
|
var require$$1 = require('abler-util');
|
|
5
5
|
var require$$2 = require('abler-db');
|
|
6
|
+
var require$$3 = require('abler-net');
|
|
7
|
+
var require$$0$1 = require('fs');
|
|
8
|
+
var require$$1$1 = require('path');
|
|
6
9
|
|
|
7
10
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
11
|
|
|
9
12
|
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
|
|
10
13
|
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
11
14
|
var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
|
|
15
|
+
var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
|
|
16
|
+
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
|
|
17
|
+
var require$$1__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$1$1);
|
|
12
18
|
|
|
13
19
|
const crypto = require$$0__default["default"];
|
|
14
|
-
const ppUtil$
|
|
20
|
+
const ppUtil$2 = require$$1__default["default"].ppUtil;
|
|
15
21
|
const {
|
|
16
22
|
dbUtil,
|
|
17
23
|
kvStorage
|
|
18
24
|
} = require$$2__default["default"];
|
|
19
|
-
|
|
25
|
+
const netUtil = require$$3__default["default"];
|
|
26
|
+
let conf$1, appSetting, err$1, dbSql;
|
|
20
27
|
const pnToken = "access_token",
|
|
21
28
|
hnToken = pnToken,
|
|
22
29
|
pnApiKey = "apiKey",
|
|
@@ -24,20 +31,20 @@ const pnToken = "access_token",
|
|
|
24
31
|
// 我们接收到的 headers 中的字段名总是全小写的
|
|
25
32
|
pnApiSecret = "apiSecret",
|
|
26
33
|
hnApiSecret = pnApiSecret.toLowerCase();
|
|
27
|
-
const MD5 = ppUtil$
|
|
28
|
-
moveProperty = ppUtil$
|
|
34
|
+
const MD5 = ppUtil$2.MD5,
|
|
35
|
+
moveProperty = ppUtil$2.moveProperty;
|
|
29
36
|
|
|
30
37
|
class apiUtil$1 {
|
|
31
|
-
static debugFlag = ppUtil$
|
|
38
|
+
static debugFlag = ppUtil$2.newGuid(); //应用必须设置,否则谁也不知道是啥
|
|
32
39
|
|
|
33
|
-
static testFlag = ppUtil$
|
|
40
|
+
static testFlag = ppUtil$2.newGuid();
|
|
34
41
|
static envId_dev = "?"; // static apiCallRecSaver;
|
|
35
42
|
|
|
36
43
|
static config(appConfig, appErrCfg, appDbSql) {
|
|
37
|
-
ppUtil$
|
|
38
|
-
conf = appConfig;
|
|
39
|
-
appSetting = conf?.appSetting;
|
|
40
|
-
err = appErrCfg, dbSql = appDbSql;
|
|
44
|
+
ppUtil$2.config(appConfig, appErrCfg);
|
|
45
|
+
conf$1 = appConfig;
|
|
46
|
+
appSetting = conf$1?.appSetting;
|
|
47
|
+
err$1 = appErrCfg, dbSql = appDbSql;
|
|
41
48
|
apiUtil$1.debugFlag = appSetting?.debugFlag || apiUtil$1.debugFlag;
|
|
42
49
|
apiUtil$1.testFlag = appSetting?.testFlag || apiUtil$1.testFlag; // apiUtil.apiCallRecSaver = apiCallRecSaver;
|
|
43
50
|
} //#region ===== 需要应用系统重写的方法
|
|
@@ -50,7 +57,7 @@ class apiUtil$1 {
|
|
|
50
57
|
|
|
51
58
|
|
|
52
59
|
static _getApiSecret(companyId) {
|
|
53
|
-
return ppUtil$
|
|
60
|
+
return ppUtil$2.newGuid();
|
|
54
61
|
}
|
|
55
62
|
/**
|
|
56
63
|
* 保存 API 调用记录,应用系统必须重写此方法
|
|
@@ -74,26 +81,6 @@ class apiUtil$1 {
|
|
|
74
81
|
} //#endregion
|
|
75
82
|
//#region ===== API服务相关工具
|
|
76
83
|
|
|
77
|
-
/**
|
|
78
|
-
* 获取客户端IP地址
|
|
79
|
-
* @param req
|
|
80
|
-
* @returns {*|string|string}
|
|
81
|
-
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
static getClientIp(req) {
|
|
85
|
-
let ip = req.headers["x-real-ip"] || req.headers["x-true-ip"] || req.headers['x-forwarded-for'] || req.headers['x-forward-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.headers['host'] || ""; // console.log("Request IP:", ip, "req: ", req);
|
|
86
|
-
|
|
87
|
-
if (ip.indexOf(",") >= 0) {
|
|
88
|
-
ip = ip.split(',')[0];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (ip.indexOf(":") >= 0) {
|
|
92
|
-
ip = ip.substring(ip.lastIndexOf(':') + 1);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return ip;
|
|
96
|
-
}
|
|
97
84
|
/**
|
|
98
85
|
* 从请求中解出数据,包括路径参数、查询参数和Body
|
|
99
86
|
* @param req
|
|
@@ -173,18 +160,18 @@ class apiUtil$1 {
|
|
|
173
160
|
|
|
174
161
|
|
|
175
162
|
static setParamsFunctions(params) {
|
|
176
|
-
ppUtil$
|
|
163
|
+
ppUtil$2.defUnenumProp(params, "asNumber", function (name, minValue, maxValue, defaultValue) {
|
|
177
164
|
// if (!this.hasOwnProperty(name)) // {} 定义的对象没有 hasOwnProperty 函数
|
|
178
165
|
if (this[name] === undefined) return defaultValue;
|
|
179
166
|
let result = +this[name];
|
|
180
167
|
|
|
181
168
|
if (typeof result !== "number" || result < minValue || result > maxValue) {
|
|
182
|
-
throw [err.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
|
|
169
|
+
throw [err$1.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
|
|
183
170
|
}
|
|
184
171
|
|
|
185
172
|
return result;
|
|
186
173
|
});
|
|
187
|
-
ppUtil$
|
|
174
|
+
ppUtil$2.defUnenumProp(params, "asBool", function (name, defaultValue) {
|
|
188
175
|
if (this[name] === undefined) return defaultValue;
|
|
189
176
|
let result = JSON.parse(this[name]);
|
|
190
177
|
return !!result;
|
|
@@ -249,7 +236,7 @@ class apiUtil$1 {
|
|
|
249
236
|
|
|
250
237
|
static apiFail(error, req) {
|
|
251
238
|
configNeeded();
|
|
252
|
-
let response = err.ERROR(error, err.errorLangParamFlag + ppUtil$
|
|
239
|
+
let response = err$1.ERROR(error, err$1.errorLangParamFlag + ppUtil$2.getMsgLang(req));
|
|
253
240
|
response.datetime = new Date();
|
|
254
241
|
|
|
255
242
|
if (req && req.headers) {
|
|
@@ -470,12 +457,12 @@ class apiUtil$1 {
|
|
|
470
457
|
delete params.token;
|
|
471
458
|
} else {
|
|
472
459
|
// 如果没有token,则返回错误
|
|
473
|
-
console.log(err.TOKEN_NEEDED);
|
|
460
|
+
console.log(err$1.TOKEN_NEEDED);
|
|
474
461
|
|
|
475
462
|
if (res) {
|
|
476
|
-
res.send(err.ERROR(err.TOKEN_NEEDED));
|
|
463
|
+
res.send(err$1.ERROR(err$1.TOKEN_NEEDED));
|
|
477
464
|
} else if (!noErr) {
|
|
478
|
-
throw err.TOKEN_NEEDED;
|
|
465
|
+
throw err$1.TOKEN_NEEDED;
|
|
479
466
|
}
|
|
480
467
|
}
|
|
481
468
|
}
|
|
@@ -497,7 +484,7 @@ class apiUtil$1 {
|
|
|
497
484
|
const params = apiUtil$1.extractParams(req);
|
|
498
485
|
req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
|
|
499
486
|
|
|
500
|
-
if (req.accessToken === MD5(ppUtil$
|
|
487
|
+
if (req.accessToken === MD5(ppUtil$2.idNumDisturbing)) {
|
|
501
488
|
//todo: 检查IP
|
|
502
489
|
params.__internal__ = true;
|
|
503
490
|
req.ignoreToken = true; // if (params.idNum || params.personId) {
|
|
@@ -518,7 +505,7 @@ class apiUtil$1 {
|
|
|
518
505
|
return true;
|
|
519
506
|
} else {
|
|
520
507
|
// console.log('token error.', req.accessToken);
|
|
521
|
-
throw err.TOKEN_INVALID;
|
|
508
|
+
throw err$1.TOKEN_INVALID;
|
|
522
509
|
}
|
|
523
510
|
}
|
|
524
511
|
/**
|
|
@@ -554,7 +541,7 @@ class apiUtil$1 {
|
|
|
554
541
|
|
|
555
542
|
if (dbgToken) {
|
|
556
543
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
557
|
-
req.__debug__ = dbgToken && dbgToken === MD5(req.headers.timestamp, ppUtil$
|
|
544
|
+
req.__debug__ = dbgToken && dbgToken === MD5(req.headers.timestamp, ppUtil$2.commonHashDisturbing) && (envId === "florist_longdan" || envId === "shuzi");
|
|
558
545
|
} else {
|
|
559
546
|
req.__debug__ = false;
|
|
560
547
|
} // console.log("__debug__:", req.__debug__, "dbgToken:", dbgToken);
|
|
@@ -734,7 +721,7 @@ class apiUtil$1 {
|
|
|
734
721
|
};
|
|
735
722
|
|
|
736
723
|
if (rec.secret !== "") {
|
|
737
|
-
rec.secret = ppUtil$
|
|
724
|
+
rec.secret = ppUtil$2.getEncAse192(rec.secret);
|
|
738
725
|
}
|
|
739
726
|
|
|
740
727
|
req.apiCallRec = rec;
|
|
@@ -801,7 +788,7 @@ class apiUtil$1 {
|
|
|
801
788
|
return certInfo;
|
|
802
789
|
}).catch(e => {
|
|
803
790
|
console.log('获取企业证书失败:\n', e);
|
|
804
|
-
throw [err.ACCESS_REFUSED, `获取企业证书失败:${err.ERROR(e).message}`];
|
|
791
|
+
throw [err$1.ACCESS_REFUSED, `获取企业证书失败:${err$1.ERROR(e).message}`];
|
|
805
792
|
});
|
|
806
793
|
}
|
|
807
794
|
/**
|
|
@@ -815,7 +802,7 @@ class apiUtil$1 {
|
|
|
815
802
|
static async verifyApiSignature(tokenData, req) {
|
|
816
803
|
try {
|
|
817
804
|
if (!req.headers.timestamp) {
|
|
818
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
805
|
+
throw [err$1.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
819
806
|
}
|
|
820
807
|
|
|
821
808
|
let timestamp = parseInt(req.headers.timestamp);
|
|
@@ -823,13 +810,13 @@ class apiUtil$1 {
|
|
|
823
810
|
let maxTimeDiff = apiUtil$1.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$1.isTestMode(req) ? 4 * 3600 : 100; // 100
|
|
824
811
|
|
|
825
812
|
if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
|
|
826
|
-
throw [err.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
813
|
+
throw [err$1.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
827
814
|
}
|
|
828
815
|
|
|
829
816
|
let signature = req.headers.signature;
|
|
830
817
|
|
|
831
818
|
if (!signature) {
|
|
832
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
819
|
+
throw [err$1.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
833
820
|
}
|
|
834
821
|
|
|
835
822
|
let signData = apiUtil$1.extractToken(req, null, true) || tokenData.apiKey;
|
|
@@ -884,7 +871,7 @@ class apiUtil$1 {
|
|
|
884
871
|
|
|
885
872
|
if (!tokenData.certPublicKeySpare) {
|
|
886
873
|
throw {
|
|
887
|
-
eo: err.ACCESS_REFUSED,
|
|
874
|
+
eo: err$1.ACCESS_REFUSED,
|
|
888
875
|
msgArgv: "签名验证异常",
|
|
889
876
|
data: e
|
|
890
877
|
};
|
|
@@ -933,7 +920,7 @@ class apiUtil$1 {
|
|
|
933
920
|
} catch (e) {
|
|
934
921
|
console.log("SPO服务签名验证异常(备用证书), ", e);
|
|
935
922
|
throw {
|
|
936
|
-
eo: err.ACCESS_REFUSED,
|
|
923
|
+
eo: err$1.ACCESS_REFUSED,
|
|
937
924
|
msgArgv: "签名验证异常(spare)",
|
|
938
925
|
data: e
|
|
939
926
|
};
|
|
@@ -942,7 +929,7 @@ class apiUtil$1 {
|
|
|
942
929
|
|
|
943
930
|
if (!verifyOK) {
|
|
944
931
|
console.log("SPO服务签名验证失败, tokenData: ", tokenData);
|
|
945
|
-
throw [err.ACCESS_REFUSED, "签名验证未通过"];
|
|
932
|
+
throw [err$1.ACCESS_REFUSED, "签名验证未通过"];
|
|
946
933
|
}
|
|
947
934
|
|
|
948
935
|
return verifyOK;
|
|
@@ -960,7 +947,7 @@ class apiUtil$1 {
|
|
|
960
947
|
if (!tokenData.companyInfo) {
|
|
961
948
|
tokenData.companyInfo = await apiUtil$1.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
|
|
962
949
|
console.log("执行企业信息查询发生异常", e);
|
|
963
|
-
throw [err.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
950
|
+
throw [err$1.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
964
951
|
});
|
|
965
952
|
}
|
|
966
953
|
|
|
@@ -969,7 +956,7 @@ class apiUtil$1 {
|
|
|
969
956
|
if (companyInfo != null) {
|
|
970
957
|
let secret = apiUtil$1._getApiSecret(tokenData.apiKey);
|
|
971
958
|
|
|
972
|
-
if (secret !== tokenData.apiSecret) throw err.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
959
|
+
if (secret !== tokenData.apiSecret) throw err$1.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
973
960
|
// console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
|
|
974
961
|
// let whiteList = companyInfo.ipWhiteList || "";
|
|
975
962
|
// // 没有设置ip白名单的就不检查了
|
|
@@ -983,7 +970,7 @@ class apiUtil$1 {
|
|
|
983
970
|
});
|
|
984
971
|
}
|
|
985
972
|
|
|
986
|
-
throw [err.API_KEY_INVALID, tokenData.apiKey];
|
|
973
|
+
throw [err$1.API_KEY_INVALID, tokenData.apiKey];
|
|
987
974
|
}
|
|
988
975
|
/**
|
|
989
976
|
* 检查令牌数据是否存在
|
|
@@ -1034,10 +1021,152 @@ class apiUtil$1 {
|
|
|
1034
1021
|
paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
|
|
1035
1022
|
}
|
|
1036
1023
|
|
|
1037
|
-
if (!paramExists) return ppUtil$
|
|
1024
|
+
if (!paramExists) return ppUtil$2.errorPormise(err$1.ERROR(err$1.PARAMETER_NEEDED, paramName));
|
|
1038
1025
|
}
|
|
1039
1026
|
|
|
1040
1027
|
return Promise.resolve(paramSufix);
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* 获取客户端IP地址
|
|
1031
|
+
* @param req
|
|
1032
|
+
* @returns {*|string|string}
|
|
1033
|
+
*/
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
static getClientIp(req) {
|
|
1037
|
+
let ip = req.headers["x-real-ip"] || req.headers["x-true-ip"] || req.headers['x-forwarded-for'] || req.headers['x-forward-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.headers['host'] || ""; // console.log("Request IP:", ip, "req: ", req);
|
|
1038
|
+
|
|
1039
|
+
if (ip.indexOf(",") >= 0) {
|
|
1040
|
+
ip = ip.split(',')[0];
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
if (ip.indexOf(":") >= 0) {
|
|
1044
|
+
ip = ip.substring(ip.lastIndexOf(':') + 1);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
return ip;
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* 获取与本机一起提供服务的所有主机
|
|
1051
|
+
* @param params
|
|
1052
|
+
* @returns {{port: (number|number), hosts: [string]}}
|
|
1053
|
+
*/
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
static getEnvHosts(params) {
|
|
1057
|
+
configNeeded();
|
|
1058
|
+
let envType = ppUtil$2.getEnvType();
|
|
1059
|
+
let x = conf$1.envHosts[envType] || {
|
|
1060
|
+
hosts: ["localhost"]
|
|
1061
|
+
};
|
|
1062
|
+
let port = +params.port || 8443;
|
|
1063
|
+
return {
|
|
1064
|
+
hosts: x.hosts,
|
|
1065
|
+
port: x.port || port
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* 检查指定的host和发送请求的ip是不是自己的ip
|
|
1070
|
+
* @param host
|
|
1071
|
+
* @param req
|
|
1072
|
+
* @returns {Promise<*>}
|
|
1073
|
+
*/
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
static async hostIsMySelf(host, req) {
|
|
1077
|
+
let clientIp = apiUtil$1.getClientIp(req);
|
|
1078
|
+
return getMyIp({
|
|
1079
|
+
hosts: [host, clientIp]
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* 检查是否应该把请求转发到其它服务器,若是则转发
|
|
1084
|
+
* @param options
|
|
1085
|
+
* @returns {Promise<boolean>}
|
|
1086
|
+
*/
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
static async checkForwardsHost(options) {
|
|
1090
|
+
configNeeded();
|
|
1091
|
+
const params = options.replacements;
|
|
1092
|
+
const myEnvHosts = apiUtil$1.getEnvHosts(params);
|
|
1093
|
+
const myIp = ppUtil$2.getMyIp();
|
|
1094
|
+
const host = params.host || myIp;
|
|
1095
|
+
if (!myEnvHosts.hosts.contains(host)) throw [err$1.ACCESS_REFUSED, `环境${conf$1.envId}貌似无此主机:${params.host}`];
|
|
1096
|
+
|
|
1097
|
+
if (!apiUtil$1.hostIsMySelf(host, options._res.req)) {
|
|
1098
|
+
let result = await apiUtil$1.forwardsTo(host, myEnvHosts.port, params, options._res.req, myIp);
|
|
1099
|
+
|
|
1100
|
+
options._res.send(result);
|
|
1101
|
+
|
|
1102
|
+
return true;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
return false;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* 将收到的请求转发到另一台主机
|
|
1109
|
+
* @param anotherIp
|
|
1110
|
+
* @param port
|
|
1111
|
+
* @param params
|
|
1112
|
+
* @param req
|
|
1113
|
+
* @param lanClient
|
|
1114
|
+
* @returns {Promise<*>}
|
|
1115
|
+
*/
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
static async forwardsTo(anotherIp, port, params, req, lanClient) {
|
|
1119
|
+
let url = anotherIp.indexOf("://") > 0 ? anotherIp : `${req.headers.scheme}://${anotherIp}:${port}${req.originalUrl}`;
|
|
1120
|
+
|
|
1121
|
+
if (url.indexOf("?") > 0) {
|
|
1122
|
+
url = url.substring(0, url.indexOf("?"));
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
let reqOptions = {
|
|
1126
|
+
method: req.method,
|
|
1127
|
+
url: url,
|
|
1128
|
+
data: params
|
|
1129
|
+
};
|
|
1130
|
+
let result = await netUtil.apiRequest(reqOptions);
|
|
1131
|
+
|
|
1132
|
+
if (result.status !== 200) {
|
|
1133
|
+
console.log(`访问 ${reqOptions.url} 出错`, result.status, result.res.statusMessage);
|
|
1134
|
+
throw [err$1.EXCEPTION, `[${result.status}] - ${result.res.statusMessage}`];
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
return result.data;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* 解析配置项路径
|
|
1141
|
+
* @param keyPath
|
|
1142
|
+
* @returns {{parent: null, parentKey: string, value, key: string}}
|
|
1143
|
+
*/
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
static parseCfgPath(keyPath) {
|
|
1147
|
+
let keys = Array.isArray(keyPath) ? keyPath : keyPath.split(".");
|
|
1148
|
+
let parentKey = "";
|
|
1149
|
+
let key = "config";
|
|
1150
|
+
let value = conf$1;
|
|
1151
|
+
let parent = null;
|
|
1152
|
+
|
|
1153
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1154
|
+
parent = value;
|
|
1155
|
+
parentKey += (parentKey ? "." : "") + key;
|
|
1156
|
+
key = keys[i];
|
|
1157
|
+
value = parent[key];
|
|
1158
|
+
|
|
1159
|
+
if (value === undefined) {
|
|
1160
|
+
throw [err$1.INVALID_PARAM, `无此配置项: ${key}`];
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
return {
|
|
1165
|
+
parent,
|
|
1166
|
+
parentKey,
|
|
1167
|
+
key,
|
|
1168
|
+
value
|
|
1169
|
+
};
|
|
1041
1170
|
} //#endregion
|
|
1042
1171
|
//region ====中间件
|
|
1043
1172
|
|
|
@@ -1051,7 +1180,7 @@ class apiUtil$1 {
|
|
|
1051
1180
|
await apiUtil$1.checkRequestToken(req);
|
|
1052
1181
|
await next();
|
|
1053
1182
|
} catch (e) {
|
|
1054
|
-
res.send(err.ERROR(e));
|
|
1183
|
+
res.send(err$1.ERROR(e));
|
|
1055
1184
|
}
|
|
1056
1185
|
|
|
1057
1186
|
return false;
|
|
@@ -1099,7 +1228,7 @@ class apiUtil$1 {
|
|
|
1099
1228
|
|
|
1100
1229
|
return true;
|
|
1101
1230
|
} catch (e) {
|
|
1102
|
-
res.send(err.ERROR(e));
|
|
1231
|
+
res.send(err$1.ERROR(e));
|
|
1103
1232
|
return false;
|
|
1104
1233
|
}
|
|
1105
1234
|
}
|
|
@@ -1149,11 +1278,11 @@ class apiUtil$1 {
|
|
|
1149
1278
|
let errResponse = null;
|
|
1150
1279
|
|
|
1151
1280
|
if (!tokenData.clientIp) {
|
|
1152
|
-
errResponse = apiUtil$1.spoApiFail(err.GET_CLIENTIP_FAIL, req);
|
|
1281
|
+
errResponse = apiUtil$1.spoApiFail(err$1.GET_CLIENTIP_FAIL, req);
|
|
1153
1282
|
} else if (!tokenData.apiKey) {
|
|
1154
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiKey"], req);
|
|
1283
|
+
errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiKey"], req);
|
|
1155
1284
|
} else if (!tokenData.apiSecret) {
|
|
1156
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1285
|
+
errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1157
1286
|
}
|
|
1158
1287
|
|
|
1159
1288
|
if (errResponse != null) {
|
|
@@ -1189,7 +1318,7 @@ class apiUtil$1 {
|
|
|
1189
1318
|
let accessToken = apiUtil$1.extractToken(req);
|
|
1190
1319
|
|
|
1191
1320
|
if (!accessToken) {
|
|
1192
|
-
res.send(apiUtil$1.spoApiFail(err.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
|
|
1321
|
+
res.send(apiUtil$1.spoApiFail(err$1.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
|
|
1193
1322
|
|
|
1194
1323
|
return;
|
|
1195
1324
|
}
|
|
@@ -1210,7 +1339,7 @@ class apiUtil$1 {
|
|
|
1210
1339
|
req.tokenData = p;
|
|
1211
1340
|
return apiUtil$1.$checkApiKeyOld(req, res, next);
|
|
1212
1341
|
}).catch(e => {
|
|
1213
|
-
apiUtil$1.sendOrRedirect(req, res, apiUtil$1.spoApiFail(err.TOKEN_INVALID, req));
|
|
1342
|
+
apiUtil$1.sendOrRedirect(req, res, apiUtil$1.spoApiFail(err$1.TOKEN_INVALID, req));
|
|
1214
1343
|
});
|
|
1215
1344
|
}
|
|
1216
1345
|
/**
|
|
@@ -1245,24 +1374,247 @@ class apiUtil$1 {
|
|
|
1245
1374
|
});
|
|
1246
1375
|
}
|
|
1247
1376
|
} //#endregion
|
|
1377
|
+
//region ====一些通用服务功能
|
|
1378
|
+
|
|
1379
|
+
/**
|
|
1380
|
+
* 获取配置数据
|
|
1381
|
+
* @param options
|
|
1382
|
+
* @returns {Promise<boolean|*>}
|
|
1383
|
+
*/
|
|
1384
|
+
// api/config/appSetting.ossEnabled
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
static async getConfigValue(options) {
|
|
1388
|
+
configNeeded();
|
|
1389
|
+
const params = options.replacements;
|
|
1390
|
+
let item = params.item;
|
|
1391
|
+
delete params.item;
|
|
1392
|
+
if (await apiUtil$1.checkForwardsHost(options)) return true;
|
|
1393
|
+
let c = apiUtil$1.parseCfgPath(item);
|
|
1394
|
+
delete c.parent;
|
|
1395
|
+
c.host = ppUtil$2.getMyIp();
|
|
1396
|
+
return c;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* 设置配置数据
|
|
1400
|
+
* @param options
|
|
1401
|
+
* @returns {Promise<*>}
|
|
1402
|
+
*/
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
static async setConfigValue(options) {
|
|
1406
|
+
configNeeded();
|
|
1407
|
+
const params = options.replacements;
|
|
1408
|
+
let item = params.item;
|
|
1409
|
+
delete params.item; // if (await checkForwardsHost(options))
|
|
1410
|
+
// return true;
|
|
1411
|
+
|
|
1412
|
+
await apiUtil$1.parametersOK(params, "value");
|
|
1413
|
+
let c = apiUtil$1.parseCfgPath(item);
|
|
1414
|
+
|
|
1415
|
+
if (typeof c.value === "object") {
|
|
1416
|
+
throw [err$1.ACCESS_REFUSED, `暂不支持修改复杂配置`];
|
|
1417
|
+
} // c.oldValue = c.value;
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
c.newValue = params.value;
|
|
1421
|
+
c.parent[c.key] = c.newValue;
|
|
1422
|
+
delete c.parent;
|
|
1423
|
+
c.host = ppUtil$2.getMyIp();
|
|
1424
|
+
return c; // 应用层自行处理多机同步
|
|
1425
|
+
} //#endregion
|
|
1248
1426
|
|
|
1249
1427
|
|
|
1250
1428
|
}
|
|
1251
1429
|
|
|
1252
1430
|
function configNeeded() {
|
|
1253
|
-
if (!conf || !err) {
|
|
1431
|
+
if (!conf$1 || !err$1) {
|
|
1432
|
+
ppUtil$2.configNeeded();
|
|
1433
|
+
conf$1 = ppUtil$2.appConfig;
|
|
1434
|
+
appSetting = conf$1.appSetting;
|
|
1435
|
+
err$1 = ppUtil$2.appErrCfg;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
var ppUtilApi = apiUtil$1;
|
|
1440
|
+
|
|
1441
|
+
function commonjsRequire(path) {
|
|
1442
|
+
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
const fs = require$$0__default$1["default"];
|
|
1446
|
+
const path = require$$1__default$1["default"];
|
|
1447
|
+
const ppUtil$1 = require$$1__default["default"].ppUtil;
|
|
1448
|
+
const redisUtil = require$$2__default["default"].redisUtil;
|
|
1449
|
+
let conf, err; // const dbCheck = require('../dbupdate/dd-version');
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* API服务启动时前置条件检查
|
|
1453
|
+
* ok = await preconditions
|
|
1454
|
+
* .setAppName(conf.thisApp)
|
|
1455
|
+
* .addCheckPromise(preconditions.checkExEnvSetting())
|
|
1456
|
+
* .addCheckPromise(preconditions.checkRedis())
|
|
1457
|
+
* .addCheckPromise(checkDatabase())
|
|
1458
|
+
* .addChecker(myChecker, args)
|
|
1459
|
+
* .checkAll()
|
|
1460
|
+
*/
|
|
1461
|
+
|
|
1462
|
+
class preconditions$1 {
|
|
1463
|
+
static appName;
|
|
1464
|
+
static checkFunctions = [];
|
|
1465
|
+
static checkPromises = [];
|
|
1466
|
+
|
|
1467
|
+
static setAppName(aName) {
|
|
1254
1468
|
ppUtil$1.configNeeded();
|
|
1255
1469
|
conf = ppUtil$1.appConfig;
|
|
1256
|
-
appSetting = conf.appSetting;
|
|
1257
1470
|
err = ppUtil$1.appErrCfg;
|
|
1471
|
+
preconditions$1.appName = aName || conf.thisApp;
|
|
1472
|
+
return preconditions$1;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
static addCheckPromise(p) {
|
|
1476
|
+
preconditions$1.checkPromises.push(p);
|
|
1477
|
+
return preconditions$1;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
static addChecker(checkFunc, args) {
|
|
1481
|
+
preconditions$1.checkFunctions.push({
|
|
1482
|
+
check: checkFunc,
|
|
1483
|
+
args: args
|
|
1484
|
+
});
|
|
1485
|
+
return preconditions$1;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
static async checkAll() {
|
|
1489
|
+
for (let i = 0; i < preconditions$1.checkFunctions.length; i++) {
|
|
1490
|
+
const f = preconditions$1.checkFunctions[i];
|
|
1491
|
+
preconditions$1.addCheckPromise(f.check(f.args));
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
for (let i = 0; i < preconditions$1.checkPromises.length; i++) {
|
|
1495
|
+
let msg = await preconditions$1.checkPromises[i];
|
|
1496
|
+
|
|
1497
|
+
if (msg) {
|
|
1498
|
+
if (!preconditions$1.messages) {
|
|
1499
|
+
preconditions$1.messages = [];
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
preconditions$1.messages.push(`${preconditions$1.messages.length + 1}. ${msg}`);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
let text = "";
|
|
1507
|
+
|
|
1508
|
+
if (preconditions$1.messages) {
|
|
1509
|
+
text = `*** 由于以下原因,${preconditions$1.appName} 尚不能正常提供服务:\n\n` + preconditions$1.messages.join("\n\n") + "\n\n*** 请检查以上各项条件,修复后重新启动服务";
|
|
1510
|
+
console.log("\n" + text); // for (let i = 0; i < preconditions.messages.length; i++) {
|
|
1511
|
+
// console.log(preconditions.messages[i]);
|
|
1512
|
+
// }
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
if (!(await fs.async_exists("../log"))) {
|
|
1516
|
+
await fs.async_mkdir("../log");
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
await fs.async_writeFile(`../log/preconditions`, text);
|
|
1520
|
+
return !text;
|
|
1521
|
+
} // 检查器
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* 检查本机外部配置文件版本
|
|
1525
|
+
*/
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
static async checkExEnvSetting() {
|
|
1529
|
+
return await checkExEnvSetting();
|
|
1258
1530
|
}
|
|
1531
|
+
/**
|
|
1532
|
+
* redis 可用性检查
|
|
1533
|
+
*/
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
static async checkRedis() {
|
|
1537
|
+
return await checkRedis();
|
|
1538
|
+
} // /**
|
|
1539
|
+
// * 数据库可用性及业务数据版本版本检查
|
|
1540
|
+
// */
|
|
1541
|
+
// static async checkDatabase() {
|
|
1542
|
+
// return await checkDatabase();
|
|
1543
|
+
// }
|
|
1544
|
+
|
|
1545
|
+
|
|
1259
1546
|
}
|
|
1260
1547
|
|
|
1261
|
-
|
|
1548
|
+
async function createEnvSettingFile(fileName) {
|
|
1549
|
+
try {
|
|
1550
|
+
const cfgText = await ppUtil$1.doCreateEnvSettingFile(fileName);
|
|
1551
|
+
|
|
1552
|
+
if (cfgText.indexOf(`cfgVersion: "${conf._envSetting.cfgVersion}"`) > 0) {
|
|
1553
|
+
console.log(`\n*** 已創建新的本機環境配置文件\n${fileName}\n请檢查各項內容是否正确(此项更新服务可正常运行)\n\n`);
|
|
1554
|
+
return "";
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
return `已創建新的本機環境配置文件\n${fileName}\n请檢查並正確設置各項內容,然後將配置版本號修改為${conf._envSettings.default.cfgVersion}`;
|
|
1558
|
+
} catch (e) {
|
|
1559
|
+
return `創建本機環境配置文件失敗\n《${fileName}》\n${err.ERROR(e).message}`;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
async function checkExEnvSetting() {
|
|
1564
|
+
if (!conf._envSetting.localSettingImported) {
|
|
1565
|
+
let fileName = conf.getEnvSettingFileName();
|
|
1566
|
+
|
|
1567
|
+
if (!fs.existsSync(fileName)) {
|
|
1568
|
+
return await createEnvSettingFile(fileName);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
let envSettingEx = commonjsRequire(fileName);
|
|
1572
|
+
|
|
1573
|
+
if (envSettingEx.cfgVersion !== conf._envSettings.default.cfgVersion) {
|
|
1574
|
+
if (envSettingEx.cfgVersion !== "0.0") {
|
|
1575
|
+
let fp = path.parse(fileName);
|
|
1576
|
+
let newFileName = path.join(fp.dir, fp.name + envSettingEx.cfgVersion + fp.ext);
|
|
1577
|
+
|
|
1578
|
+
if (!fs.existsSync(newFileName)) {
|
|
1579
|
+
fs.renameSync(fileName, newFileName);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
return await createEnvSettingFile(fileName);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
} // async function checkDatabase() {
|
|
1587
|
+
// return dbCheck.check().then(info => info.updateMessage);
|
|
1588
|
+
// }
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
async function checkRedis() {
|
|
1592
|
+
if (!conf.redis.enabled) return "";
|
|
1593
|
+
const redis = redisUtil.newClient("io"); // console.log(`checkRedis begin:`);
|
|
1594
|
+
|
|
1595
|
+
await ppUtil$1.wait(15 * 1000, param => {
|
|
1596
|
+
if (redis.ready && redis.connected || redis.error) {
|
|
1597
|
+
return true;
|
|
1598
|
+
}
|
|
1599
|
+
}).catch(e => {
|
|
1600
|
+
redis.error = e;
|
|
1601
|
+
});
|
|
1602
|
+
|
|
1603
|
+
if (redis.error) {
|
|
1604
|
+
console.log(`未能成功連接 redis: ${redis.error},請檢查相關設置`);
|
|
1605
|
+
return `未能成功連接 redis: ${redis.error},請檢查相關設置`;
|
|
1606
|
+
} // console.log(`checkRedis done:`);
|
|
1607
|
+
// console.log(redis);
|
|
1608
|
+
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
var ppPrecond = preconditions$1;
|
|
1262
1612
|
|
|
1263
1613
|
const apiUtil = ppUtilApi;
|
|
1614
|
+
const preconditions = ppPrecond;
|
|
1264
1615
|
var ppUtil = {
|
|
1265
|
-
apiUtil
|
|
1616
|
+
apiUtil,
|
|
1617
|
+
preconditions
|
|
1266
1618
|
};
|
|
1267
1619
|
|
|
1268
1620
|
module.exports = ppUtil;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abler-api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "API服务相关工具",
|
|
5
5
|
"main": "./dist/cjs/pp-util.js",
|
|
6
6
|
"-module": "./dist/es/pp-util.js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"q": "^1.5.1",
|
|
18
18
|
"abler-util": ">=0.1.1",
|
|
19
|
-
"abler-db": ">=0.1.1"
|
|
19
|
+
"abler-db": ">=0.1.1",
|
|
20
|
+
"abler-net": ">=0.1.1"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@babel/core": "^7.18.5",
|