abler-api 0.1.15 → 0.1.18
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 -65
- 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
|
/**
|
|
@@ -532,7 +519,6 @@ class apiUtil$1 {
|
|
|
532
519
|
req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
|
|
533
520
|
const tokenKey = apiUtil$1.userTokenStoreKey(req.accessToken);
|
|
534
521
|
const expireTime = apiUtil$1.tokenExpireTime(req);
|
|
535
|
-
await apiUtil$1.restoreTokenData(tokenKey, expireTime);
|
|
536
522
|
return await apiUtil$1.restoreTokenData(tokenKey, expireTime).then(async function (data) {
|
|
537
523
|
req.userInfo = apiUtil$1.setUserIdNo(data, data._idNo);
|
|
538
524
|
if (req.tokenValidater) await req.tokenValidater(req.userInfo, req);
|
|
@@ -555,7 +541,7 @@ class apiUtil$1 {
|
|
|
555
541
|
|
|
556
542
|
if (dbgToken) {
|
|
557
543
|
let envId = process.env.ECS_DEPLOY_ID;
|
|
558
|
-
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");
|
|
559
545
|
} else {
|
|
560
546
|
req.__debug__ = false;
|
|
561
547
|
} // console.log("__debug__:", req.__debug__, "dbgToken:", dbgToken);
|
|
@@ -735,7 +721,7 @@ class apiUtil$1 {
|
|
|
735
721
|
};
|
|
736
722
|
|
|
737
723
|
if (rec.secret !== "") {
|
|
738
|
-
rec.secret = ppUtil$
|
|
724
|
+
rec.secret = ppUtil$2.getEncAse192(rec.secret);
|
|
739
725
|
}
|
|
740
726
|
|
|
741
727
|
req.apiCallRec = rec;
|
|
@@ -802,7 +788,7 @@ class apiUtil$1 {
|
|
|
802
788
|
return certInfo;
|
|
803
789
|
}).catch(e => {
|
|
804
790
|
console.log('获取企业证书失败:\n', e);
|
|
805
|
-
throw [err.ACCESS_REFUSED, `获取企业证书失败:${err.ERROR(e).message}`];
|
|
791
|
+
throw [err$1.ACCESS_REFUSED, `获取企业证书失败:${err$1.ERROR(e).message}`];
|
|
806
792
|
});
|
|
807
793
|
}
|
|
808
794
|
/**
|
|
@@ -816,7 +802,7 @@ class apiUtil$1 {
|
|
|
816
802
|
static async verifyApiSignature(tokenData, req) {
|
|
817
803
|
try {
|
|
818
804
|
if (!req.headers.timestamp) {
|
|
819
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
805
|
+
throw [err$1.ACCESS_REFUSED, `必须在请求头中设置时戳`];
|
|
820
806
|
}
|
|
821
807
|
|
|
822
808
|
let timestamp = parseInt(req.headers.timestamp);
|
|
@@ -824,13 +810,13 @@ class apiUtil$1 {
|
|
|
824
810
|
let maxTimeDiff = apiUtil$1.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$1.isTestMode(req) ? 4 * 3600 : 100; // 100
|
|
825
811
|
|
|
826
812
|
if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
|
|
827
|
-
throw [err.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
813
|
+
throw [err$1.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
|
|
828
814
|
}
|
|
829
815
|
|
|
830
816
|
let signature = req.headers.signature;
|
|
831
817
|
|
|
832
818
|
if (!signature) {
|
|
833
|
-
throw [err.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
819
|
+
throw [err$1.ACCESS_REFUSED, `必须在请求头中提供签名`];
|
|
834
820
|
}
|
|
835
821
|
|
|
836
822
|
let signData = apiUtil$1.extractToken(req, null, true) || tokenData.apiKey;
|
|
@@ -885,7 +871,7 @@ class apiUtil$1 {
|
|
|
885
871
|
|
|
886
872
|
if (!tokenData.certPublicKeySpare) {
|
|
887
873
|
throw {
|
|
888
|
-
eo: err.ACCESS_REFUSED,
|
|
874
|
+
eo: err$1.ACCESS_REFUSED,
|
|
889
875
|
msgArgv: "签名验证异常",
|
|
890
876
|
data: e
|
|
891
877
|
};
|
|
@@ -934,7 +920,7 @@ class apiUtil$1 {
|
|
|
934
920
|
} catch (e) {
|
|
935
921
|
console.log("SPO服务签名验证异常(备用证书), ", e);
|
|
936
922
|
throw {
|
|
937
|
-
eo: err.ACCESS_REFUSED,
|
|
923
|
+
eo: err$1.ACCESS_REFUSED,
|
|
938
924
|
msgArgv: "签名验证异常(spare)",
|
|
939
925
|
data: e
|
|
940
926
|
};
|
|
@@ -943,7 +929,7 @@ class apiUtil$1 {
|
|
|
943
929
|
|
|
944
930
|
if (!verifyOK) {
|
|
945
931
|
console.log("SPO服务签名验证失败, tokenData: ", tokenData);
|
|
946
|
-
throw [err.ACCESS_REFUSED, "签名验证未通过"];
|
|
932
|
+
throw [err$1.ACCESS_REFUSED, "签名验证未通过"];
|
|
947
933
|
}
|
|
948
934
|
|
|
949
935
|
return verifyOK;
|
|
@@ -961,7 +947,7 @@ class apiUtil$1 {
|
|
|
961
947
|
if (!tokenData.companyInfo) {
|
|
962
948
|
tokenData.companyInfo = await apiUtil$1.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
|
|
963
949
|
console.log("执行企业信息查询发生异常", e);
|
|
964
|
-
throw [err.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
950
|
+
throw [err$1.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
|
|
965
951
|
});
|
|
966
952
|
}
|
|
967
953
|
|
|
@@ -970,7 +956,7 @@ class apiUtil$1 {
|
|
|
970
956
|
if (companyInfo != null) {
|
|
971
957
|
let secret = apiUtil$1._getApiSecret(tokenData.apiKey);
|
|
972
958
|
|
|
973
|
-
if (secret !== tokenData.apiSecret) throw err.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
959
|
+
if (secret !== tokenData.apiSecret) throw err$1.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
|
|
974
960
|
// console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
|
|
975
961
|
// let whiteList = companyInfo.ipWhiteList || "";
|
|
976
962
|
// // 没有设置ip白名单的就不检查了
|
|
@@ -984,7 +970,7 @@ class apiUtil$1 {
|
|
|
984
970
|
});
|
|
985
971
|
}
|
|
986
972
|
|
|
987
|
-
throw [err.API_KEY_INVALID, tokenData.apiKey];
|
|
973
|
+
throw [err$1.API_KEY_INVALID, tokenData.apiKey];
|
|
988
974
|
}
|
|
989
975
|
/**
|
|
990
976
|
* 检查令牌数据是否存在
|
|
@@ -1035,10 +1021,152 @@ class apiUtil$1 {
|
|
|
1035
1021
|
paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
|
|
1036
1022
|
}
|
|
1037
1023
|
|
|
1038
|
-
if (!paramExists) return ppUtil$
|
|
1024
|
+
if (!paramExists) return ppUtil$2.errorPormise(err$1.ERROR(err$1.PARAMETER_NEEDED, paramName));
|
|
1039
1025
|
}
|
|
1040
1026
|
|
|
1041
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
|
+
};
|
|
1042
1170
|
} //#endregion
|
|
1043
1171
|
//region ====中间件
|
|
1044
1172
|
|
|
@@ -1052,7 +1180,7 @@ class apiUtil$1 {
|
|
|
1052
1180
|
await apiUtil$1.checkRequestToken(req);
|
|
1053
1181
|
await next();
|
|
1054
1182
|
} catch (e) {
|
|
1055
|
-
res.send(err.ERROR(e));
|
|
1183
|
+
res.send(err$1.ERROR(e));
|
|
1056
1184
|
}
|
|
1057
1185
|
|
|
1058
1186
|
return false;
|
|
@@ -1100,7 +1228,7 @@ class apiUtil$1 {
|
|
|
1100
1228
|
|
|
1101
1229
|
return true;
|
|
1102
1230
|
} catch (e) {
|
|
1103
|
-
res.send(err.ERROR(e));
|
|
1231
|
+
res.send(err$1.ERROR(e));
|
|
1104
1232
|
return false;
|
|
1105
1233
|
}
|
|
1106
1234
|
}
|
|
@@ -1150,11 +1278,11 @@ class apiUtil$1 {
|
|
|
1150
1278
|
let errResponse = null;
|
|
1151
1279
|
|
|
1152
1280
|
if (!tokenData.clientIp) {
|
|
1153
|
-
errResponse = apiUtil$1.spoApiFail(err.GET_CLIENTIP_FAIL, req);
|
|
1281
|
+
errResponse = apiUtil$1.spoApiFail(err$1.GET_CLIENTIP_FAIL, req);
|
|
1154
1282
|
} else if (!tokenData.apiKey) {
|
|
1155
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiKey"], req);
|
|
1283
|
+
errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiKey"], req);
|
|
1156
1284
|
} else if (!tokenData.apiSecret) {
|
|
1157
|
-
errResponse = apiUtil$1.spoApiFail([err.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1285
|
+
errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiSecret"], req);
|
|
1158
1286
|
}
|
|
1159
1287
|
|
|
1160
1288
|
if (errResponse != null) {
|
|
@@ -1190,7 +1318,7 @@ class apiUtil$1 {
|
|
|
1190
1318
|
let accessToken = apiUtil$1.extractToken(req);
|
|
1191
1319
|
|
|
1192
1320
|
if (!accessToken) {
|
|
1193
|
-
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));
|
|
1194
1322
|
|
|
1195
1323
|
return;
|
|
1196
1324
|
}
|
|
@@ -1211,7 +1339,7 @@ class apiUtil$1 {
|
|
|
1211
1339
|
req.tokenData = p;
|
|
1212
1340
|
return apiUtil$1.$checkApiKeyOld(req, res, next);
|
|
1213
1341
|
}).catch(e => {
|
|
1214
|
-
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));
|
|
1215
1343
|
});
|
|
1216
1344
|
}
|
|
1217
1345
|
/**
|
|
@@ -1246,24 +1374,247 @@ class apiUtil$1 {
|
|
|
1246
1374
|
});
|
|
1247
1375
|
}
|
|
1248
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
|
|
1249
1426
|
|
|
1250
1427
|
|
|
1251
1428
|
}
|
|
1252
1429
|
|
|
1253
1430
|
function configNeeded() {
|
|
1254
|
-
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) {
|
|
1255
1468
|
ppUtil$1.configNeeded();
|
|
1256
1469
|
conf = ppUtil$1.appConfig;
|
|
1257
|
-
appSetting = conf.appSetting;
|
|
1258
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();
|
|
1259
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
|
+
|
|
1260
1546
|
}
|
|
1261
1547
|
|
|
1262
|
-
|
|
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;
|
|
1263
1612
|
|
|
1264
1613
|
const apiUtil = ppUtilApi;
|
|
1614
|
+
const preconditions = ppPrecond;
|
|
1265
1615
|
var ppUtil = {
|
|
1266
|
-
apiUtil
|
|
1616
|
+
apiUtil,
|
|
1617
|
+
preconditions
|
|
1267
1618
|
};
|
|
1268
1619
|
|
|
1269
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.18",
|
|
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",
|