@cloudbase/node-sdk
Version:
tencent cloud base server sdk for node.js
283 lines (282 loc) • 10.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Request = void 0;
const tracing_1 = require("./tracing");
const utils = __importStar(require("./utils"));
const code_1 = require("../const/code");
const symbol_1 = require("../const/symbol");
const cloudbase_1 = require("../cloudbase");
const request_1 = __importDefault(require("./request"));
const requestHook_1 = require("./requestHook");
const getWxCloudApiToken_1 = require("./getWxCloudApiToken");
const signature_nodejs_1 = require("@cloudbase/signature-nodejs");
const url_1 = __importDefault(require("url"));
const { version } = require('../../package.json');
const { E, second, processReturn, getServerInjectUrl } = utils;
class Request {
constructor(args) {
this.defaultEndPoint = 'tcb-admin.tencentcloudapi.com';
this.inScfHost = 'tcb-admin.tencentyun.com';
// private openApiHost: string = 'tcb-open.tencentcloudapi.com'
this.urlPath = '/admin';
this.defaultTimeout = 15000;
this.timestamp = new Date().valueOf();
this.tracingInfo = tracing_1.generateTracingInfo();
this.args = args;
this.config = args.config;
}
/**
*
* 接口action
*/
getAction() {
const { params } = this.args;
const { action } = params;
return action;
}
/**
* 设置超时warning
*/
setSlowRequeryWarning(action) {
const { seqId } = this.tracingInfo;
const warnStr = `Your current request ${action ||
''} is longer than 3s, it may be due to the network or your query performance | [${seqId}]`;
// 暂针对数据库请求
const warnTimer = setTimeout(() => {
console.warn(warnStr);
}, 3000);
return warnTimer;
}
/**
* 构造params
*/
getParams() {
const args = this.args;
const config = this.config;
const { eventId } = this.tracingInfo;
let params = Object.assign(Object.assign({}, args.params), { envName: config.envName, eventId,
// wxCloudApiToken: process.env.WX_API_TOKEN || '',
wxCloudApiToken: getWxCloudApiToken_1.getWxCloudApiToken(),
// 对应服务端 wxCloudSessionToken
tcb_sessionToken: process.env.TCB_SESSIONTOKEN || '', sessionToken: config.sessionToken, sdk_version: version // todo 可去掉该参数
});
// 取当前云函数环境时,替换为云函数下环境变量
if (params.envName === symbol_1.SYMBOL_CURRENT_ENV) {
params.envName = process.env.TCB_ENV || process.env.SCF_NAMESPACE;
}
// 过滤value undefined
utils.filterUndefined(params);
return params;
}
/**
* 构造请求项
*/
makeReqOpts() {
// 校验密钥是否存在
this.validateSecretIdAndKey();
const config = this.config;
const args = this.args;
const url = this.getUrl();
const method = this.getMethod();
const params = this.getParams();
const opts = {
url,
method,
// 先取模块的timeout,没有则取sdk的timeout,还没有就使用默认值
// timeout: args.timeout || config.timeout || 15000,
timeout: this.getTimeout(),
// 优先取config,其次取模块,最后取默认
headers: this.getHeaders(),
proxy: config.proxy
};
if (config.forever === true) {
opts.forever = true;
}
if (args.method === 'post') {
if (args.isFormData) {
opts.formData = params;
opts.encoding = null;
}
else {
opts.body = params;
opts.json = true;
}
}
else {
opts.qs = params;
}
return opts;
}
/**
* 协议
*/
getProtocol() {
return this.config.isHttp === true ? 'http' : 'https';
}
/**
* 请求方法
*/
getMethod() {
return this.args.method || 'get';
}
/**
* 超时时间
*/
getTimeout() {
const { opts = {} } = this.args;
// timeout优先级 自定义接口timeout > config配置timeout > 默认timeout
return opts.timeout || this.config.timeout || this.defaultTimeout;
}
/**
* 获取
*/
/**
* 校验密钥和token是否存在
*/
validateSecretIdAndKey() {
const isInSCF = utils.checkIsInScf();
const { secretId, secretKey } = this.config;
if (!secretId || !secretKey) {
// 用户init未传入密钥对,读process.env
const envSecretId = process.env.TENCENTCLOUD_SECRETID;
const envSecretKey = process.env.TENCENTCLOUD_SECRETKEY;
const sessionToken = process.env.TENCENTCLOUD_SESSIONTOKEN;
if (!envSecretId || !envSecretKey) {
if (isInSCF) {
throw E(Object.assign(Object.assign({}, code_1.ERROR.INVALID_PARAM), { message: 'missing authoration key, redeploy the function' }));
}
else {
throw E(Object.assign(Object.assign({}, code_1.ERROR.INVALID_PARAM), { message: 'missing secretId or secretKey of tencent cloud' }));
}
}
else {
this.config = Object.assign(Object.assign({}, this.config), { secretId: envSecretId, secretKey: envSecretKey, sessionToken: sessionToken });
return;
}
}
}
/**
*
* 获取headers 此函数中设置authorization
*/
getHeaders() {
const config = this.config;
const { secretId, secretKey } = config;
const args = this.args;
const method = this.getMethod();
const isInSCF = utils.checkIsInScf();
// Note: 云函数被调用时可能调用端未传递 SOURCE,TCB_SOURCE 可能为空
const TCB_SOURCE = process.env.TCB_SOURCE || '';
const SOURCE = isInSCF ? `${TCB_SOURCE},scf` : ',not_scf';
const url = this.getUrl();
// 默认
let requiredHeaders = {
'User-Agent': `tcb-node-sdk/${version}`,
'x-tcb-source': SOURCE,
'x-client-timestamp': this.timestamp,
'X-SDK-Version': `tcb-node-sdk/${version}`,
Host: url_1.default.parse(url).host
};
if (config.version) {
requiredHeaders['X-SDK-Version'] = config.version;
}
requiredHeaders = Object.assign(Object.assign(Object.assign({}, config.headers), args.headers), requiredHeaders);
const params = this.getParams();
const { authorization, timestamp } = signature_nodejs_1.sign({
secretId: secretId,
secretKey: secretKey,
method: method,
url: url,
params: params,
headers: requiredHeaders,
withSignedParams: true,
timestamp: second() - 1
});
requiredHeaders['Authorization'] = authorization;
requiredHeaders['X-Signature-Expires'] = 600;
requiredHeaders['X-Timestamp'] = timestamp;
return Object.assign({}, requiredHeaders);
}
/**
* 获取url
* @param action
*/
getUrl() {
const protocol = this.getProtocol();
const isInSCF = utils.checkIsInScf();
const { eventId, seqId } = this.tracingInfo;
const { customApiUrl } = this.args;
const { serviceUrl } = this.config;
const serverInjectUrl = getServerInjectUrl();
const defaultUrl = isInSCF
? `http://${this.inScfHost}${this.urlPath}`
: `${protocol}://${this.defaultEndPoint}${this.urlPath}`;
let url = serviceUrl || serverInjectUrl || customApiUrl || defaultUrl;
let urlQueryStr = `&eventId=${eventId}&seqId=${seqId}`;
const scfContext = cloudbase_1.CloudBase.scfContext;
if (scfContext) {
urlQueryStr = `&eventId=${eventId}&seqId=${seqId}&scfRequestId=${scfContext.request_id}`;
}
if (url.includes('?')) {
url = `${url}${urlQueryStr}`;
}
else {
url = `${url}?${urlQueryStr}`;
}
return url;
}
}
exports.Request = Request;
// 业务逻辑都放在这里处理
exports.default = async (args) => {
const req = new Request(args);
const reqOpts = req.makeReqOpts();
const config = args.config;
const action = req.getAction();
let reqHooks;
let warnTimer = null;
if (action === 'wx.openApi' || action === 'wx.wxPayApi') {
reqHooks = {
handleData: requestHook_1.handleWxOpenApiData
};
}
if (action.indexOf('database') >= 0) {
warnTimer = req.setSlowRequeryWarning(action);
}
try {
const res = await request_1.default(reqOpts, reqHooks);
// 检查res是否为return {code, message}回包
if (res.code) {
// 判断是否设置config._returnCodeByThrow = false
return processReturn(config.throwOnCode, res);
}
return res;
}
finally {
if (warnTimer) {
clearTimeout(warnTimer);
}
}
};