ksyun-sdk-node 1.0.5 → 1.4.8
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/.claude/settings.local.json +12 -0
- package/dist/base/BaseClient.js +133 -52
- package/dist/index.js +9 -12
- package/dist/lib/fetch.js +4 -5
- package/dist/lib/sign.js +31 -33
- package/dist/lib/signautreV4.js +167 -0
- package/dist/service/Actiontrail/v20190401/index.js +34 -37
- package/dist/service/Aicp/v20240612/index.js +511 -0
- package/dist/service/Bill/v20180601/index.js +49 -88
- package/dist/service/Bill/v20220601/index.js +64 -0
- package/dist/service/Bill_union/v20200101/index.js +151 -77
- package/dist/service/Bill_union/v20221222/index.js +142 -0
- package/dist/service/Bill_union/v20250801/index.js +66 -0
- package/dist/service/Bws/v20160304/index.js +111 -94
- package/dist/service/Cdn/v20160901/index.js +89 -0
- package/dist/service/Cdn/v20200630/index.js +410 -0
- package/dist/service/Cdn/v20200901/index.js +162 -0
- package/dist/service/Cdn/v20211201/index.js +45 -0
- package/dist/service/Cdn/v20250503/index.js +71 -0
- package/dist/service/Cen/v20160304/index.js +460 -0
- package/dist/service/Clickhouse/v20210101/index.js +546 -0
- package/dist/service/Ebs/v20160304/index.js +265 -268
- package/dist/service/Eip/v20160304/index.js +104 -107
- package/dist/service/Epc/v20151101/index.js +1735 -784
- package/dist/service/Iam/v20151101/index.js +872 -711
- package/dist/service/Iam/v20240513/index.js +47 -0
- package/dist/service/Iam/v20240703/index.js +44 -0
- package/dist/service/Kad/v20161122/index.js +84 -87
- package/dist/service/Kce/v20180314/index.js +320 -0
- package/dist/service/Kce/v20190806/index.js +482 -0
- package/dist/service/Kce/v20201231/index.js +63 -0
- package/dist/service/Kcf/v20211215/index.js +203 -0
- package/dist/service/Kcm/v20160304/index.js +120 -0
- package/dist/service/Kcrs/v20211109/index.js +851 -0
- package/dist/service/Kcs/v20160701/index.js +1106 -0
- package/dist/service/Kcs/v20170401/index.js +81 -0
- package/dist/service/Kead/v20200101/index.js +28 -31
- package/dist/service/Kec/v20160304/index.js +1695 -1466
- package/dist/service/Kes/v20201215/index.js +171 -0
- package/dist/service/Ket/v20170101/index.js +141 -0
- package/dist/service/Kkms/v20160304/index.js +167 -0
- package/dist/service/Klog/v20200731/index.js +331 -0
- package/dist/service/Kls/v20170101/index.js +194 -0
- package/dist/service/Kmr/v20210902/index.js +422 -0
- package/dist/service/Kmr/v20231231/index.js +154 -0
- package/dist/service/Kmr/v20240814/index.js +370 -0
- package/dist/service/Krds/v20160701/index.js +1302 -0
- package/dist/service/Krds/v20200825/index.js +174 -0
- package/dist/service/Memcached/v20180627/index.js +249 -0
- package/dist/service/Mongodb/v20170101/index.js +516 -501
- package/dist/service/Monitor/v20100525/index.js +70 -0
- package/dist/service/Monitor/v20181114/index.js +49 -0
- package/dist/service/Monitor/v20210101/index.js +216 -0
- package/dist/service/Monitor/v20220101/index.js +58 -0
- package/dist/service/Monitor/v20250101/index.js +71 -0
- package/dist/service/Rabbitmq/v20191017/index.js +242 -0
- package/dist/service/Resourcemanager/v20210320/index.js +113 -116
- package/dist/service/Sks/v20151101/index.js +72 -75
- package/dist/service/Slb/v20160304/index.js +1299 -790
- package/dist/service/Sts/v20151101/index.js +26 -29
- package/dist/service/Tagv2/v20200901/index.js +174 -0
- package/dist/service/Tidb/v20210520/index.js +363 -0
- package/dist/service/Trade/v20200114/index.js +23 -26
- package/dist/service/Trade/v20200831/index.js +25 -28
- package/dist/service/Vpc/v20160304/index.js +2015 -1045
- package/dist/service/Waf/v20200707/index.js +248 -0
- package/example/iam.js +2 -1
- package/example/res.js +2 -1
- package/package.json +1 -1
- package/src/base/BaseClient.js +131 -35
- package/src/lib/signautreV4.js +166 -0
- package/src/service/Actiontrail/v20190401/index.js +42 -42
- package/src/service/Aicp/v20240612/index.js +503 -0
- package/src/service/Bill/v20180601/index.js +61 -102
- package/src/service/Bill/v20220601/index.js +56 -0
- package/src/service/Bill_union/v20200101/index.js +181 -109
- package/src/service/Bill_union/v20221222/index.js +134 -0
- package/src/service/Bill_union/v20250801/index.js +58 -0
- package/src/service/Bws/v20160304/index.js +139 -119
- package/src/service/Cdn/v20160901/index.js +81 -0
- package/src/service/Cdn/v20200630/index.js +402 -0
- package/src/service/Cdn/v20200901/index.js +154 -0
- package/src/service/Cdn/v20211201/index.js +37 -0
- package/src/service/Cdn/v20250503/index.js +63 -0
- package/src/service/Cen/v20160304/index.js +452 -0
- package/src/service/Clickhouse/v20210101/index.js +538 -0
- package/src/service/Ebs/v20160304/index.js +365 -368
- package/src/service/Eip/v20160304/index.js +135 -136
- package/src/service/Epc/v20151101/index.js +1984 -1033
- package/src/service/Iam/v20151101/index.js +1155 -993
- package/src/service/Iam/v20240513/index.js +39 -0
- package/src/service/Iam/v20240703/index.js +36 -0
- package/src/service/Kad/v20161122/index.js +112 -112
- package/src/service/Kce/v20180314/index.js +312 -0
- package/src/service/Kce/v20190806/index.js +474 -0
- package/src/service/Kce/v20201231/index.js +55 -0
- package/src/service/Kcf/v20211215/index.js +195 -0
- package/src/service/Kcm/v20160304/index.js +112 -0
- package/src/service/Kcrs/v20211109/index.js +843 -0
- package/src/service/Kcs/v20160701/index.js +1098 -0
- package/src/service/Kcs/v20170401/index.js +73 -0
- package/src/service/Kead/v20200101/index.js +36 -36
- package/src/service/Kec/v20160304/index.js +2061 -1838
- package/src/service/Kes/v20201215/index.js +163 -0
- package/src/service/Ket/v20170101/index.js +133 -0
- package/src/service/Kkms/v20160304/index.js +159 -0
- package/src/service/Klog/v20200731/index.js +323 -0
- package/src/service/Kls/v20170101/index.js +186 -0
- package/src/service/Kmr/v20210902/index.js +414 -0
- package/src/service/Kmr/v20231231/index.js +146 -0
- package/src/service/Kmr/v20240814/index.js +362 -0
- package/src/service/Krds/v20160701/index.js +1294 -0
- package/src/service/Krds/v20200825/index.js +166 -0
- package/src/service/Memcached/v20180627/index.js +241 -0
- package/src/service/Mongodb/v20170101/index.js +672 -654
- package/src/service/Monitor/v20100525/index.js +62 -0
- package/src/service/Monitor/v20181114/index.js +41 -0
- package/src/service/Monitor/v20210101/index.js +208 -0
- package/src/service/Monitor/v20220101/index.js +50 -0
- package/src/service/Monitor/v20250101/index.js +63 -0
- package/src/service/Rabbitmq/v20191017/index.js +234 -0
- package/src/service/Resourcemanager/v20210320/index.js +157 -158
- package/src/service/Sks/v20151101/index.js +95 -96
- package/src/service/Slb/v20160304/index.js +1471 -959
- package/src/service/Sts/v20151101/index.js +34 -34
- package/src/service/Tagv2/v20200901/index.js +166 -0
- package/src/service/Tidb/v20210520/index.js +355 -0
- package/src/service/Trade/v20200114/index.js +31 -31
- package/src/service/Trade/v20200831/index.js +33 -33
- package/src/service/Vpc/v20160304/index.js +2404 -1432
- package/src/service/Waf/v20200707/index.js +240 -0
- package/src/service/Bill_union/v20211209/index.js +0 -35
- package/src/service/Slb/v20171210/index.js +0 -39
package/dist/base/BaseClient.js
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
require("core-js/modules/es.json.stringify.js");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
5
|
+
require("core-js/modules/esnext.iterator.for-each.js");
|
|
6
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
7
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
8
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
9
|
+
const {
|
|
10
|
+
getSignatureHeaders,
|
|
11
|
+
getCanonicalizedQuery
|
|
12
|
+
} = require('../lib/signautreV4.js');
|
|
9
13
|
const fetch = require('../lib/fetch.js');
|
|
10
|
-
|
|
11
14
|
const dayjs = require('dayjs');
|
|
12
|
-
|
|
13
15
|
const utc = require('dayjs/plugin/utc.js');
|
|
14
|
-
|
|
15
16
|
const qs = require('qs');
|
|
16
|
-
|
|
17
17
|
dayjs.extend(utc);
|
|
18
18
|
module.exports = class BaseClient {
|
|
19
19
|
constructor(clientConfig) {
|
|
20
20
|
_defineProperty(this, "_baseConfig", {});
|
|
21
|
-
|
|
22
21
|
_defineProperty(this, "_apiList", {});
|
|
23
|
-
|
|
24
22
|
this.ak = clientConfig.credential.secretId, this.sk = clientConfig.credential.secretKey;
|
|
25
23
|
this.region = clientConfig.region;
|
|
26
24
|
this.httpProfile = clientConfig.httpProfile || {};
|
|
27
|
-
|
|
28
25
|
if (!this.ak || !this.sk) {
|
|
29
26
|
throw new Error('secretId and secretKey are required');
|
|
30
27
|
}
|
|
@@ -34,71 +31,155 @@ module.exports = class BaseClient {
|
|
|
34
31
|
* @param {string} apiAction 接口名
|
|
35
32
|
* @param {object} data 参数 { body, query }
|
|
36
33
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
34
|
request(apiAction, params = {}) {
|
|
35
|
+
params = this.formatParams(apiAction, params);
|
|
40
36
|
let apiConfig = this._apiList[apiAction];
|
|
41
|
-
let publicParams = {
|
|
42
|
-
Accesskey: this.ak,
|
|
43
|
-
Service: this._baseConfig.config.credentials.service,
|
|
44
|
-
Action: apiAction,
|
|
45
|
-
Version: apiConfig.config.query.Version,
|
|
46
|
-
Timestamp: dayjs().utc().format('YYYY-MM-DDThh:mm:ss') + 'Z',
|
|
47
|
-
SignatureVersion: '1.0',
|
|
48
|
-
SignatureMethod: 'HMAC-SHA256',
|
|
49
|
-
Region: this.region || this._baseConfig.config.credentials.region
|
|
50
|
-
};
|
|
51
|
-
let combainParams = { ...publicParams,
|
|
52
|
-
...params
|
|
53
|
-
};
|
|
54
|
-
let signedParams = getSignedParams(combainParams, this.sk);
|
|
55
37
|
let protocol = this.httpProfile.protocol || this._baseConfig.protocol;
|
|
56
38
|
let endpoint = this.httpProfile.endpoint || this._baseConfig.endpoint;
|
|
57
|
-
let method = this.httpProfile.method || apiConfig.method;
|
|
58
|
-
let
|
|
39
|
+
let method = (this.httpProfile.method || apiConfig.method).toUpperCase();
|
|
40
|
+
let region = this.region || this._baseConfig.config.credentials.region;
|
|
41
|
+
let headers = {
|
|
42
|
+
...(this._baseConfig.config.headers || {}),
|
|
43
|
+
...(apiConfig.config.headers || {})
|
|
44
|
+
};
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
46
|
+
// 处理自定义path
|
|
47
|
+
let customPath = this.httpProfile.path || '';
|
|
48
|
+
// 清理path中的?参数
|
|
49
|
+
if (customPath && customPath.includes('?')) {
|
|
50
|
+
customPath = customPath.split('?')[0];
|
|
62
51
|
}
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
// 处理path拼接,避免双斜杠
|
|
54
|
+
let finalPath = apiConfig.url;
|
|
55
|
+
if (customPath) {
|
|
56
|
+
// 清理endpoint末尾的斜杠
|
|
57
|
+
endpoint = endpoint.replace(/\/+$/, '');
|
|
58
|
+
// 确保customPath以/开头
|
|
59
|
+
if (!customPath.startsWith('/')) {
|
|
60
|
+
customPath = '/' + customPath;
|
|
61
|
+
}
|
|
62
|
+
finalPath = customPath;
|
|
63
|
+
}
|
|
64
|
+
let query = apiConfig.config.query;
|
|
65
|
+
if (['GET', 'OPTION', 'HEAD'].includes(method)) {
|
|
66
|
+
query = {
|
|
67
|
+
...query,
|
|
68
|
+
...params
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
let body = this.getBody(method, headers['Content-Type'], params);
|
|
72
|
+
let signParams = {
|
|
73
|
+
path: finalPath,
|
|
74
|
+
query,
|
|
75
|
+
body: body || '',
|
|
76
|
+
headers,
|
|
77
|
+
host: endpoint,
|
|
78
|
+
method,
|
|
79
|
+
region,
|
|
80
|
+
service: this._baseConfig.config.credentials.service,
|
|
81
|
+
access_key: this.ak,
|
|
82
|
+
secret_key: this.sk
|
|
68
83
|
};
|
|
69
|
-
let
|
|
84
|
+
let signHeaders = getSignatureHeaders(signParams);
|
|
85
|
+
let url = `${protocol}${endpoint}${finalPath}?${getCanonicalizedQuery(query)}`;
|
|
70
86
|
let timeoutSecond = this.httpProfile.timeout || this._baseConfig.config.timeout;
|
|
87
|
+
|
|
88
|
+
// 打印 curl 命令
|
|
89
|
+
this.printCurl(url, method, signHeaders, body);
|
|
71
90
|
return fetch(url, {
|
|
72
91
|
method: method,
|
|
73
92
|
timeout: timeoutSecond * 1000,
|
|
74
|
-
headers,
|
|
93
|
+
headers: signHeaders,
|
|
75
94
|
body
|
|
76
95
|
});
|
|
77
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* 格式化参数,对Filter类型做扁平处理
|
|
99
|
+
* @param {string} apiAction 接口名
|
|
100
|
+
* @param {object} params 参数值
|
|
101
|
+
* @returns 格式化后的参数
|
|
102
|
+
*/
|
|
103
|
+
formatParams(apiAction, params) {
|
|
104
|
+
let paramsType = this._apiList[apiAction].paramsType;
|
|
105
|
+
if (!paramsType || params == null) {
|
|
106
|
+
return params;
|
|
107
|
+
}
|
|
108
|
+
let res = {};
|
|
109
|
+
Object.keys(params).forEach(key => {
|
|
110
|
+
let type = paramsType[key];
|
|
111
|
+
// 这些类型不用处理,如果为null、undefined则排除掉
|
|
112
|
+
if (['String', 'Int', 'Double', 'Long', 'Boolean', 'Array'].includes(type) && params[key] != null) {
|
|
113
|
+
res[key] = params[key];
|
|
114
|
+
}
|
|
115
|
+
if (type == 'Filter' || type == 'Object') {
|
|
116
|
+
res = {
|
|
117
|
+
...res,
|
|
118
|
+
...this.formatFilter(key, params[key])
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return res;
|
|
123
|
+
}
|
|
124
|
+
formatFilter(pKey, value) {
|
|
125
|
+
let res = {};
|
|
126
|
+
Object.keys(value).forEach(key => {
|
|
127
|
+
let prefixName = `${pKey}.${key}`;
|
|
128
|
+
let childValue = value[key];
|
|
129
|
+
if (typeof childValue == 'object') {
|
|
130
|
+
res = {
|
|
131
|
+
...res,
|
|
132
|
+
...this.formatFilter(prefixName, childValue)
|
|
133
|
+
};
|
|
134
|
+
} else {
|
|
135
|
+
res[prefixName] = childValue;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return res;
|
|
139
|
+
}
|
|
140
|
+
|
|
78
141
|
/**
|
|
79
142
|
* 获取body
|
|
80
143
|
* @param {string} method 请求类型
|
|
81
144
|
* @param {string} contentType
|
|
82
|
-
* @param {object}
|
|
145
|
+
* @param {object} params 参数对象
|
|
83
146
|
* @returns {string}
|
|
84
147
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
} // 目前只有下面这两种
|
|
91
|
-
|
|
92
|
-
|
|
148
|
+
getBody(method, contentType, params) {
|
|
149
|
+
if (!['POST', 'PUT'].includes(method) || JSON.stringify(params) == '{}') {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
// 目前只有下面这两种
|
|
93
153
|
if (contentType == 'application/x-www-form-urlencoded') {
|
|
94
|
-
return qs.stringify(
|
|
154
|
+
return qs.stringify(params, {
|
|
155
|
+
allowDots: true,
|
|
156
|
+
// 对象转成a.b.c
|
|
157
|
+
arrayFormat: 'indices' // 数组转成a[0]=b&a[1]=c
|
|
158
|
+
});
|
|
95
159
|
}
|
|
96
|
-
|
|
97
160
|
if (contentType == 'application/json') {
|
|
98
|
-
return JSON.stringify(
|
|
161
|
+
return JSON.stringify(params);
|
|
99
162
|
}
|
|
100
|
-
|
|
101
|
-
return JSON.stringify(signedParams);
|
|
163
|
+
return JSON.stringify(params);
|
|
102
164
|
}
|
|
103
165
|
|
|
166
|
+
/**
|
|
167
|
+
* 打印 curl 命令
|
|
168
|
+
*/
|
|
169
|
+
printCurl(url, method, headers, body) {
|
|
170
|
+
let curlCmd = `curl -X ${method} '${url}'`;
|
|
171
|
+
|
|
172
|
+
// 添加 headers
|
|
173
|
+
Object.keys(headers).forEach(key => {
|
|
174
|
+
curlCmd += ` \\\n -H '${key}: ${headers[key]}'`;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// 添加 body
|
|
178
|
+
if (body) {
|
|
179
|
+
curlCmd += ` \\\n -d '${body}'`;
|
|
180
|
+
}
|
|
181
|
+
console.log('\n========== CURL 请求 ==========');
|
|
182
|
+
console.log(curlCmd);
|
|
183
|
+
console.log('================================\n');
|
|
184
|
+
}
|
|
104
185
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
4
|
+
require("core-js/modules/esnext.iterator.reduce.js");
|
|
3
5
|
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let servicePath = path.resolve(__dirname, './service'); // [Iam, Kec]
|
|
9
|
-
|
|
8
|
+
// /xxx/node-sdk/src/service
|
|
9
|
+
let servicePath = path.resolve(__dirname, './service');
|
|
10
|
+
// [Iam, Kec]
|
|
10
11
|
let serviceDirs = fs.readdirSync(servicePath);
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* {
|
|
13
15
|
* Iam: {
|
|
@@ -15,27 +17,22 @@ let serviceDirs = fs.readdirSync(servicePath);
|
|
|
15
17
|
* }
|
|
16
18
|
* }
|
|
17
19
|
*/
|
|
18
|
-
|
|
19
20
|
module.exports = serviceDirs.reduce((acc, serviceDir) => {
|
|
20
21
|
// /xxx/node-sdk/src/service/iam
|
|
21
22
|
let versionPath = path.resolve(servicePath, serviceDir);
|
|
22
|
-
|
|
23
23
|
if (fs.statSync(versionPath).isDirectory()) {
|
|
24
24
|
// [v20151101, v20160606]
|
|
25
|
-
let versionDirs = fs.readdirSync(versionPath);
|
|
26
|
-
|
|
25
|
+
let versionDirs = fs.readdirSync(versionPath);
|
|
26
|
+
// acc.Iam
|
|
27
27
|
acc[serviceDir] = versionDirs.reduce((accVersion, versionDir) => {
|
|
28
28
|
// /xxx/node-sdk/src/service/iam/v20151101/index.js
|
|
29
29
|
let filePath = path.resolve(versionPath, versionDir, 'index.js');
|
|
30
|
-
|
|
31
30
|
if (fs.existsSync(filePath)) {
|
|
32
31
|
// accVersion.v20151101
|
|
33
32
|
accVersion[versionDir] = require(filePath);
|
|
34
33
|
}
|
|
35
|
-
|
|
36
34
|
return accVersion;
|
|
37
35
|
}, {});
|
|
38
36
|
}
|
|
39
|
-
|
|
40
37
|
return acc;
|
|
41
38
|
}, {});
|
package/dist/lib/fetch.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const nodeFetch = require('node-fetch');
|
|
4
|
+
const AbortController = require('abort-controller');
|
|
5
|
+
// const HttpsProxyAgent = require('https-proxy-agent')
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
let proxyConfig = {};
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
let proxyConfig = {}; // if (process.env.isKscSdkTest) {
|
|
9
|
+
// if (process.env.isKscSdkTest) {
|
|
9
10
|
// 本地代理
|
|
10
11
|
// proxyConfig = {
|
|
11
12
|
// agent: new HttpsProxyAgent('http://localhost:9090')
|
|
@@ -14,13 +15,11 @@ let proxyConfig = {}; // if (process.env.isKscSdkTest) {
|
|
|
14
15
|
|
|
15
16
|
module.exports = function (url, options) {
|
|
16
17
|
const controller = new AbortController();
|
|
17
|
-
|
|
18
18
|
if (options.timeout) {
|
|
19
19
|
setTimeout(() => {
|
|
20
20
|
controller.abort();
|
|
21
21
|
}, options.timeout);
|
|
22
22
|
}
|
|
23
|
-
|
|
24
23
|
return nodeFetch(url, {
|
|
25
24
|
signal: controller.signal,
|
|
26
25
|
...proxyConfig,
|
package/dist/lib/sign.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
require("core-js/modules/es.array.sort.js");
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
5
|
+
require("core-js/modules/esnext.iterator.for-each.js");
|
|
6
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
7
|
+
const crypto = require("crypto-js");
|
|
8
|
+
// const qs = require("qs")
|
|
7
9
|
|
|
8
10
|
module.exports = {
|
|
9
11
|
getSignedParams,
|
|
@@ -13,31 +15,32 @@ module.exports = {
|
|
|
13
15
|
getFormatParams,
|
|
14
16
|
isArrayOrObjectNotNull
|
|
15
17
|
};
|
|
18
|
+
|
|
16
19
|
/**
|
|
17
20
|
* 简化版签名算法
|
|
18
21
|
* @param {*} params 参数
|
|
19
22
|
* @param {*} sk
|
|
20
23
|
*/
|
|
21
|
-
|
|
22
24
|
function getSignedParams(params, sk) {
|
|
23
25
|
if (!sk) {
|
|
24
26
|
throw new Error('need sk');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
}
|
|
28
|
+
// 第零点一步:参数扁平化处理
|
|
29
|
+
let flatParams = getFlatParams(params);
|
|
30
|
+
// 第零点二步:去除值为null的参数, boolean转字符串
|
|
31
|
+
flatParams = getFormatParams(flatParams);
|
|
32
|
+
// 第一步:请求参数排序 请求参数包括公共参数和业务参数,不包含公共参数Signature。 排序规则以参数名按照字典排序.
|
|
33
|
+
let sortParamKeys = Object.keys(flatParams).sort();
|
|
34
|
+
// 第二步:请求参数编码
|
|
33
35
|
// 使用UTF-8字符集按照RFC3986规则编码请求参数和参数取值
|
|
34
36
|
// 第三步:请求参数拼接成CanonicalizedQueryString
|
|
35
37
|
// 每对URLEncode后的参数名称和参数值,用=进行连接。每对之间使用&进行连接。得到规范化请求字符串CanonicalizedQueryString
|
|
36
|
-
|
|
37
38
|
let canonicalizedQueryString = sortParamKeys.map(key => {
|
|
38
39
|
let value = flatParams[key];
|
|
39
40
|
return `${fixedEncodeURIComponent(key)}=${fixedEncodeURIComponent(value)}`;
|
|
40
|
-
}).join('&');
|
|
41
|
+
}).join('&');
|
|
42
|
+
|
|
43
|
+
// 参见源码得qs的处理顺序-符合流程:1. 去除null 2. 排序、3. 编码 4. 按照url参数拼接
|
|
41
44
|
// let canonicalizedQueryString = qs.stringify(flatParams, {
|
|
42
45
|
// sort: (a, b) => a.localeCompare(b),
|
|
43
46
|
// format : 'RFC3986',
|
|
@@ -45,28 +48,30 @@ function getSignedParams(params, sk) {
|
|
|
45
48
|
// arrayFormat: 'indices', // 数组转成a[0]
|
|
46
49
|
// allowDots: true, // 对象转成a.b.c
|
|
47
50
|
// } )
|
|
48
|
-
// 计算签名。
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
// 计算签名。
|
|
53
|
+
let sign = crypto.HmacSHA256(canonicalizedQueryString, sk).toString();
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
// 添加到请求参数
|
|
56
|
+
return {
|
|
57
|
+
...flatParams,
|
|
53
58
|
Signature: sign
|
|
54
59
|
};
|
|
55
60
|
}
|
|
61
|
+
|
|
56
62
|
/**
|
|
57
63
|
* RFC 3986
|
|
58
64
|
* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
|
|
59
65
|
* @param {*} str
|
|
60
66
|
* @returns
|
|
61
67
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
64
68
|
function fixedEncodeURIComponent(str) {
|
|
65
69
|
// encodeURIComponent比RFC 3986少了!'()*这个几个字符的转义
|
|
66
70
|
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
|
|
67
71
|
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
|
|
68
72
|
});
|
|
69
73
|
}
|
|
74
|
+
|
|
70
75
|
/**
|
|
71
76
|
* 格式化参数,对Array,Filter(Object),Object类型做扁平处理
|
|
72
77
|
* @example
|
|
@@ -76,15 +81,13 @@ function fixedEncodeURIComponent(str) {
|
|
|
76
81
|
* @param {object} params 参数值
|
|
77
82
|
* @returns 格式化后的参数
|
|
78
83
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
84
|
function getFlatParams(params) {
|
|
82
85
|
let res = {};
|
|
83
86
|
Object.keys(params).forEach(key => {
|
|
84
87
|
let value = params[key];
|
|
85
|
-
|
|
86
88
|
if (isArrayOrObjectNotNull(value)) {
|
|
87
|
-
res = {
|
|
89
|
+
res = {
|
|
90
|
+
...res,
|
|
88
91
|
...flatObj(key, params[key])
|
|
89
92
|
};
|
|
90
93
|
} else {
|
|
@@ -93,14 +96,13 @@ function getFlatParams(params) {
|
|
|
93
96
|
});
|
|
94
97
|
return res;
|
|
95
98
|
}
|
|
99
|
+
|
|
96
100
|
/**
|
|
97
101
|
* 扁平化对象
|
|
98
102
|
* @param {string} pKey key
|
|
99
103
|
* @param {*} value 对象或者数组,非null
|
|
100
104
|
* @returns
|
|
101
105
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
106
|
function flatObj(pKey, value) {
|
|
105
107
|
let res = {};
|
|
106
108
|
let prefixName = '';
|
|
@@ -110,11 +112,10 @@ function flatObj(pKey, value) {
|
|
|
110
112
|
} else {
|
|
111
113
|
prefixName = `${pKey}.${key}`;
|
|
112
114
|
}
|
|
113
|
-
|
|
114
115
|
let childValue = value[key];
|
|
115
|
-
|
|
116
116
|
if (isArrayOrObjectNotNull(childValue)) {
|
|
117
|
-
res = {
|
|
117
|
+
res = {
|
|
118
|
+
...res,
|
|
118
119
|
...flatObj(prefixName, childValue)
|
|
119
120
|
};
|
|
120
121
|
} else {
|
|
@@ -123,33 +124,30 @@ function flatObj(pKey, value) {
|
|
|
123
124
|
});
|
|
124
125
|
return res;
|
|
125
126
|
}
|
|
127
|
+
|
|
126
128
|
/**
|
|
127
129
|
* 1. 剔除null、undefined,
|
|
128
130
|
* 2. boolean转字符串
|
|
129
131
|
* @param {object} params 参数对象
|
|
130
132
|
* @returns {object}
|
|
131
133
|
*/
|
|
132
|
-
|
|
133
|
-
|
|
134
134
|
function getFormatParams(params) {
|
|
135
135
|
Object.keys(params).forEach(key => {
|
|
136
136
|
if (params[key] == null) {
|
|
137
137
|
delete params[key];
|
|
138
138
|
}
|
|
139
|
-
|
|
140
139
|
if (Object.prototype.toString.call(params[key]) == '[object Boolean]') {
|
|
141
140
|
params[key] = params[key].toString();
|
|
142
141
|
}
|
|
143
142
|
});
|
|
144
143
|
return params;
|
|
145
144
|
}
|
|
145
|
+
|
|
146
146
|
/**
|
|
147
147
|
* 是否为数组或者对象,非null
|
|
148
148
|
* @param {any} value
|
|
149
149
|
* @returns {boolean}
|
|
150
150
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
151
|
function isArrayOrObjectNotNull(value) {
|
|
154
152
|
return Array.isArray(value) || Object.prototype.toString.call(value) == '[object Object]';
|
|
155
153
|
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("core-js/modules/es.array.sort.js");
|
|
4
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
5
|
+
require("core-js/modules/esnext.iterator.filter.js");
|
|
6
|
+
require("core-js/modules/esnext.iterator.for-each.js");
|
|
7
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
8
|
+
const crypto = require("crypto-js");
|
|
9
|
+
const dayjs = require('dayjs');
|
|
10
|
+
const utc = require('dayjs/plugin/utc.js');
|
|
11
|
+
dayjs.extend(utc);
|
|
12
|
+
const HEADERS_TO_IGNORE = {
|
|
13
|
+
'cache-control': true,
|
|
14
|
+
'content-type': true,
|
|
15
|
+
'content-length': true,
|
|
16
|
+
'expect': true,
|
|
17
|
+
'max-forwards': true,
|
|
18
|
+
'pragma': true,
|
|
19
|
+
'range': true,
|
|
20
|
+
'te': true,
|
|
21
|
+
'if-match': true,
|
|
22
|
+
'if-none-match': true,
|
|
23
|
+
'if-modified-since': true,
|
|
24
|
+
'if-unmodified-since': true,
|
|
25
|
+
'if-range': true,
|
|
26
|
+
'accept': true,
|
|
27
|
+
'authorization': true,
|
|
28
|
+
'proxy-authorization': true,
|
|
29
|
+
'from': true,
|
|
30
|
+
'referer': true,
|
|
31
|
+
'user-agent': true
|
|
32
|
+
};
|
|
33
|
+
function getSignatureKey(key, dateStamp, regionName, serviceName) {
|
|
34
|
+
var kDate = crypto.HmacSHA256(dateStamp, "AWS4" + key);
|
|
35
|
+
var kRegion = crypto.HmacSHA256(regionName, kDate);
|
|
36
|
+
var kService = crypto.HmacSHA256(serviceName, kRegion);
|
|
37
|
+
var kSigning = crypto.HmacSHA256("aws4_request", kService);
|
|
38
|
+
return kSigning;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 编码
|
|
43
|
+
* @param {*} str
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
function encodeRfc3986Full(str) {
|
|
47
|
+
// This function assumes the string has already been percent encoded
|
|
48
|
+
function encodeRfc3986(urlEncodedString) {
|
|
49
|
+
return urlEncodedString.replace(/[!'()*]/g, function (c) {
|
|
50
|
+
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return encodeRfc3986(encodeURIComponent(str));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {*} path
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
function createCanonicalizedPath(path) {
|
|
62
|
+
return encodeRfc3986Full(path).replace(/%2F/g, '/');
|
|
63
|
+
}
|
|
64
|
+
function getCanonicalHeaders(headers) {
|
|
65
|
+
function trimAll(header) {
|
|
66
|
+
return header.toString().trim().replace(/\s+/g, ' ');
|
|
67
|
+
}
|
|
68
|
+
return Object.keys(headers).filter(function (key) {
|
|
69
|
+
return HEADERS_TO_IGNORE[key.toLowerCase()] == null;
|
|
70
|
+
}).sort(function (a, b) {
|
|
71
|
+
return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
|
|
72
|
+
}).map(function (key) {
|
|
73
|
+
return key.toLowerCase() + ':' + trimAll(headers[key]);
|
|
74
|
+
}).join('\n') + '\n';
|
|
75
|
+
}
|
|
76
|
+
function getSignedHeaders(headers) {
|
|
77
|
+
return Object.keys(headers).map(function (key) {
|
|
78
|
+
return key.toLowerCase();
|
|
79
|
+
}).filter(function (key) {
|
|
80
|
+
return HEADERS_TO_IGNORE[key] == null;
|
|
81
|
+
}).sort().join(';');
|
|
82
|
+
}
|
|
83
|
+
function getCanonicalizedQuery(query) {
|
|
84
|
+
if (!query) {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
delete query['X-Amz-Signature']; // php项目里有这句
|
|
88
|
+
let res = [];
|
|
89
|
+
let sortKeys = Object.keys(query).sort();
|
|
90
|
+
sortKeys.forEach(key => {
|
|
91
|
+
if (!Array.isArray(query[key])) {
|
|
92
|
+
res.push(encodeRfc3986Full(key) + '=' + encodeRfc3986Full(query[key]));
|
|
93
|
+
} else {
|
|
94
|
+
query[key].map(encodeRfc3986Full).sort().forEach(val => {
|
|
95
|
+
res.push(encodeRfc3986Full(key) + '=' + encodeRfc3986Full(val));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return res.join('&');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 签名步骤摘要
|
|
103
|
+
// 要创建已签名的请求,请完成以下操作:
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 获取包含签名的头,含之前的头
|
|
107
|
+
* AWS Version 4
|
|
108
|
+
* https://docs.aws.amazon.com/zh_cn/general/latest/gr/sigv4_signing.html
|
|
109
|
+
* @param {string} path
|
|
110
|
+
* @param {string} query
|
|
111
|
+
*/
|
|
112
|
+
function getSignatureHeaders({
|
|
113
|
+
path,
|
|
114
|
+
query,
|
|
115
|
+
body,
|
|
116
|
+
headers,
|
|
117
|
+
host,
|
|
118
|
+
method,
|
|
119
|
+
region,
|
|
120
|
+
service,
|
|
121
|
+
secret_key,
|
|
122
|
+
access_key
|
|
123
|
+
}) {
|
|
124
|
+
let now = dayjs().utc();
|
|
125
|
+
let amzdate = now.format(`YYYYMMDDTHHmmssZ`);
|
|
126
|
+
let datestamp = now.format('YYYYMMDD');
|
|
127
|
+
|
|
128
|
+
// 任务 1:针对签名版本 4 创建规范请求
|
|
129
|
+
// 将请求的内容(主体、操作、标头等)组织为标准(规范)格式。规范请求是用于创建待签字符串的输入之一。
|
|
130
|
+
|
|
131
|
+
let canonical_uri = createCanonicalizedPath(path);
|
|
132
|
+
let canonical_querystring = getCanonicalizedQuery(query);
|
|
133
|
+
let allHeaders = {
|
|
134
|
+
...headers,
|
|
135
|
+
host,
|
|
136
|
+
'x-amz-date': amzdate
|
|
137
|
+
};
|
|
138
|
+
let canonical_headers = getCanonicalHeaders(allHeaders);
|
|
139
|
+
let signed_headers = getSignedHeaders(allHeaders);
|
|
140
|
+
let payload_hash = headers['X-Amz-Content-Sha256'] || headers['x-amz-content-sha256'] || crypto.SHA256(body || '').toString();
|
|
141
|
+
let canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;
|
|
142
|
+
|
|
143
|
+
// 任务 2:创建签名版本 4 的待签字符串
|
|
144
|
+
// 使用规范请求和额外信息(例如算法、请求日期、凭证范围和规范请求的摘要(哈希))创建待签字符串。
|
|
145
|
+
let algorithm = 'AWS4-HMAC-SHA256';
|
|
146
|
+
let credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
|
|
147
|
+
let string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + crypto.SHA256(canonical_request).toString();
|
|
148
|
+
|
|
149
|
+
// 任务 3:为AWS签名版本 4 计算签名
|
|
150
|
+
// 使用AWS秘密访问密钥作为初始哈希操作的密钥,对请求日期、区域和服务执行一系列加密哈希操作(HMAC 操作),从而派生签名密钥。在派生签名密钥后,通过对待签字符串执行加密哈希操作来计算签名。使用派生的签名密钥作为此操作的哈希密钥。
|
|
151
|
+
let signing_key = getSignatureKey(secret_key, datestamp, region, service);
|
|
152
|
+
let signature = crypto.HmacSHA256(string_to_sign, signing_key).toString();
|
|
153
|
+
|
|
154
|
+
// 任务 4:将签名添加到 HTTP 请求
|
|
155
|
+
// 在计算签名后,将其添加到请求的 HTTP 标头或查询字符串中。
|
|
156
|
+
let authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature;
|
|
157
|
+
let res = {
|
|
158
|
+
...headers
|
|
159
|
+
};
|
|
160
|
+
res['x-amz-date'] = amzdate;
|
|
161
|
+
res['Authorization'] = authorization_header;
|
|
162
|
+
return res;
|
|
163
|
+
}
|
|
164
|
+
module.exports = {
|
|
165
|
+
getCanonicalizedQuery,
|
|
166
|
+
getSignatureHeaders
|
|
167
|
+
};
|