@cloudbase/node-sdk 3.17.0 → 3.17.1-alpha.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.
@@ -135,6 +135,10 @@ class Auth {
135
135
  });
136
136
  }
137
137
  async getClientCredential(opts) {
138
+ // 如果有 accessKey 直接返回 accessKey,不用再去换取 token
139
+ if (this.cloudbase.config.accessKey) {
140
+ return this.cloudbase.config.accessKey;
141
+ }
138
142
  return await tcbopenapicommonrequester.request({
139
143
  config: this.cloudbase.config,
140
144
  method: 'POST',
package/dist/cloudbase.js CHANGED
@@ -22,17 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __rest = (this && this.__rest) || function (s, e) {
26
- var t = {};
27
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
28
- t[p] = s[p];
29
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
30
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
31
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
32
- t[p[i]] = s[p[i]];
33
- }
34
- return t;
35
- };
36
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
37
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
27
  };
@@ -49,14 +38,13 @@ const wx_1 = require("./wx");
49
38
  const analytics_1 = require("./analytics");
50
39
  const ai_1 = require("./ai");
51
40
  const logger_1 = require("./logger");
52
- const code_1 = require("./const/code");
53
- const utils = __importStar(require("./utils/utils"));
54
41
  const cloudplatform_1 = require("./utils/cloudplatform");
55
42
  const tcbcontext_1 = require("./utils/tcbcontext");
56
43
  const notification_1 = require("./notification");
57
44
  const openapicommonrequester = __importStar(require("./utils/tcbopenapicommonrequester"));
58
45
  const tcbopenapiendpoint_1 = require("./utils/tcbopenapiendpoint");
59
46
  const symbol_1 = require("./const/symbol");
47
+ const utils_1 = require("./utils/utils");
60
48
  class CloudBase {
61
49
  static parseContext(context) {
62
50
  const parseResult = (0, tcbcontext_1.parseContext)(context);
@@ -70,33 +58,14 @@ class CloudBase {
70
58
  this.init(config);
71
59
  }
72
60
  init(config = {}) {
73
- var _a, _b, _c, _d;
74
61
  // 预检运行环境,调用与否并不影响后续逻辑
75
62
  // 注意:该函数为异步函数,这里并不等待检查结果
76
63
  /* eslint-disable-next-line */
77
64
  (0, cloudplatform_1.preflightRuntimeCloudPlatform)();
78
- const { debug, secretId, secretKey, sessionToken, env, timeout, headers = {} } = config, restConfig = __rest(config, ["debug", "secretId", "secretKey", "sessionToken", "env", "timeout", "headers"]);
79
- if (('secretId' in config && !('secretKey' in config)) || (!('secretId' in config) && 'secretKey' in config)) {
80
- throw utils.E(Object.assign(Object.assign({}, code_1.ERROR.INVALID_PARAM), { message: 'secretId and secretKey must be a pair' }));
81
- }
82
- const newConfig = Object.assign(Object.assign({}, restConfig), { debug: !!debug, secretId,
83
- secretKey,
84
- sessionToken,
85
- env, envName: env, headers: Object.assign({}, headers), timeout: timeout || 15000 });
86
- if ((_a = config.context) === null || _a === void 0 ? void 0 : _a.extendedContext) {
87
- const extendedContext = config.context.extendedContext;
88
- if (!newConfig.env) {
89
- newConfig.env = extendedContext.envId;
90
- newConfig.envName = newConfig.env;
91
- }
92
- // 从 context 中获取 secret
93
- if (!newConfig.secretId && !newConfig.secretKey) {
94
- newConfig.secretId = (_b = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _b === void 0 ? void 0 : _b.secretId;
95
- newConfig.secretKey = (_c = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _c === void 0 ? void 0 : _c.secretKey;
96
- newConfig.sessionToken = (_d = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _d === void 0 ? void 0 : _d.token;
97
- }
98
- }
99
- this.config = newConfig;
65
+ // 所有的鉴权,参数塑形都在 normalizeConfig 中处理
66
+ // 后续其他模块获取 config 都通过 CloudBase 实例的 config 获取
67
+ // 禁止在业务模块中直接修改 config 配置
68
+ this.config = (0, utils_1.normalizeConfig)(config);
100
69
  this.extensionMap = new Map();
101
70
  // NOTE:try-catch 为防止 init 报错
102
71
  try {
@@ -112,6 +81,10 @@ class CloudBase {
112
81
  method: (_a = options.method) === null || _a === void 0 ? void 0 : _a.toUpperCase(),
113
82
  url: options.url,
114
83
  headers: Object.assign({ 'Content-Type': 'application/json' }, headersInitToRecord(options.headers)),
84
+ /**
85
+ * 既然 openapicommonrequester.request 的参数里的 token 获取也是通过 openapicommonrequester.request 方法去获取的
86
+ * 为什么不把这里的 token 去掉,全部放在 openapicommonrequester.request 中去统一处理 token 获取的逻辑
87
+ */
115
88
  token: (await this.auth().getClientCredential()).access_token
116
89
  });
117
90
  return result.body;
@@ -127,9 +127,15 @@ class TcbApiHttpRequester {
127
127
  this.tracingInfo = (0, tracing_1.generateTracingInfo)((_b = (_a = args.config) === null || _a === void 0 ? void 0 : _a.context) === null || _b === void 0 ? void 0 : _b.eventID);
128
128
  }
129
129
  async request() {
130
- await this.prepareCredentials();
130
+ // 如果没有配置 accessKey,则通过密钥获取签名,这里先检查密钥是否存在
131
+ if (!this.config.accessKey) {
132
+ // 检查密钥是否存在
133
+ await this.prepareCredentials();
134
+ }
131
135
  const params = await this.makeParams();
136
+ // console.log('params', params)
132
137
  const opts = this.makeReqOpts(params);
138
+ // console.log('opts', opts)
133
139
  const action = this.getAction();
134
140
  const key = {
135
141
  functions: 'function_name',
@@ -277,7 +283,7 @@ class TcbApiHttpRequester {
277
283
  getHeaders(method, url, params) {
278
284
  var _a;
279
285
  const config = this.config;
280
- const { context, secretId, secretKey } = config;
286
+ const { context, secretId, secretKey, accessKey } = config;
281
287
  const args = this.args;
282
288
  const { TCB_SOURCE } = cloudbase_1.CloudBase.getCloudbaseContext();
283
289
  // Note: 云函数被调用时可能调用端未传递 SOURCE,TCB_SOURCE 可能为空
@@ -317,7 +323,8 @@ class TcbApiHttpRequester {
317
323
  timestamp: second() - 1
318
324
  });
319
325
  /* eslint-disable @typescript-eslint/dot-notation */
320
- requiredHeaders['Authorization'] = authorization;
326
+ // 优先使用 accessKey,否则使用签名
327
+ requiredHeaders['Authorization'] = accessKey ? `Bearer ${accessKey}` : authorization;
321
328
  requiredHeaders['X-Signature-Expires'] = 600;
322
329
  requiredHeaders['X-Timestamp'] = timestamp;
323
330
  return Object.assign({}, requiredHeaders);
@@ -334,6 +341,7 @@ const handleWxOpenApiData = (res, err, response, body) => {
334
341
  return transformRes;
335
342
  };
336
343
  async function request(args) {
344
+ // console.log('args', args)
337
345
  if (typeof args.isInternal === 'undefined') {
338
346
  args.isInternal = await (0, cloudplatform_1.checkIsInternalAsync)();
339
347
  }
@@ -60,6 +60,7 @@ exports.parseContext = parseContext;
60
60
  * 获取当前函数内的所有环境变量(作为获取变量的统一方法,取值来源 process.env 和 context)
61
61
  */
62
62
  function getCloudbaseContext(context) {
63
+ // console.log('context', context)
63
64
  if ((0, cloudplatform_1.checkIsInScf)()) {
64
65
  // 云函数环境下,应该包含以下环境变量,如果没有,后续逻辑可能会有问题
65
66
  if (!process.env.TENCENTCLOUD_REGION) {
@@ -56,8 +56,13 @@ class TcbOpenApiHttpCommonRequester {
56
56
  this.tracingInfo = (0, tracing_1.generateTracingInfo)((_b = (_a = args.config) === null || _a === void 0 ? void 0 : _a.context) === null || _b === void 0 ? void 0 : _b.eventID);
57
57
  }
58
58
  async request() {
59
- await this.prepareCredentials();
59
+ // 如果没有 accessKey,去检查密钥是否存在,有则直接使用
60
+ if (!this.config.accessKey) {
61
+ // 检查密钥是否存在
62
+ await this.prepareCredentials();
63
+ }
60
64
  const opts = this.makeReqOpts();
65
+ // console.log('opts', opts)
61
66
  const argopts = this.opts;
62
67
  const config = this.config;
63
68
  // 注意:必须初始化为 null
@@ -140,7 +145,7 @@ class TcbOpenApiHttpCommonRequester {
140
145
  buildHeaders(method, url) {
141
146
  var _a;
142
147
  const config = this.config;
143
- const { context, secretId, secretKey, sessionToken } = config;
148
+ const { context, secretId, secretKey, sessionToken, accessKey } = config;
144
149
  const args = this.args;
145
150
  const { TCB_SOURCE } = cloudbase_1.CloudBase.getCloudbaseContext();
146
151
  // Note: 云函数被调用时可能调用端未传递 SOURCE,TCB_SOURCE 可能为空
@@ -181,12 +186,25 @@ class TcbOpenApiHttpCommonRequester {
181
186
  withSignedParams: false,
182
187
  isCloudApi: true
183
188
  });
189
+ // console.log('xxxx', authorization)
190
+ let token = '';
191
+ // 如果请求参数里面传了 token,优先使用 token
192
+ if (args.token) {
193
+ token = makeBearerToken(args.token);
194
+ }
195
+ else if (accessKey) {
196
+ // 如果配置了 API_KEY,优先使用 API_KEY
197
+ token = makeBearerToken(accessKey);
198
+ }
199
+ else if (typeof sessionToken === 'string' && sessionToken !== '') {
200
+ // 如果配置了 sessionToken,携带 sessionToken
201
+ token = `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`;
202
+ }
203
+ else {
204
+ token = `${authorization}, Timestamp=${timestamp}`;
205
+ }
184
206
  /* eslint-disable @typescript-eslint/dot-notation */
185
- requiredHeaders['Authorization'] = args.token
186
- ? makeBearerToken(args.token)
187
- : typeof sessionToken === 'string' && sessionToken !== ''
188
- ? `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
189
- : `${authorization}, Timestamp=${timestamp}`;
207
+ requiredHeaders['Authorization'] = token;
190
208
  return Object.assign({}, requiredHeaders);
191
209
  }
192
210
  }
@@ -56,8 +56,11 @@ class TcbOpenApiHttpRequester {
56
56
  this.tracingInfo = (0, tracing_1.generateTracingInfo)((_b = (_a = args.config) === null || _a === void 0 ? void 0 : _a.context) === null || _b === void 0 ? void 0 : _b.eventID);
57
57
  }
58
58
  async request() {
59
- await this.prepareCredentials();
59
+ if (!this.config.accessKey) {
60
+ await this.prepareCredentials();
61
+ }
60
62
  const opts = this.makeReqOpts();
63
+ // console.log('opts', opts)
61
64
  const argopts = this.opts;
62
65
  const config = this.config;
63
66
  // 注意:必须初始化为 null
@@ -140,7 +143,7 @@ class TcbOpenApiHttpRequester {
140
143
  buildHeaders(method, url) {
141
144
  var _a;
142
145
  const config = this.config;
143
- const { context, secretId, secretKey, sessionToken } = config;
146
+ const { context, secretId, secretKey, sessionToken, accessKey } = config;
144
147
  const args = this.args;
145
148
  const { TCB_SOURCE } = cloudbase_1.CloudBase.getCloudbaseContext();
146
149
  // Note: 云函数被调用时可能调用端未传递 SOURCE,TCB_SOURCE 可能为空
@@ -186,10 +189,24 @@ class TcbOpenApiHttpRequester {
186
189
  withSignedParams: false,
187
190
  isCloudApi: true
188
191
  });
192
+ let token = '';
193
+ // 如果请求参数里面传了 token,优先使用 token
194
+ if (args.token) {
195
+ token = makeBearerToken(args.token);
196
+ }
197
+ else if (accessKey) {
198
+ // 如果配置了 API_KEY,优先使用 API_KEY
199
+ token = makeBearerToken(accessKey);
200
+ }
201
+ else if (typeof sessionToken === 'string' && sessionToken !== '') {
202
+ // 如果配置了 sessionToken,使用 sessionToken
203
+ token = `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`;
204
+ }
205
+ else {
206
+ token = `${authorization}, Timestamp=${timestamp}`;
207
+ }
189
208
  /* eslint-disable @typescript-eslint/dot-notation */
190
- requiredHeaders['Authorization'] = typeof sessionToken === 'string' && sessionToken !== ''
191
- ? `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
192
- : `${authorization}, Timestamp=${timestamp}`;
209
+ requiredHeaders['Authorization'] = token;
193
210
  return Object.assign({}, requiredHeaders);
194
211
  }
195
212
  }
@@ -204,3 +221,7 @@ async function request(args) {
204
221
  return await requester.request();
205
222
  }
206
223
  exports.request = request;
224
+ function makeBearerToken(token) {
225
+ const trimmed = token.trim();
226
+ return trimmed.startsWith('Bearer ') ? trimmed : `Bearer ${trimmed}`;
227
+ }
@@ -1,6 +1,31 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isValidEnvFormat = exports.isPageModuleName = exports.processReturn = exports.setThrowOnCode = exports.second = exports.isNonEmptyString = exports.E = exports.filterUndefined = exports.filterValue = exports.isAppId = exports.TcbError = void 0;
26
+ exports.normalizeConfig = exports.isValidEnvFormat = exports.isPageModuleName = exports.processReturn = exports.setThrowOnCode = exports.second = exports.isNonEmptyString = exports.E = exports.filterUndefined = exports.filterValue = exports.isAppId = exports.TcbError = void 0;
27
+ const utils = __importStar(require("../utils/utils"));
28
+ const code_1 = require("../const/code");
4
29
  class TcbError extends Error {
5
30
  constructor(error) {
6
31
  super(error.message);
@@ -72,3 +97,50 @@ function isValidEnvFormat(env = '') {
72
97
  return typeof env === 'string' && kEnvRuleReg.test(env);
73
98
  }
74
99
  exports.isValidEnvFormat = isValidEnvFormat;
100
+ function normalizeConfig(config) {
101
+ var _a, _b, _c, _d;
102
+ const { debug = false, secretId, secretKey, env, timeout = 15000, headers = {}, accessKey } = config;
103
+ // 检查用户显示配置的 secretId 和 secretKey 是否成对出现,要么都有,要么都没有
104
+ if (!secretId !== !secretKey) {
105
+ throw utils.E(Object.assign(Object.assign({}, code_1.ERROR.INVALID_PARAM), { message: 'secretId and secretKey must be a pair' }));
106
+ }
107
+ const cloudbaseConfigBase = Object.assign(Object.assign({}, config), { debug,
108
+ // secretId,
109
+ // secretKey,
110
+ envName: env, headers: Object.assign({}, headers), // 结构用户传进来的 headers,防止用户修改原对象
111
+ timeout
112
+ // accessKey: accessKey || process.env.CLOUDBASE_APIKEY
113
+ });
114
+ const { TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN, CLOUDBASE_APIKEY } = process.env;
115
+ // 如果用户显示配置了accessKey,取用户显示配置的 accessKey,优先级最高
116
+ if (accessKey) {
117
+ return Object.assign(cloudbaseConfigBase, { secretId: undefined, secretKey: undefined, accessKey });
118
+ }
119
+ // 显示配置了 secretId, secretKey,取 secretId, secretKey
120
+ if (secretId && secretKey) {
121
+ return Object.assign(cloudbaseConfigBase, { secretId, secretKey, accessKey: undefined });
122
+ }
123
+ // 下面从环境变量取 secretId, secretKey, accessKey
124
+ if (CLOUDBASE_APIKEY) {
125
+ return Object.assign(cloudbaseConfigBase, { secretId: undefined, secretKey: undefined, accessKey: CLOUDBASE_APIKEY });
126
+ }
127
+ if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
128
+ return Object.assign(cloudbaseConfigBase, { secretId: TENCENTCLOUD_SECRETID, secretKey: TENCENTCLOUD_SECRETKEY, sessionToken: TENCENTCLOUD_SESSIONTOKEN, accessKey: undefined });
129
+ }
130
+ if ((_a = config.context) === null || _a === void 0 ? void 0 : _a.extendedContext) {
131
+ const extendedContext = config.context.extendedContext;
132
+ if (!cloudbaseConfigBase.env) {
133
+ cloudbaseConfigBase.env = extendedContext.envId;
134
+ cloudbaseConfigBase.envName = extendedContext.envId;
135
+ }
136
+ // 从 context 中获取 secret
137
+ if (!cloudbaseConfigBase.secretId && !cloudbaseConfigBase.secretKey) {
138
+ cloudbaseConfigBase.secretId = (_b = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _b === void 0 ? void 0 : _b.secretId;
139
+ cloudbaseConfigBase.secretKey = (_c = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _c === void 0 ? void 0 : _c.secretKey;
140
+ cloudbaseConfigBase.sessionToken = (_d = extendedContext === null || extendedContext === void 0 ? void 0 : extendedContext.tmpSecret) === null || _d === void 0 ? void 0 : _d.token;
141
+ }
142
+ }
143
+ // 都没有配置,返回原始的配置
144
+ return cloudbaseConfigBase;
145
+ }
146
+ exports.normalizeConfig = normalizeConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/node-sdk",
3
- "version": "3.17.0",
3
+ "version": "3.17.1-alpha.0",
4
4
  "description": "tencent cloud base server sdk for node.js",
5
5
  "main": "dist/index.js",
6
6
  "typings": "types/index.d.ts",
package/src/auth/index.ts CHANGED
@@ -147,6 +147,10 @@ export class Auth {
147
147
  }
148
148
 
149
149
  public async getClientCredential(opts?: ICustomReqOpts): Promise<any> {
150
+ // 如果有 accessKey 直接返回 accessKey,不用再去换取 token
151
+ if (this.cloudbase.config.accessKey) {
152
+ return this.cloudbase.config.accessKey
153
+ }
150
154
  return await tcbopenapicommonrequester.request({
151
155
  config: this.cloudbase.config,
152
156
  method: 'POST',
@@ -183,7 +187,7 @@ export class Auth {
183
187
  throw E({
184
188
  ...ERROR.INVALID_PARAM,
185
189
  message:
186
- '当前私钥未包含env_id 信息, 请前往腾讯云云开发控制台,获取自定义登录最新私钥'
190
+ '当前私钥未包含env_id 信息, 请前往腾讯云云开发控制台,获取自定义登录最新私钥'
187
191
  })
188
192
  }
189
193
 
package/src/cloudbase.ts CHANGED
@@ -63,7 +63,7 @@ import { IFetchOptions } from '@cloudbase/adapter-interface'
63
63
  import { buildCommonOpenApiUrlWithPath } from './utils/tcbopenapiendpoint'
64
64
  import { SYMBOL_CURRENT_ENV } from './const/symbol'
65
65
  import { IncomingHttpHeaders } from 'http'
66
-
66
+ import { normalizeConfig } from './utils/utils'
67
67
  export class CloudBase {
68
68
  public static scfContext: ISCFContext
69
69
 
@@ -100,43 +100,10 @@ export class CloudBase {
100
100
  /* eslint-disable-next-line */
101
101
  preflightRuntimeCloudPlatform()
102
102
 
103
- const { debug, secretId, secretKey, sessionToken, env, timeout, headers = {}, ...restConfig } = config
104
-
105
- if (('secretId' in config && !('secretKey' in config)) || (!('secretId' in config) && 'secretKey' in config)) {
106
- throw utils.E({
107
- ...ERROR.INVALID_PARAM,
108
- message: 'secretId and secretKey must be a pair'
109
- })
110
- }
111
-
112
- const newConfig: ICloudBaseConfig = {
113
- ...restConfig,
114
- debug: !!debug,
115
- secretId,
116
- secretKey,
117
- sessionToken,
118
- env,
119
- envName: env,
120
- headers: { ...headers },
121
- timeout: timeout || 15000
122
- }
123
-
124
- if (config.context?.extendedContext) {
125
- const extendedContext = config.context.extendedContext
126
- if (!newConfig.env) {
127
- newConfig.env = extendedContext.envId
128
- newConfig.envName = newConfig.env
129
- }
130
-
131
- // 从 context 中获取 secret
132
- if (!newConfig.secretId && !newConfig.secretKey) {
133
- newConfig.secretId = extendedContext?.tmpSecret?.secretId
134
- newConfig.secretKey = extendedContext?.tmpSecret?.secretKey
135
- newConfig.sessionToken = extendedContext?.tmpSecret?.token
136
- }
137
- }
138
-
139
- this.config = newConfig
103
+ // 所有的鉴权,参数塑形都在 normalizeConfig 中处理
104
+ // 后续其他模块获取 config 都通过 CloudBase 实例的 config 获取
105
+ // 禁止在业务模块中直接修改 config 配置
106
+ this.config = normalizeConfig(config)
140
107
  this.extensionMap = new Map()
141
108
 
142
109
  // NOTE:try-catch 为防止 init 报错
@@ -155,6 +122,10 @@ export class CloudBase {
155
122
  'Content-Type': 'application/json',
156
123
  ...headersInitToRecord(options.headers)
157
124
  },
125
+ /**
126
+ * 既然 openapicommonrequester.request 的参数里的 token 获取也是通过 openapicommonrequester.request 方法去获取的
127
+ * 为什么不把这里的 token 去掉,全部放在 openapicommonrequester.request 中去统一处理 token 获取的逻辑
128
+ */
158
129
  token: (await this.auth().getClientCredential()).access_token
159
130
  })
160
131
  return result.body
@@ -147,10 +147,15 @@ export class TcbApiHttpRequester {
147
147
  }
148
148
 
149
149
  public async request(): Promise<any> {
150
- await this.prepareCredentials()
150
+ // 如果没有配置 accessKey,则通过密钥获取签名,这里先检查密钥是否存在
151
+ if (!this.config.accessKey) {
152
+ // 检查密钥是否存在
153
+ await this.prepareCredentials()
154
+ }
151
155
  const params = await this.makeParams()
152
-
156
+ // console.log('params', params)
153
157
  const opts = this.makeReqOpts(params)
158
+ // console.log('opts', opts)
154
159
  const action = this.getAction()
155
160
  const key = {
156
161
  functions: 'function_name',
@@ -320,7 +325,7 @@ export class TcbApiHttpRequester {
320
325
 
321
326
  private getHeaders(method: string, url: string, params: any): any {
322
327
  const config = this.config
323
- const { context, secretId, secretKey } = config
328
+ const { context, secretId, secretKey, accessKey } = config
324
329
  const args = this.args
325
330
 
326
331
  const { TCB_SOURCE } = CloudBase.getCloudbaseContext()
@@ -370,7 +375,8 @@ export class TcbApiHttpRequester {
370
375
  })
371
376
 
372
377
  /* eslint-disable @typescript-eslint/dot-notation */
373
- requiredHeaders['Authorization'] = authorization
378
+ // 优先使用 accessKey,否则使用签名
379
+ requiredHeaders['Authorization'] = accessKey ? `Bearer ${accessKey}` : authorization
374
380
  requiredHeaders['X-Signature-Expires'] = 600
375
381
  requiredHeaders['X-Timestamp'] = timestamp
376
382
 
@@ -389,6 +395,7 @@ const handleWxOpenApiData = (res: any, err: any, response: any, body: any): any
389
395
  }
390
396
 
391
397
  export async function request(args: IRequestInfo): Promise<any> {
398
+ // console.log('args', args)
392
399
  if (typeof args.isInternal === 'undefined') {
393
400
  args.isInternal = await checkIsInternalAsync()
394
401
  }
@@ -76,6 +76,7 @@ export function parseContext(context: IContextParam): ISCFContext {
76
76
  * 获取当前函数内的所有环境变量(作为获取变量的统一方法,取值来源 process.env 和 context)
77
77
  */
78
78
  export function getCloudbaseContext(context?: IContextParam): ICompleteCloudbaseContext {
79
+ // console.log('context', context)
79
80
  if (checkIsInScf()) {
80
81
  // 云函数环境下,应该包含以下环境变量,如果没有,后续逻辑可能会有问题
81
82
  if (!process.env.TENCENTCLOUD_REGION) {
@@ -17,7 +17,6 @@ export class TcbDBApiHttpRequester {
17
17
  public async send(api: string, data: any, opts?: ICustomReqOpts): Promise<any> {
18
18
  const { instance, database, ...config } = this.config
19
19
  const params = { ...data, action: api, instance, database }
20
-
21
20
  return await tcbapicaller.request({
22
21
  config,
23
22
  params,
@@ -54,9 +54,14 @@ export class TcbOpenApiHttpCommonRequester {
54
54
  }
55
55
 
56
56
  public async request() {
57
- await this.prepareCredentials()
57
+ // 如果没有 accessKey,去检查密钥是否存在,有则直接使用
58
+ if (!this.config.accessKey) {
59
+ // 检查密钥是否存在
60
+ await this.prepareCredentials()
61
+ }
58
62
 
59
63
  const opts = this.makeReqOpts()
64
+ // console.log('opts', opts)
60
65
 
61
66
  const argopts: any = this.opts
62
67
  const config = this.config
@@ -144,7 +149,7 @@ export class TcbOpenApiHttpCommonRequester {
144
149
 
145
150
  private buildHeaders(method: string, url: string): any {
146
151
  const config = this.config
147
- const { context, secretId, secretKey, sessionToken } = config
152
+ const { context, secretId, secretKey, sessionToken, accessKey } = config
148
153
  const args = this.args
149
154
 
150
155
  const { TCB_SOURCE } = CloudBase.getCloudbaseContext()
@@ -194,13 +199,22 @@ export class TcbOpenApiHttpCommonRequester {
194
199
  withSignedParams: false,
195
200
  isCloudApi: true
196
201
  })
197
-
202
+ // console.log('xxxx', authorization)
203
+ let token = ''
204
+ // 如果请求参数里面传了 token,优先使用 token
205
+ if (args.token) {
206
+ token = makeBearerToken(args.token)
207
+ } else if (accessKey) {
208
+ // 如果配置了 API_KEY,优先使用 API_KEY
209
+ token = makeBearerToken(accessKey)
210
+ } else if (typeof sessionToken === 'string' && sessionToken !== '') {
211
+ // 如果配置了 sessionToken,携带 sessionToken
212
+ token = `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
213
+ } else {
214
+ token = `${authorization}, Timestamp=${timestamp}`
215
+ }
198
216
  /* eslint-disable @typescript-eslint/dot-notation */
199
- requiredHeaders['Authorization'] = args.token
200
- ? makeBearerToken(args.token)
201
- : typeof sessionToken === 'string' && sessionToken !== ''
202
- ? `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
203
- : `${authorization}, Timestamp=${timestamp}`
217
+ requiredHeaders['Authorization'] = token
204
218
 
205
219
  return { ...requiredHeaders }
206
220
  }
@@ -30,6 +30,7 @@ export function getEnvIdFromContext(): string {
30
30
  type ICallContainerRequestInfo = Omit<IRequestInfo, 'params'> & {
31
31
  path: string
32
32
  data: any
33
+ token?: string
33
34
  cloudrun: {
34
35
  name: string
35
36
  // version: string
@@ -56,9 +57,12 @@ export class TcbOpenApiHttpRequester {
56
57
  }
57
58
 
58
59
  public async request(): Promise<any> {
59
- await this.prepareCredentials()
60
+ if (!this.config.accessKey) {
61
+ await this.prepareCredentials()
62
+ }
60
63
 
61
64
  const opts = this.makeReqOpts()
65
+ // console.log('opts', opts)
62
66
 
63
67
  const argopts: any = this.opts
64
68
  const config = this.config
@@ -147,7 +151,7 @@ export class TcbOpenApiHttpRequester {
147
151
 
148
152
  private buildHeaders(method: string, url: string): any {
149
153
  const config = this.config
150
- const { context, secretId, secretKey, sessionToken } = config
154
+ const { context, secretId, secretKey, sessionToken, accessKey } = config
151
155
  const args = this.args
152
156
 
153
157
  const { TCB_SOURCE } = CloudBase.getCloudbaseContext()
@@ -204,11 +208,21 @@ export class TcbOpenApiHttpRequester {
204
208
  withSignedParams: false,
205
209
  isCloudApi: true
206
210
  })
207
-
211
+ let token = ''
212
+ // 如果请求参数里面传了 token,优先使用 token
213
+ if (args.token) {
214
+ token = makeBearerToken(args.token)
215
+ } else if (accessKey) {
216
+ // 如果配置了 API_KEY,优先使用 API_KEY
217
+ token = makeBearerToken(accessKey)
218
+ } else if (typeof sessionToken === 'string' && sessionToken !== '') {
219
+ // 如果配置了 sessionToken,使用 sessionToken
220
+ token = `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
221
+ } else {
222
+ token = `${authorization}, Timestamp=${timestamp}`
223
+ }
208
224
  /* eslint-disable @typescript-eslint/dot-notation */
209
- requiredHeaders['Authorization'] = typeof sessionToken === 'string' && sessionToken !== ''
210
- ? `${authorization}, Timestamp=${timestamp}, Token=${sessionToken}`
211
- : `${authorization}, Timestamp=${timestamp}`
225
+ requiredHeaders['Authorization'] = token
212
226
 
213
227
  return { ...requiredHeaders }
214
228
  }
@@ -225,3 +239,7 @@ export async function request(args: ICallContainerRequestInfo & { path: string }
225
239
 
226
240
  return await requester.request()
227
241
  }
242
+ function makeBearerToken(token: string): string {
243
+ const trimmed = token.trim()
244
+ return trimmed.startsWith('Bearer ') ? trimmed : `Bearer ${trimmed}`
245
+ }
@@ -1,3 +1,7 @@
1
+ import { ICloudBaseConfig } from '../../types'
2
+ import * as utils from '../utils/utils'
3
+ import { ERROR } from '../const/code'
4
+
1
5
  interface IErrorInfo {
2
6
  requestId?: string
3
7
  code?: string
@@ -81,3 +85,61 @@ const kEnvRuleReg = /^[a-z0-9_-]{1,40}$/
81
85
  export function isValidEnvFormat(env = '') {
82
86
  return typeof env === 'string' && kEnvRuleReg.test(env)
83
87
  }
88
+ export function normalizeConfig(config: ICloudBaseConfig) {
89
+ const { debug = false, secretId, secretKey, env, timeout = 15000, headers = {}, accessKey } = config
90
+
91
+ // 检查用户显示配置的 secretId 和 secretKey 是否成对出现,要么都有,要么都没有
92
+ if (!secretId !== !secretKey) {
93
+ throw utils.E({
94
+ ...ERROR.INVALID_PARAM,
95
+ message: 'secretId and secretKey must be a pair'
96
+ })
97
+ }
98
+ const cloudbaseConfigBase: ICloudBaseConfig = {
99
+ ...config,
100
+ debug,
101
+ // secretId,
102
+ // secretKey,
103
+ envName: env,
104
+ headers: { ...headers }, // 结构用户传进来的 headers,防止用户修改原对象
105
+ timeout
106
+ // accessKey: accessKey || process.env.CLOUDBASE_APIKEY
107
+ }
108
+ const {
109
+ TENCENTCLOUD_SECRETID,
110
+ TENCENTCLOUD_SECRETKEY,
111
+ TENCENTCLOUD_SESSIONTOKEN,
112
+ CLOUDBASE_APIKEY
113
+ } = process.env
114
+ // 如果用户显示配置了accessKey,取用户显示配置的 accessKey,优先级最高
115
+ if (accessKey) {
116
+ return Object.assign(cloudbaseConfigBase, { secretId: undefined, secretKey: undefined, accessKey })
117
+ }
118
+ // 显示配置了 secretId, secretKey,取 secretId, secretKey
119
+ if (secretId && secretKey) {
120
+ return Object.assign(cloudbaseConfigBase, { secretId, secretKey, accessKey: undefined })
121
+ }
122
+ // 下面从环境变量取 secretId, secretKey, accessKey
123
+ if (CLOUDBASE_APIKEY) {
124
+ return Object.assign(cloudbaseConfigBase, { secretId: undefined, secretKey: undefined, accessKey: CLOUDBASE_APIKEY })
125
+ }
126
+ if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
127
+ return Object.assign(cloudbaseConfigBase, { secretId: TENCENTCLOUD_SECRETID, secretKey: TENCENTCLOUD_SECRETKEY, sessionToken: TENCENTCLOUD_SESSIONTOKEN, accessKey: undefined })
128
+ }
129
+ if (config.context?.extendedContext) {
130
+ const extendedContext = config.context.extendedContext
131
+ if (!cloudbaseConfigBase.env) {
132
+ cloudbaseConfigBase.env = extendedContext.envId
133
+ cloudbaseConfigBase.envName = extendedContext.envId
134
+ }
135
+
136
+ // 从 context 中获取 secret
137
+ if (!cloudbaseConfigBase.secretId && !cloudbaseConfigBase.secretKey) {
138
+ cloudbaseConfigBase.secretId = extendedContext?.tmpSecret?.secretId
139
+ cloudbaseConfigBase.secretKey = extendedContext?.tmpSecret?.secretKey
140
+ cloudbaseConfigBase.sessionToken = extendedContext?.tmpSecret?.token
141
+ }
142
+ }
143
+ // 都没有配置,返回原始的配置
144
+ return cloudbaseConfigBase
145
+ }
package/types/index.d.ts CHANGED
@@ -196,6 +196,7 @@ export interface ICloudBaseConfig extends IKeyValue {
196
196
  version?: string
197
197
  credentials?: ICredentialsInfo
198
198
  region?: string
199
+ accessKey?: string
199
200
 
200
201
  // @cloudbase/functions-framework 函数上下文,只要求部分字段
201
202
  context?: Readonly<{