feat: change dir
5
.gitignore
vendored
@ -8,7 +8,10 @@ dist/
|
||||
/release
|
||||
*.js
|
||||
*.js.map
|
||||
!core/market/browser/**/*.js
|
||||
!src/core/api-manager/browser/**/*.js
|
||||
!src/core/market/browser/**/*.js
|
||||
!src/core/market/browser/dist/icon.png
|
||||
!src/core/api-manager/browser/dist/assets/images/icon.png
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
@ -64,7 +64,6 @@ npm install -g @angular/cli
|
||||
| Command | Description |
|
||||
| ------------------------ | -------------------------------------------------------------------- |
|
||||
| `npm start` | In development mode, running on browser and desktop at the same time |
|
||||
| `npm run ng:serve` | only runs in the browser |
|
||||
| `npm run electron:serve` | only runs in the desktop |
|
||||
|
||||
### Build
|
||||
|
@ -1,509 +0,0 @@
|
||||
/**
|
||||
* @name 返回通用方法
|
||||
* @author Eoapi
|
||||
*/
|
||||
let _LIB_WORKER_THREAD = require('./exec_worker_thread');
|
||||
let CryptoJS = require('crypto-js');
|
||||
let privateFun = {},
|
||||
_LibsCommon = require('./common'),
|
||||
_LibsEncrypt = require('./encrypt').core,
|
||||
_Xml_Class = new (require('./xml').core)();
|
||||
const DOMAIN_CONSTANT = require('../domain.json');
|
||||
const DOMAIN_REGEX =
|
||||
'(^((http|wss|ws|ftp|https)://))|(^(((http|wss|ws|ftp|https)://)|)(([\\w\\-_]+([\\w\\-\\.]*)?(\\.(' +
|
||||
DOMAIN_CONSTANT.join('|') +
|
||||
')))|((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(localhost))((\\/)|(\\?)|(:)|($)))';
|
||||
const TIMINGSUMMARY = {
|
||||
NS_PER_SEC: 1e9,
|
||||
MS_PER_NS: 1e6,
|
||||
};
|
||||
const { NodeVM } = require('./vm2/index');
|
||||
let querystring = require('querystring');
|
||||
/**
|
||||
* @desc 重置env
|
||||
* @param {object} inputSanboxVar 沙箱中的env变量
|
||||
* @param {object} inputBaiscEnv 基础的env
|
||||
*/
|
||||
privateFun.resetEnv = (inputBaiscEnv, inputSanboxVar) => {
|
||||
let tmpResult = Object.assign({}, inputBaiscEnv);
|
||||
tmpResult.envParam = _LibsCommon.deepCopy(inputSanboxVar.envParam);
|
||||
['http'].map((val) => {
|
||||
tmpResult[val] = {};
|
||||
for (let itemKey in inputSanboxVar[val]) {
|
||||
if (
|
||||
['extraFormDataParam', 'queryParam', 'headerParam', 'baseUrlParam', 'requestScript', 'responseScript'].indexOf(
|
||||
itemKey
|
||||
) > -1
|
||||
) {
|
||||
tmpResult[val][itemKey] = inputSanboxVar[val][itemKey];
|
||||
}
|
||||
}
|
||||
});
|
||||
return tmpResult;
|
||||
};
|
||||
privateFun.getMicrosToMs = (inputStartTime, inputEndTime) => {
|
||||
if (inputStartTime === undefined || inputEndTime === undefined) return 0.0;
|
||||
let tmpSecondDiff = inputEndTime[0] - inputStartTime[0];
|
||||
let tmpNanoSecondDiff = inputEndTime[1] - inputStartTime[1];
|
||||
let tmpDiffInNanoSecond = tmpSecondDiff * TIMINGSUMMARY.NS_PER_SEC + tmpNanoSecondDiff;
|
||||
let tmpOutput = tmpDiffInNanoSecond / TIMINGSUMMARY.MS_PER_NS;
|
||||
if (tmpOutput < 0) {
|
||||
return 0.0;
|
||||
} else {
|
||||
return tmpOutput;
|
||||
}
|
||||
};
|
||||
privateFun.getHttpTiming = (timingSummary) => {
|
||||
return {
|
||||
dnsTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.startAt, timingSummary.dnsTiming),
|
||||
tcpTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.dnsTiming || timingSummary.startAt, timingSummary.tcpTiming),
|
||||
tlsTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.tcpTiming, timingSummary.tlsTiming),
|
||||
requestSentTiming: _LibsEncrypt.getMicrosToMsStr(
|
||||
timingSummary.tlsTiming || timingSummary.tcpTiming,
|
||||
timingSummary.firstByteTiming
|
||||
),
|
||||
firstByteTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.startAt, timingSummary.firstByteTiming),
|
||||
contentDeliveryTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.firstByteTiming, timingSummary.endAt),
|
||||
responseTiming: _LibsEncrypt.getMicrosToMsStr(timingSummary.startAt, timingSummary.endAt),
|
||||
};
|
||||
};
|
||||
privateFun.getBaiscEoFn = (inputSanboxVar, inputEnv = {}) => {
|
||||
let tmpResult = {
|
||||
env: {
|
||||
envParam: inputEnv.envParam,
|
||||
},
|
||||
};
|
||||
['http', 'websocket', 'socket', 'rpc'].map((val) => {
|
||||
tmpResult.env[val] = _LibsCommon.deepCopy(inputEnv[val]) || {};
|
||||
});
|
||||
return tmpResult;
|
||||
};
|
||||
privateFun.setExecWorkerThread = (inputPostMsg, inputMsgCallback) => {
|
||||
return new _LIB_WORKER_THREAD.core(inputPostMsg, inputMsgCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc 主要用于UI脚本中公用函数补全
|
||||
* @param {*} inputSanboxVar 沙盒变量
|
||||
* @param {*} inputEnv 环境
|
||||
* @param {*} inputOpts 可选配置项,主要结构需要(globalHeader:全局头部)
|
||||
*/
|
||||
privateFun.constructUiCodeBasicFn = (inputSanboxVar, inputEnv, inputOpts = {}) => {
|
||||
inputOpts = inputOpts || {};
|
||||
let tmpResult = Object.assign({}, inputSanboxVar.eo, privateFun.getBaiscEoFn(inputSanboxVar, inputEnv));
|
||||
tmpResult.env['http'] = _LibsCommon.deepCopy(inputEnv['http']) || {};
|
||||
return tmpResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc 构造各种类型的sanbox结构
|
||||
* @param {object} inputSanboxVar 沙箱中的变量
|
||||
* @param {object} inputInitialData 初始化的变量集合
|
||||
* @param {boolean} inputIsResponse 是否为返回信息
|
||||
*/
|
||||
privateFun.setTypesRefFns = (inputSanboxVar, inputInitialData, inputIsResponse) => {
|
||||
let tmpTypes = ['http', 'socket', 'rpc', 'websocket'],
|
||||
tmpBasicConf = {
|
||||
apiUrl: (inputInitialData.url || '').split('?')[0],
|
||||
bodyParam: inputInitialData.raw || '',
|
||||
bodyParseParam: inputInitialData.params || {},
|
||||
queryParam: inputInitialData.query || {},
|
||||
headerParam: inputInitialData.headers || {},
|
||||
restParam: inputInitialData.rest || {},
|
||||
responseParam: inputInitialData.response || '',
|
||||
responseHeaderParam: inputInitialData.responseHeaders || {},
|
||||
};
|
||||
tmpTypes.map((val) => {
|
||||
inputSanboxVar[val] = _LibsCommon.deepCopy(tmpBasicConf);
|
||||
inputSanboxVar[val].url = {
|
||||
parse() {
|
||||
return privateFun.parseRealSendUrl(
|
||||
{
|
||||
baseUrlParam: inputSanboxVar[val].baseUrlParam,
|
||||
queryParam: inputSanboxVar[val].queryParam,
|
||||
apiUrl: inputSanboxVar[val].apiUrl,
|
||||
restParam: inputSanboxVar[val].restParam,
|
||||
},
|
||||
{
|
||||
baseUrlParam: inputSanboxVar.env[val].baseUrlParam,
|
||||
queryParam: inputSanboxVar.env[val].queryParam,
|
||||
envParam: inputSanboxVar.env.envParam,
|
||||
}
|
||||
);
|
||||
},
|
||||
get: () => {
|
||||
return inputSanboxVar[val].apiUrl;
|
||||
},
|
||||
set: (inputVal) => {
|
||||
inputSanboxVar[val].apiUrl = inputVal;
|
||||
},
|
||||
};
|
||||
inputSanboxVar[val].query = {
|
||||
get: (inputKey) => {
|
||||
return inputSanboxVar[val].queryParam[inputKey];
|
||||
},
|
||||
set: (inputKey, inputVal) => {
|
||||
inputSanboxVar[val].queryParam[inputKey] = inputVal;
|
||||
},
|
||||
unset: (inputKey) => {
|
||||
delete inputSanboxVar[val].queryParam[inputKey];
|
||||
},
|
||||
clear: () => {
|
||||
inputSanboxVar[val].queryParam = {};
|
||||
},
|
||||
};
|
||||
inputSanboxVar[val].header = {
|
||||
get: (inputKey) => {
|
||||
return inputSanboxVar[val].headerParam[inputKey];
|
||||
},
|
||||
set: (inputKey, inputVal) => {
|
||||
inputSanboxVar[val].headerParam[inputKey] = inputVal;
|
||||
},
|
||||
unset: (inputKey) => {
|
||||
delete inputSanboxVar[val].headerParam[inputKey];
|
||||
},
|
||||
clear: () => {
|
||||
inputSanboxVar[val].headerParam = {};
|
||||
},
|
||||
};
|
||||
inputSanboxVar[val].rest = {
|
||||
get: (inputKey) => {
|
||||
return inputSanboxVar[val].restParam[inputKey];
|
||||
},
|
||||
set: (inputKey, inputVal) => {
|
||||
inputSanboxVar[val].restParam[inputKey] = inputVal;
|
||||
},
|
||||
unset: (inputKey) => {
|
||||
delete inputSanboxVar[val].restParam[inputKey];
|
||||
},
|
||||
clear: () => {
|
||||
inputSanboxVar[val].restParam = {};
|
||||
},
|
||||
};
|
||||
if (inputIsResponse) {
|
||||
inputSanboxVar[val].response = {
|
||||
get: () => {
|
||||
return inputSanboxVar[val].responseParam;
|
||||
},
|
||||
set: (inputVal) => {
|
||||
inputSanboxVar[val].responseParam = inputVal;
|
||||
},
|
||||
};
|
||||
inputSanboxVar[val].responseHeader = {
|
||||
get: (inputKey) => {
|
||||
return inputSanboxVar[val].responseHeaderParam[inputKey];
|
||||
},
|
||||
set: (inputKey, inputVal) => {
|
||||
inputSanboxVar[val].responseHeaderParam[inputKey] = inputVal;
|
||||
},
|
||||
unset: (inputKey) => {
|
||||
delete inputSanboxVar[val].responseHeaderParam[inputKey];
|
||||
},
|
||||
clear: () => {
|
||||
inputSanboxVar[val].responseHeaderParam = {};
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @desc 构造各种类型的sanbox结构
|
||||
* @param {object} inputSanboxVar 沙箱中的变量
|
||||
* @param {object} inputInitialData 初始化的变量集合
|
||||
* @param {boolean} inputIsResponse 是否为返回信息
|
||||
*/
|
||||
privateFun.setTypesRefFns = (inputSanboxVar, inputInitialData, inputIsResponse) => {
|
||||
let tmpTypes = ['http'],
|
||||
tmpBasicConf = {
|
||||
apiUrl: (inputInitialData.url || '').split('?')[0],
|
||||
bodyParam: inputInitialData.raw || '',
|
||||
bodyParseParam: inputInitialData.params || {},
|
||||
queryParam: inputInitialData.query || {},
|
||||
headerParam: inputInitialData.headers || {},
|
||||
restParam: inputInitialData.rest || {},
|
||||
responseParam: inputInitialData.response || '',
|
||||
responseHeaderParam: inputInitialData.responseHeaders || {},
|
||||
};
|
||||
tmpTypes.map((val) => {
|
||||
inputSanboxVar[val] = _LibsCommon.deepCopy(tmpBasicConf);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 前置脚本代码
|
||||
* @param {string} inputData 请求可分别赋值信息
|
||||
* @param {string} inputScript 前置脚本代码
|
||||
* @param {object} inputOpts options
|
||||
* @return {object} 前置组合请求信息
|
||||
*/
|
||||
privateFun.parseBeforeCode = function (inputData, inputScript, inputOpts = {}) {
|
||||
let tmpBasicEnv = inputData.env || _LibsCommon.parseEnv(),
|
||||
tmpApiType = inputOpts.type || 'http';
|
||||
inputData = JSON.parse(JSON.stringify(inputData));
|
||||
|
||||
let tmpReportList = [],
|
||||
tmpBinary = inputData.binary,
|
||||
tmpSanboxObj = {
|
||||
requestBody: inputData.requestBody || {},
|
||||
requestHeaders: inputData.requestHeaders || {},
|
||||
restParams: inputData.restParams || {},
|
||||
queryParams: inputData.queryParams || {},
|
||||
responseHeaders: inputData.responseHeaders || {},
|
||||
response: inputData.response || {},
|
||||
CryptoJS: CryptoJS,
|
||||
eo: {},
|
||||
};
|
||||
const tmpVm = new NodeVM({
|
||||
sandbox: tmpSanboxObj,
|
||||
require: {
|
||||
external: true,
|
||||
builtin: ['crypto'],
|
||||
},
|
||||
}),
|
||||
tmpCodeEvalObj = tmpVm._context;
|
||||
tmpCodeEvalObj.eo = privateFun.constructUiCodeBasicFn(tmpCodeEvalObj, tmpBasicEnv, inputOpts);
|
||||
privateFun.setTypesRefFns(tmpCodeEvalObj.eo, inputData);
|
||||
let tmpTargetTypeData = tmpCodeEvalObj.eo[tmpApiType],
|
||||
tmpTargetTypeEnv = tmpCodeEvalObj.eo.env[tmpApiType];
|
||||
let tmpOutput = {
|
||||
status: 'finish',
|
||||
url: tmpTargetTypeData.apiUrl,
|
||||
headers: {},
|
||||
params: null,
|
||||
env: privateFun.resetEnv(tmpBasicEnv, tmpCodeEvalObj.eo.env),
|
||||
reportList: tmpReportList,
|
||||
},
|
||||
tmpParams,
|
||||
tmpHeaders;
|
||||
if (inputData.isReturnSoonWhenExecCode) return tmpOutput;
|
||||
try {
|
||||
let tmp_query_param_obj = Object.assign({}, tmpTargetTypeEnv.queryParam, tmpTargetTypeData.queryParam);
|
||||
tmpHeaders = Object.assign({}, tmpTargetTypeEnv.headerParam, tmpTargetTypeData.headerParam);
|
||||
switch (inputData.requestType.toString()) {
|
||||
case '0': {
|
||||
tmpParams = _LibsCommon.mergeObj(tmpTargetTypeData.bodyParseParam, tmpTargetTypeEnv.extraFormDataParam);
|
||||
break;
|
||||
}
|
||||
case '2': {
|
||||
if (/^\[/.test(tmpTargetTypeData.bodyParam)) {
|
||||
tmpParams = JSON.stringify([JSON.parse(tmpTargetTypeData.bodyParam)[0]]);
|
||||
} else {
|
||||
tmpParams = tmpTargetTypeData.bodyParam;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '3': {
|
||||
/**
|
||||
* @desc 去除xml自动补全额外参数功能
|
||||
*/
|
||||
|
||||
tmpParams = _Xml_Class.jsonToXml()(tmpTargetTypeData.bodyParseParam, inputData.xmlAttrObj);
|
||||
break;
|
||||
}
|
||||
case '1': {
|
||||
tmpParams =
|
||||
typeof tmpTargetTypeData.bodyParam === 'string'
|
||||
? tmpTargetTypeData.bodyParam
|
||||
: JSON.stringify(tmpTargetTypeData.bodyParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let tmpEnvGlobals = Object.assign({}, global.eoTestGlobals || {}, tmpCodeEvalObj.eo.env.envParam || {});
|
||||
for (let key in tmpEnvGlobals) {
|
||||
let val = tmpEnvGlobals[key];
|
||||
let templateParamObject = {};
|
||||
let templateHeaderObject = {};
|
||||
for (let tmp_query_param_key in tmp_query_param_obj) {
|
||||
let tmp_query_param_val = _LibsCommon.replaceAll(
|
||||
'{{' + key + '}}',
|
||||
val || '',
|
||||
tmp_query_param_obj[tmp_query_param_key]
|
||||
);
|
||||
delete tmp_query_param_obj[tmp_query_param_key];
|
||||
tmp_query_param_obj[_LibsCommon.replaceAll('{{' + key + '}}', val || '', tmp_query_param_key)] =
|
||||
tmp_query_param_val;
|
||||
}
|
||||
tmpOutput.url = _LibsCommon.replaceAll('{{' + key + '}}', val || '', tmpOutput.url);
|
||||
for (let childKey in tmpHeaders) {
|
||||
tmpHeaders[childKey] = _LibsCommon.replaceAll('{{' + key + '}}', val, tmpHeaders[childKey]);
|
||||
if (childKey.indexOf('{{' + key + '}}') > -1) {
|
||||
templateHeaderObject[_LibsCommon.replaceAll('{{' + key + '}}', val, childKey)] = tmpHeaders[childKey];
|
||||
} else {
|
||||
templateHeaderObject[childKey] = tmpHeaders[childKey];
|
||||
}
|
||||
}
|
||||
tmpHeaders = templateHeaderObject;
|
||||
if (!tmpBinary) {
|
||||
switch (typeof tmpParams) {
|
||||
case 'string': {
|
||||
tmpParams = _LibsCommon.replaceAll('{{' + key + '}}', val, tmpParams);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
for (let childKey in tmpParams) {
|
||||
switch (typeof tmpParams[childKey]) {
|
||||
case 'string': {
|
||||
tmpParams[childKey] = _LibsCommon.replaceAll('{{' + key + '}}', val, tmpParams[childKey]);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
for (let grandSonKey in tmpParams[childKey]) {
|
||||
let grandSonVal = tmpParams[childKey][grandSonKey];
|
||||
switch (typeof grandSonVal) {
|
||||
case 'string': {
|
||||
tmpParams[childKey][grandSonKey] = _LibsCommon.replaceAll('{{' + key + '}}', val, grandSonVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (childKey.indexOf('{{' + key + '}}') > -1) {
|
||||
let tmpHadReplaceString = _LibsCommon.replaceAll('{{' + key + '}}', val, childKey);
|
||||
templateParamObject[tmpHadReplaceString] = tmpParams[childKey];
|
||||
if (tmpParams[tmpHadReplaceString]) {
|
||||
switch (_LibsCommon.getTypeOfVar(templateParamObject[tmpHadReplaceString])) {
|
||||
case 'Array': {
|
||||
if (_LibsCommon.getTypeOfVar(tmpParams[tmpHadReplaceString]) == 'Array') {
|
||||
templateParamObject[tmpHadReplaceString] = templateParamObject[tmpHadReplaceString].concat(
|
||||
tmpParams[tmpHadReplaceString]
|
||||
);
|
||||
} else {
|
||||
templateParamObject[tmpHadReplaceString] = templateParamObject[tmpHadReplaceString].push(
|
||||
tmpParams[tmpHadReplaceString]
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (_LibsCommon.getTypeOfVar(tmpParams[tmpHadReplaceString]) == 'Array') {
|
||||
templateParamObject[tmpHadReplaceString] = tmpParams[tmpHadReplaceString].push(
|
||||
templateParamObject[tmpHadReplaceString]
|
||||
);
|
||||
} else {
|
||||
templateParamObject[tmpHadReplaceString] = [
|
||||
templateParamObject[tmpHadReplaceString],
|
||||
tmpParams[tmpHadReplaceString],
|
||||
];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
templateParamObject[childKey] = tmpParams[childKey];
|
||||
}
|
||||
}
|
||||
tmpParams = templateParamObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpOutput.headers = tmpHeaders;
|
||||
tmpOutput.queryParams = tmp_query_param_obj;
|
||||
let queryString = querystring.stringify(tmpOutput.queryParams);
|
||||
tmpOutput.url += queryString ? '?' + queryString : '';
|
||||
for (let key in tmpTargetTypeData.restParam) {
|
||||
tmpOutput.url = privateFun.replaceRestParam(key, tmpTargetTypeData.restParam[key], tmpOutput.url);
|
||||
}
|
||||
if (tmpBinary) {
|
||||
tmpOutput.params = {};
|
||||
} else {
|
||||
tmpOutput.params = tmpParams;
|
||||
}
|
||||
if (!new RegExp(DOMAIN_REGEX).test(tmpOutput.url)) {
|
||||
tmpOutput.url = (tmpTargetTypeEnv.baseUrlParam || '') + tmpOutput.url;
|
||||
}
|
||||
if (!/"content-type":/i.test(JSON.stringify(tmpOutput.headers))) {
|
||||
switch (inputData.requestType.toString()) {
|
||||
case '0': {
|
||||
tmpOutput.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
break;
|
||||
}
|
||||
case '2': {
|
||||
tmpOutput.headers['Content-Type'] = 'application/json';
|
||||
break;
|
||||
}
|
||||
case '3': {
|
||||
tmpOutput.headers['Content-Type'] = 'application/xml';
|
||||
break;
|
||||
}
|
||||
case '4': {
|
||||
if (/(data:)(.*)(;base64),/.test(tmpBinary)) {
|
||||
tmpOutput.headers['Content-Type'] = RegExp.$2;
|
||||
} else {
|
||||
tmpOutput.headers['Content-Type'] = 'false';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(new Date() + ':libs/common.js 217:', e);
|
||||
}
|
||||
return tmpOutput;
|
||||
};
|
||||
/**
|
||||
* 后置脚本代码
|
||||
* @param {string} inputData 返回结果信息
|
||||
* @param {string} inputScript 后置脚本代码
|
||||
* @param {object} inputEnv env
|
||||
* @param {object} inputOpts options
|
||||
* @return {object} 后置组合请求信息
|
||||
*/
|
||||
privateFun.parseAfterCode = function (inputData, inputScript, inputEnv, inputOpts = {}) {
|
||||
let tmpReportList = [],
|
||||
tmpApiType = inputOpts.type || 'http',
|
||||
tmpBasicEnv = inputEnv || _LibsCommon.parseEnv();
|
||||
let tmpStatus, tmpErrorContent; //不可删,与提示预警有关
|
||||
let tmpBindObj = (inputOpts || {}).bindObj || {};
|
||||
const tmpVm = new NodeVM({
|
||||
sandbox: {
|
||||
CryptoJS: CryptoJS,
|
||||
db_result: inputOpts.dbResult || {},
|
||||
eo: {},
|
||||
requestBody: tmpBindObj.requestBody || {},
|
||||
requestHeaders: tmpBindObj.requestHeaders || {},
|
||||
restParams: tmpBindObj.restParams || {},
|
||||
queryParams: tmpBindObj.queryParams || {},
|
||||
response: tmpBindObj.response || {},
|
||||
responseHeaders: (inputOpts || {}).responseHeaders,
|
||||
},
|
||||
require: {
|
||||
external: true,
|
||||
builtin: ['crypto'],
|
||||
},
|
||||
}),
|
||||
tmpCodeEvalObj = tmpVm._context;
|
||||
tmpCodeEvalObj.eo = privateFun.constructUiCodeBasicFn(tmpCodeEvalObj, tmpBasicEnv, inputOpts);
|
||||
privateFun.setTypesRefFns(
|
||||
tmpCodeEvalObj.eo,
|
||||
Object.assign({}, inputOpts, {
|
||||
response: inputData,
|
||||
}),
|
||||
true
|
||||
);
|
||||
let tmpTargetTypeData = tmpCodeEvalObj.eo[tmpApiType];
|
||||
return {
|
||||
status: 'finish',
|
||||
content: tmpTargetTypeData.responseParam,
|
||||
env: privateFun.resetEnv(tmpBasicEnv, tmpCodeEvalObj.eo.env),
|
||||
reportList: tmpReportList,
|
||||
};
|
||||
};
|
||||
privateFun.requestPreReduceByPromise = (inputData, inputCode, inputOptions) => {
|
||||
return new Promise((resolve) => {
|
||||
let tmpResponse = privateFun.parseBeforeCode(inputData, inputCode, inputOptions);
|
||||
resolve(tmpResponse);
|
||||
});
|
||||
};
|
||||
privateFun.responsePreReduceByPromise = (inputData, inputCode, inputEnv, inputOptions) => {
|
||||
return new Promise((resolve) => {
|
||||
let tmpResponse = privateFun.parseAfterCode(inputData, inputCode, inputEnv, inputOptions);
|
||||
resolve(tmpResponse);
|
||||
});
|
||||
};
|
||||
exports.getMicrosToMs = privateFun.getMicrosToMs;
|
||||
exports.getHttpTiming = privateFun.getHttpTiming;
|
||||
exports.requestPreReduceByPromise = privateFun.requestPreReduceByPromise;
|
||||
exports.responsePreReduceByPromise = privateFun.responsePreReduceByPromise;
|
@ -1,187 +0,0 @@
|
||||
/**
|
||||
* @name 通用方法
|
||||
* @author EOAPI
|
||||
*/
|
||||
'use strict';
|
||||
let _LibsDataConstructor = new (require('./data_constructor').core)();
|
||||
let xml2json = require('xml2js');
|
||||
let privateFun = {};
|
||||
const LOCAL_REGEXP_CONST = 'eoundefined$';
|
||||
privateFun.deepCopy = (inputObject) => {
|
||||
try {
|
||||
return JSON.parse(JSON.stringify(inputObject));
|
||||
} catch (JSON_STRINGIFY_ERROR) {
|
||||
return inputObject;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @desc 解析请求信息,组合成合适的对象
|
||||
* @param [object] inputData 原始待组合对象
|
||||
* @return [object]
|
||||
*/
|
||||
privateFun.parseRequestDataToObj = (inputData) => {
|
||||
let tmpOutputObj = {
|
||||
restParams: inputData.restParams,
|
||||
queryParams: inputData.queryParams,
|
||||
requestBody: null,
|
||||
},
|
||||
tmpRequestBody = inputData.requestBody.body;
|
||||
try {
|
||||
switch (inputData.requestType) {
|
||||
case '2': {
|
||||
tmpRequestBody = JSON.parse(tmpRequestBody);
|
||||
break;
|
||||
}
|
||||
case '3': {
|
||||
xml2json.parseString(
|
||||
tmpRequestBody,
|
||||
{
|
||||
explicitArray: false,
|
||||
ignoreAttrs: true,
|
||||
},
|
||||
function (error, result) {
|
||||
if (!error) {
|
||||
tmpRequestBody = result;
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
case '1': {
|
||||
tmpOutputObj.raw = tmpRequestBody;
|
||||
tmpRequestBody = {
|
||||
raw: tmpRequestBody,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case '4': {
|
||||
tmpOutputObj.binary = tmpRequestBody;
|
||||
tmpRequestBody = {
|
||||
binary: tmpRequestBody,
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (PARSE_REQUEST_BODY_DATA_ERR) {
|
||||
console.error(new Date() + ':PARSE_REQUEST_BODY_DATA_ERR::', PARSE_REQUEST_BODY_DATA_ERR);
|
||||
}
|
||||
tmpOutputObj.requestBody = tmpRequestBody;
|
||||
return tmpOutputObj;
|
||||
};
|
||||
privateFun.bodyQueryToJson = function (inputArray, inputOptions) {
|
||||
inputOptions = inputOptions || {
|
||||
apiRequestParamJsonType: 0
|
||||
}
|
||||
let tmpXmlAttrObj={};
|
||||
let tmpJsonObj=_LibsDataConstructor.eo_define_arr_to_json(inputArray, {},inputOptions,tmpXmlAttrObj);
|
||||
if(inputOptions.isXml){
|
||||
return {
|
||||
value:JSON.stringify(tmpJsonObj),
|
||||
attr:tmpXmlAttrObj
|
||||
}
|
||||
}
|
||||
if ((inputOptions.apiRequestParamJsonType || 0).toString() == '1') {
|
||||
return JSON.stringify([tmpJsonObj]).replace(/("eo_big_int_)(((?!").)*)(")/g,"$2");
|
||||
} else {
|
||||
return JSON.stringify(tmpJsonObj).replace(/("eo_big_int_)(((?!").)*)(")/g,"$2");
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 解析环境变量
|
||||
* @param {array} env 环境变量
|
||||
* @return object 返回环境
|
||||
*/
|
||||
privateFun.parseEnv = function (env) {
|
||||
env = env || {};
|
||||
//设置全局的配置:环境变量、全局脚本、环境ID、环境名称
|
||||
let tmpConf = {
|
||||
envID: env.envID || 0,
|
||||
envName: env.envName || '',
|
||||
envParam: {},
|
||||
startup: env.globalBeforeProcess || '',
|
||||
teardown: env.globalAfterProcess || '',
|
||||
envAuth: env.envAuth || {
|
||||
status: '0',
|
||||
},
|
||||
};
|
||||
//处理全局变量
|
||||
try {
|
||||
for (let val of env.paramList) {
|
||||
if (val.paramKey)
|
||||
tmpConf.envParam[val.paramKey] = JSON.stringify(val.paramValue || '')
|
||||
.replace(/^"/, '')
|
||||
.replace(/"$/, '');
|
||||
}
|
||||
} catch (MAP_ERR) {}
|
||||
//轮询协议,设置协议配置
|
||||
let tmpProtocolRef = ['http', 'socket', 'websocket', 'rpc'],
|
||||
tmpIsLessThan780 = !env.hasOwnProperty('socket');
|
||||
let tmpBuildArr = [
|
||||
{
|
||||
origin: 'additionalParamList',
|
||||
target: 'extraFormDataParam',
|
||||
key: 'paramKey',
|
||||
value: 'paramValue',
|
||||
},
|
||||
{
|
||||
origin: 'urlParamList',
|
||||
target: 'queryParam',
|
||||
key: 'paramKey',
|
||||
value: 'paramValue',
|
||||
},
|
||||
{
|
||||
origin: 'headerList',
|
||||
target: 'headerParam',
|
||||
key: 'headerName',
|
||||
value: 'headerValue',
|
||||
},
|
||||
];
|
||||
for (let key of tmpProtocolRef) {
|
||||
let tmpEnvItem = (tmpIsLessThan780 || key === 'http' ? env : env[key]) || {};
|
||||
let tmpItem = {
|
||||
baseUrlParam: tmpEnvItem.host || tmpEnvItem.frontURI || '',
|
||||
headerParam: {},
|
||||
extraFormDataParam: {},
|
||||
queryParam: {},
|
||||
requestScript: tmpEnvItem.beforeInject || '',
|
||||
responseScript: tmpEnvItem.afterInject || '',
|
||||
};
|
||||
if (tmpEnvItem.hasOwnProperty('connectInject')) {
|
||||
tmpItem.connectInject = tmpEnvItem.connectInject || '';
|
||||
}
|
||||
tmpBuildArr.map((item) => {
|
||||
if (tmpEnvItem[item.origin]) {
|
||||
tmpEnvItem[item.origin].map((val) => {
|
||||
if (val[item.key]) tmpItem[item.target][val[item.key]] = val[item.value] || '';
|
||||
});
|
||||
}
|
||||
});
|
||||
tmpConf[key] = tmpItem;
|
||||
}
|
||||
return tmpConf;
|
||||
};
|
||||
/**
|
||||
* merge对象数据
|
||||
* @param {object} inputTargetItem 目标对象
|
||||
* @param {object} inputSourceItem 源对象
|
||||
* @returns {object} 已合并输出对象
|
||||
*/
|
||||
privateFun.mergeObj = (inputTargetItem, inputSourceItem) => {
|
||||
let tmpOutputObj = privateFun.deepCopy(inputTargetItem);
|
||||
for (let key in inputSourceItem) {
|
||||
if (tmpOutputObj[key] || tmpOutputObj[key] === 0 || tmpOutputObj[key] === null || tmpOutputObj[key] === false)
|
||||
continue;
|
||||
tmpOutputObj[key] = inputSourceItem[key];
|
||||
}
|
||||
return tmpOutputObj;
|
||||
};
|
||||
exports.mergeObj = privateFun.mergeObj;
|
||||
exports.parseEnv = privateFun.parseEnv;
|
||||
exports.deepCopy = privateFun.deepCopy;
|
||||
exports.parseRequestDataToObj = privateFun.parseRequestDataToObj;
|
||||
exports.bodyQueryToJson = privateFun.bodyQueryToJson;
|
||||
exports.LOCAL_REGEXP_CONST=LOCAL_REGEXP_CONST;
|
||||
exports.replaceAll = function () {
|
||||
return _LibsDataConstructor.text_replace_all(...arguments);
|
||||
};
|
@ -1,215 +0,0 @@
|
||||
(() => {
|
||||
'use strict';
|
||||
/**
|
||||
* @name 信息构造器类
|
||||
* @author Eoapi
|
||||
*/
|
||||
class main {
|
||||
constructor() {
|
||||
this.DEFAULT_REFS_FROM_EO_TYPE = {
|
||||
"8": "false",
|
||||
"12": "[]",
|
||||
"13": "{}",
|
||||
"14": "0",
|
||||
"15": "null"
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @desc eolinker自定义格式转换为json
|
||||
* @param {array} input_eo_original_arr 原始 eo 定义队列
|
||||
* @param {object} input_parent_obj 父对象
|
||||
* @param {object} input_opts 可选配置项 {needToParseBindData:是否特殊解析定义字符串,isXml:组装内容是否为xml,bindObj:绑定对象,fnSetXmlAttr:xml属性处理函数}
|
||||
* @param {object} input_xml_attr_parent_obj 可选配置项,当且仅当构造对象为xml时生效,为xml父属性继承对象
|
||||
* @return {object} json字符串
|
||||
*
|
||||
*/
|
||||
eo_define_arr_to_json(input_eo_original_arr, input_parent_obj={}, input_opts={}, input_xml_attr_parent_obj={}) {
|
||||
let vm = this;
|
||||
input_eo_original_arr.map(function (val) {
|
||||
if (!val.paramKey || !val.checkbox) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (input_opts.needToParseBindData) {
|
||||
val.paramKey = vm.construct_text_by_express_builder(vm.replace_text_from_bind_obj(val.paramKey, input_opts.bindObj));
|
||||
val.paramInfo = vm.construct_text_by_express_builder(vm.replace_text_from_bind_obj(val.paramInfo || val.paramValue || '', input_opts.bindObj));
|
||||
if (input_opts.isXml) val.attribute = vm.construct_text_by_express_builder(vm.replace_text_from_bind_obj(val.attribute || "", input_opts.bindObj));
|
||||
} else {
|
||||
val.paramKey = vm.construct_text_by_express_builder(val.paramKey);
|
||||
val.paramInfo = vm.construct_text_by_express_builder(val.paramInfo || val.paramValue || '');
|
||||
if (input_opts.isXml) val.attribute = vm.construct_text_by_express_builder(val.attribute || "");
|
||||
}
|
||||
} catch (BIND_PARSE_ERROR) {}
|
||||
let tmp_value = input_parent_obj[val.paramKey] = val.paramInfo || val.paramValue || '';
|
||||
if (input_opts.isXml) input_xml_attr_parent_obj[val.paramKey] = val.attribute || "";
|
||||
if (val.childList && val.childList.length > 0) {
|
||||
if (input_opts.isXml) input_xml_attr_parent_obj[val.paramKey] = [input_xml_attr_parent_obj[val.paramKey], {}];
|
||||
let tmp_cb_result;
|
||||
switch (val.paramType.toString()) {
|
||||
case '12': { //array
|
||||
if((val.childList[0]||{}).isArrItem){
|
||||
//新数据结构,多项值数组
|
||||
input_parent_obj[val.paramKey] = [];
|
||||
tmp_cb_result={has_text:true};//设置tmp_cb_result,用于确认当前数组已经有内容,无需重新json_parse
|
||||
val.childList.map((tmp_child_item,tmp_child_key)=>{
|
||||
if(!tmp_child_item.checkbox)return;
|
||||
let tmp_item_parent_obj={},tmp_item_xml_attr_parent_obj={};
|
||||
if(tmp_child_item.paramType.toString()==="12"||!(tmp_child_item.childList&&tmp_child_item.childList.length>0)){
|
||||
vm.eo_define_arr_to_json([tmp_child_item], tmp_item_parent_obj, input_opts, input_opts.isXml ? tmp_item_xml_attr_parent_obj : {});
|
||||
tmp_item_parent_obj=tmp_item_parent_obj[tmp_child_item.paramKey];
|
||||
tmp_item_xml_attr_parent_obj=tmp_item_xml_attr_parent_obj[tmp_child_item.paramKey];
|
||||
}else{
|
||||
vm.eo_define_arr_to_json(tmp_child_item.childList, tmp_item_parent_obj, input_opts, input_opts.isXml ? tmp_item_xml_attr_parent_obj : {});
|
||||
}
|
||||
input_parent_obj[val.paramKey].push(tmp_item_parent_obj);
|
||||
if (input_opts.isXml) {
|
||||
if(typeof input_xml_attr_parent_obj[val.paramKey][0] !=="object")input_xml_attr_parent_obj[val.paramKey][0]=[];
|
||||
input_xml_attr_parent_obj[val.paramKey][0].push(tmp_child_item.attribute||"");
|
||||
input_xml_attr_parent_obj[val.paramKey].splice(tmp_child_key+1,1,tmp_item_xml_attr_parent_obj);
|
||||
}
|
||||
})
|
||||
}else{
|
||||
//为老数据,第一项数值不存在字段isArrItem
|
||||
input_parent_obj[val.paramKey] = [{}];
|
||||
tmp_cb_result = vm.eo_define_arr_to_json(val.childList, input_parent_obj[val.paramKey][0], input_opts, input_opts.isXml ? input_xml_attr_parent_obj[val.paramKey][1] : {});
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
input_parent_obj[val.paramKey] = {};
|
||||
tmp_cb_result = vm.eo_define_arr_to_json(val.childList, input_parent_obj[val.paramKey], input_opts, input_opts.isXml ? input_xml_attr_parent_obj[val.paramKey][1] : {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vm.check_empty_obj(tmp_cb_result)) {
|
||||
try {
|
||||
input_parent_obj[val.paramKey] = JSON.parse(tmp_value);
|
||||
} catch (JSON_PARSE_ERROR) {
|
||||
input_parent_obj[val.paramKey] = tmp_value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let tmp_param_type = val.paramType.toString();
|
||||
switch (tmp_param_type) {
|
||||
case '0': { //字符串
|
||||
break;
|
||||
}
|
||||
case '15': { //null
|
||||
input_parent_obj[val.paramKey] = null;
|
||||
}
|
||||
case '14': { //number
|
||||
let tmp_num_text = input_parent_obj[val.paramKey] || vm.DEFAULT_REFS_FROM_EO_TYPE[tmp_param_type];
|
||||
if (input_opts.isXml) {
|
||||
input_parent_obj[val.paramKey] = `${tmp_num_text}`;
|
||||
} else {
|
||||
try {
|
||||
if (JSON.parse(tmp_num_text) > Number.MAX_SAFE_INTEGER) {
|
||||
input_parent_obj[val.paramKey] = `eo_big_int_${tmp_num_text}`;
|
||||
} else {
|
||||
input_parent_obj[val.paramKey] = JSON.parse(tmp_num_text);
|
||||
}
|
||||
} catch (JSON_PARSE_ERROR) {
|
||||
input_parent_obj[val.paramKey] = `${tmp_num_text}`;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { //其他
|
||||
let tmp_default_value = input_parent_obj[val.paramKey] || vm.DEFAULT_REFS_FROM_EO_TYPE[tmp_param_type];
|
||||
try {
|
||||
input_parent_obj[val.paramKey] = JSON.parse(tmp_default_value);
|
||||
} catch (JSON_PARSE_ERROR) {
|
||||
input_parent_obj[val.paramKey] = `${tmp_default_value}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input_opts.isXml && input_opts.fnSetXmlAttr && val.attribute) {
|
||||
input_opts.fnSetXmlAttr(val.paramKey, val.attribute);
|
||||
}
|
||||
})
|
||||
return input_parent_obj;
|
||||
}
|
||||
/**
|
||||
* @desc 绑定管理解析
|
||||
* @param {string} input_old_text 源数据
|
||||
* @param {object} input_bind_obj 待解析的绑定对象
|
||||
* @return {string} 替换绑定变量后的字符串
|
||||
*/
|
||||
replace_text_from_bind_obj(input_old_text, input_bind_obj) {
|
||||
let vm = this;
|
||||
if (!input_bind_obj) return input_old_text;
|
||||
input_old_text = input_old_text || "";
|
||||
let response = input_bind_obj.response,
|
||||
responseHeaders = input_bind_obj.responseHeaders,
|
||||
requestBody = input_bind_obj.requestBody,
|
||||
requestHeaders = input_bind_obj.requestHeaders,
|
||||
restParams = input_bind_obj.restParams,
|
||||
queryParams = input_bind_obj.queryParams;
|
||||
let tmp_result = input_old_text,
|
||||
tmp_fn_replace_bind_text = (tmp_input_mark, tmp_input_match_text_arr) => {
|
||||
tmp_input_match_text_arr.map(function (val) {
|
||||
let tmp_new_text = '';
|
||||
try {
|
||||
let tmp_header_key_end_index = val.indexOf("]"); //头部信息关键字结束字符
|
||||
tmp_new_text = eval(/Headers/.test(tmp_input_mark) ? `${val.substring(1,val.indexOf("]"))}${val.substring(tmp_header_key_end_index,val.length - 1).toLowerCase()}` : val.substring(1, val.length - 1));
|
||||
if (tmp_new_text === undefined) {
|
||||
tmp_new_text = 'NULL';
|
||||
} else if (typeof tmp_new_text == 'object') {
|
||||
tmp_new_text = JSON.stringify(tmp_new_text);
|
||||
}
|
||||
} catch (EVAL_ERR) {
|
||||
tmp_new_text = 'NULL';
|
||||
}
|
||||
tmp_result = vm.text_replace_all('.' + val + '.', tmp_new_text, tmp_result);
|
||||
tmp_result = vm.text_replace_all('.' + val, tmp_new_text, tmp_result);
|
||||
tmp_result = vm.text_replace_all(val + '.', tmp_new_text, tmp_result);
|
||||
tmp_result = vm.text_replace_all(val, tmp_new_text, tmp_result);
|
||||
})
|
||||
return
|
||||
}
|
||||
tmp_fn_replace_bind_text('requestBody', input_old_text.trim().match(/(<requestBody[.\[])((?!(>)).)*(>)/g) || []);
|
||||
tmp_fn_replace_bind_text('requestHeaders', input_old_text.trim().match(/(<requestHeaders[.\[])((?!(>)).)*(>)/g) || []);
|
||||
tmp_fn_replace_bind_text('restParams', input_old_text.trim().match(/(<restParams[.\[])((?!(>)).)*(>)/g) || []);
|
||||
tmp_fn_replace_bind_text('queryParams', input_old_text.trim().match(/(<queryParams[.\[])((?!(>)).)*(>)/g) || []);
|
||||
tmp_fn_replace_bind_text('responseHeaders', input_old_text.trim().match(/(<responseHeaders[.\[])((?!(>)).)*(>)/g) || []);
|
||||
tmp_fn_replace_bind_text('response', input_old_text.trim().match(/(<response[.\[])((?!(>)).)*(>)/g) || []);
|
||||
return tmp_result;
|
||||
}
|
||||
/**
|
||||
* 文本替换全部
|
||||
* @param {string} input_old_text 被替换文本
|
||||
* @param {string} input_new_text 替换文本
|
||||
* @param {any} input_text 源数据
|
||||
*/
|
||||
text_replace_all(input_old_text, input_new_text, input_text) {
|
||||
if (input_old_text === input_new_text) return input_text;
|
||||
let tmp_text = input_text || "";
|
||||
if (typeof tmp_text !== "string") {
|
||||
try{
|
||||
tmp_text = JSON.stringify(tmp_text);
|
||||
return JSON.parse(tmp_text.split(input_old_text).join(input_new_text));
|
||||
}catch(JSON_ERR){
|
||||
}
|
||||
}
|
||||
return tmp_text.split(input_old_text).join(input_new_text);
|
||||
}
|
||||
/**
|
||||
* @desc 表达式构造器
|
||||
* @param {*} input_text
|
||||
* @returns {string} 构造后内容
|
||||
*/
|
||||
construct_text_by_express_builder(input_text) {
|
||||
return input_text;
|
||||
}
|
||||
check_empty_obj(input_check_obj) {
|
||||
for (let key in input_check_obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
exports.core = main;
|
||||
})()
|
@ -1,534 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
let Crypto = require('crypto');
|
||||
let CryptoJS = require('crypto-js');
|
||||
let privateFun = {};
|
||||
let publicFun = {};
|
||||
const TIMINGSUMMARY = {
|
||||
NS_PER_SEC: 1e9,
|
||||
MS_PER_NS: 1e6,
|
||||
};
|
||||
/**
|
||||
* @desc AES/DES解密
|
||||
* @param {string} inputMode 选择模式
|
||||
* @param {string} inputKey 加密密钥
|
||||
* @param {string} inputData 待加密数据
|
||||
* @param {object} inputOpts 配置项,padding/iv/mode
|
||||
* @return {string} 结果字符串
|
||||
*/
|
||||
privateFun.aesOrDesAndEncryptOrDecrypt=(inputMode,inputData, inputKey, inputOpts)=>{
|
||||
if (inputOpts) {
|
||||
inputOpts=Object.assign({},inputOpts);
|
||||
if (inputOpts.mode) inputOpts.mode = CryptoJS.mode[inputOpts.mode];
|
||||
if (inputOpts.padding) inputOpts.padding = CryptoJS.pad[inputOpts.padding];
|
||||
if(inputOpts.iv)inputOpts.iv=CryptoJS.enc.Latin1.parse(inputOpts.iv || "")
|
||||
}
|
||||
inputKey=CryptoJS.enc.Latin1.parse(inputKey || "");
|
||||
let tmpType=inputMode.split("-")[0],tmpOpr=inputMode.split("-")[1];
|
||||
switch(tmpOpr){
|
||||
case "decrypt":{
|
||||
return CryptoJS[tmpType].decrypt(inputData, inputKey, inputOpts).toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
case "encrypt":{
|
||||
return CryptoJS[tmpType].encrypt(inputData, inputKey, inputOpts).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @desc AES/DES解密
|
||||
* @param {string} inputKey 加密密钥
|
||||
* @param {string} inputData 待加密数据
|
||||
* @param {object} inputOpts 配置项,padding/iv/mode
|
||||
* @return {string} 解密后字符串
|
||||
*/
|
||||
publicFun.aesDecrypt = (inputData, inputKey, inputOpts) => {
|
||||
return privateFun.aesOrDesAndEncryptOrDecrypt("AES-decrypt",inputData, inputKey, inputOpts);
|
||||
}
|
||||
publicFun.desDecrypt = (inputData, inputKey, inputOpts) => {
|
||||
return privateFun.aesOrDesAndEncryptOrDecrypt("DES-decrypt",inputData, inputKey, inputOpts);
|
||||
}
|
||||
/**
|
||||
* @desc AES/DES加密
|
||||
* @param {string} inputKey 加密密钥
|
||||
* @param {string} inputData 待加密数据
|
||||
* @param {object} inputOpts 配置项,padding/iv/mode
|
||||
* @return {string} 加密后字符串
|
||||
*/
|
||||
publicFun.aesEncrypt = (inputData, inputKey, inputOpts) => {
|
||||
return privateFun.aesOrDesAndEncryptOrDecrypt("AES-encrypt",inputData, inputKey, inputOpts);
|
||||
}
|
||||
publicFun.desEncrypt = (inputData, inputKey, inputOpts) => {
|
||||
return privateFun.aesOrDesAndEncryptOrDecrypt("DES-encrypt",inputData, inputKey, inputOpts);
|
||||
}
|
||||
/**
|
||||
* @description
|
||||
*/
|
||||
privateFun.createEcdsa = () => {
|
||||
var MAX_OCTET = 0x80,
|
||||
CLASS_UNIVERSAL = 0,
|
||||
PRIMITIVE_BIT = 0x20,
|
||||
TAG_SEQ = 0x10,
|
||||
TAG_INT = 0x02,
|
||||
ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6),
|
||||
ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6);
|
||||
|
||||
function getParamSize(keySize) {
|
||||
switch (keySize) {
|
||||
case 512: {
|
||||
keySize = 521;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
function derToJose(signature, bits) {
|
||||
signature = Buffer.from(signature, 'base64');
|
||||
var paramBytes = getParamSize(parseInt(bits));
|
||||
|
||||
var maxEncodedParamLength = paramBytes + 1;
|
||||
|
||||
var inputLength = signature.length;
|
||||
|
||||
var offset = 0;
|
||||
if (signature[offset++] !== ENCODED_TAG_SEQ) {
|
||||
throw new Error('Could not find expected "seq"');
|
||||
}
|
||||
|
||||
var seqLength = signature[offset++];
|
||||
if (seqLength === (MAX_OCTET | 1)) {
|
||||
seqLength = signature[offset++];
|
||||
}
|
||||
|
||||
if (inputLength - offset < seqLength) {
|
||||
throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining');
|
||||
}
|
||||
|
||||
if (signature[offset++] !== ENCODED_TAG_INT) {
|
||||
throw new Error('Could not find expected "int" for "r"');
|
||||
}
|
||||
|
||||
var rLength = signature[offset++];
|
||||
|
||||
if (inputLength - offset - 2 < rLength) {
|
||||
throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available');
|
||||
}
|
||||
|
||||
if (maxEncodedParamLength < rLength) {
|
||||
throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
||||
}
|
||||
|
||||
var rOffset = offset;
|
||||
offset += rLength;
|
||||
|
||||
if (signature[offset++] !== ENCODED_TAG_INT) {
|
||||
throw new Error('Could not find expected "int" for "s"');
|
||||
}
|
||||
|
||||
var sLength = signature[offset++];
|
||||
|
||||
if (inputLength - offset !== sLength) {
|
||||
throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"');
|
||||
}
|
||||
|
||||
if (maxEncodedParamLength < sLength) {
|
||||
throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable');
|
||||
}
|
||||
|
||||
var sOffset = offset;
|
||||
offset += sLength;
|
||||
|
||||
if (offset !== inputLength) {
|
||||
throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain');
|
||||
}
|
||||
|
||||
var rPadding = paramBytes - rLength,
|
||||
sPadding = paramBytes - sLength;
|
||||
|
||||
var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength);
|
||||
|
||||
for (offset = 0; offset < rPadding; ++offset) {
|
||||
dst[offset] = 0;
|
||||
}
|
||||
signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength);
|
||||
|
||||
offset = paramBytes;
|
||||
|
||||
for (var o = offset; offset < o + sPadding; ++offset) {
|
||||
dst[offset] = 0;
|
||||
}
|
||||
signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength);
|
||||
|
||||
dst = dst.toString('base64');
|
||||
dst = publicFun.setBase64Url(dst);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
return function (bits, message, secretKey) {
|
||||
try {
|
||||
var signature = publicFun.setBase64Url(privateFun.createSign('RSA-SHA' + bits, message, secretKey));
|
||||
signature = derToJose(signature, bits);
|
||||
return signature;
|
||||
} catch (e) {
|
||||
console.error(new Date() + ':libs/encrypt.js,122(ES 签名错误):' + e);
|
||||
return 'EcdsaError';
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @description 公用加密算法(create sign)
|
||||
* @param [string] encryption 加密方式
|
||||
* @param [string] message 待加密内容
|
||||
* @param [string] secretKey 密钥
|
||||
* @param [object] options 配置可选项
|
||||
* @returns [string] 已加密内容
|
||||
*/
|
||||
privateFun.createSign = function (encryption, message, secretKey, options) {
|
||||
options = options || {
|
||||
hash: 'base64'
|
||||
};
|
||||
let sign = Crypto.createSign(encryption);
|
||||
sign.update(message || '', 'utf8');
|
||||
try {
|
||||
if(typeof secretKey==="object"&& typeof secretKey.padding ==="string"){
|
||||
secretKey.padding=Crypto.constants[secretKey.padding];
|
||||
}
|
||||
return sign.sign(secretKey, options.hash);
|
||||
} catch (e) {
|
||||
return 'SignError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 公用加密算法(createHash)
|
||||
* @param [string] encryption 加密方式
|
||||
* @param [string] message 待加密内容
|
||||
* @param [object] options
|
||||
* @returns [string] 已加密内容
|
||||
*/
|
||||
privateFun.createHash = function (encryption, message, options) {
|
||||
options = options || {
|
||||
hash: 'hex'
|
||||
};
|
||||
return Crypto.createHash(encryption).update(message || '').digest(options.hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 公用加密算法(createHmac)
|
||||
* @param [string] encryption 加密方式
|
||||
* @param [string] message 待加密内容
|
||||
* @returns [string] 已加密内容
|
||||
*/
|
||||
privateFun.createHmac = function (encryption, message, key, options) {
|
||||
options = options || {
|
||||
hash: 'hex'
|
||||
};
|
||||
return Crypto.createHmac(encryption, key || '').update(message || '').digest(options.hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* md5数据加密
|
||||
* @param {string} info 需加密信息体
|
||||
* return {string} md5加密后信息
|
||||
*/
|
||||
publicFun.md5 = function (info) {
|
||||
return privateFun.createHash('md5', info);
|
||||
}
|
||||
|
||||
/**
|
||||
* HmacSHA1数据加密
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} key 密钥
|
||||
* @param {object} options 配置
|
||||
* return {string} HmacSHA1加密后信息
|
||||
*/
|
||||
publicFun.HmacSHA1 = function (info, key, options) {
|
||||
return privateFun.createHmac('sha1', info, key, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* HmacSHA256数据加密
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} key 密钥
|
||||
* @param {object} options 配置
|
||||
* return {string} HmacSHA256加密后信息
|
||||
*/
|
||||
publicFun.HmacSHA256 = function (info, key, options) {
|
||||
return privateFun.createHmac('sha256', info, key, options);
|
||||
}
|
||||
/**
|
||||
* HmacSHA224
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} key 密钥
|
||||
* @param {object} options 配置
|
||||
* return {string} HmacSHA224加密后信息
|
||||
*/
|
||||
publicFun.HmacSHA224 = function (info, key, options) {
|
||||
return privateFun.createHmac('sha224', info, key, options);
|
||||
}
|
||||
/**
|
||||
* HmacSHA384
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} key 密钥
|
||||
* @param {object} options 配置
|
||||
* return {string} HmacSHA384加密后信息
|
||||
*/
|
||||
publicFun.HmacSHA384 = function (info, key, options) {
|
||||
return privateFun.createHmac('sha384', info, key, options);
|
||||
}
|
||||
/**
|
||||
* HmacSHA512
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} key 密钥
|
||||
* @param {object} options 配置
|
||||
* return {string} HmacSHA512加密后信息
|
||||
*/
|
||||
publicFun.HmacSHA512 = function (info, key, options) {
|
||||
return privateFun.createHmac('sha512', info, key, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1数据加密
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {object} options 配置
|
||||
* return {string} sha1加密后信息
|
||||
*/
|
||||
publicFun.sha1 = function (info, options) {
|
||||
return privateFun.createHash('sha1', info, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256数据加密
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {object} options 配置
|
||||
* return {string} sha256加密后信息
|
||||
*/
|
||||
publicFun.sha256 = function (info, options) {
|
||||
return privateFun.createHash('sha256', info, options);
|
||||
}
|
||||
/**
|
||||
* sha224
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {object} options 配置
|
||||
* return {string} sha224加密后信息
|
||||
*/
|
||||
publicFun.sha224 = function (info, options) {
|
||||
return privateFun.createHash('sha224', info, options);
|
||||
}
|
||||
/**
|
||||
* sha384
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {object} options 配置
|
||||
* return {string} sha384加密后信息
|
||||
*/
|
||||
publicFun.sha384 = function (info, options) {
|
||||
return privateFun.createHash('sha384', info, options);
|
||||
}
|
||||
/**
|
||||
* sha512
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {object} options 配置
|
||||
* return {string} sha512加密后信息
|
||||
*/
|
||||
publicFun.sha512 = function (info, options) {
|
||||
return privateFun.createHash('sha512', info, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* RS256
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} RS256加密后信息
|
||||
*/
|
||||
publicFun.RS256 = function (info, privateKey, options) {
|
||||
if (typeof options === "string") {
|
||||
options = {
|
||||
hash: options
|
||||
}
|
||||
}
|
||||
return privateFun.createSign('RSA-SHA256', info, privateKey, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* RS384
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} RS384加密后信息
|
||||
*/
|
||||
publicFun.RS384 = function (info, privateKey, options) {
|
||||
return privateFun.createSign('RSA-SHA384', info, privateKey, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* RS512
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} RS512加密后信息
|
||||
*/
|
||||
publicFun.RS512 = function (info, privateKey, options) {
|
||||
return privateFun.createSign('RSA-SHA512', info, privateKey, options);
|
||||
}
|
||||
/**
|
||||
* RS1
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} RSA-SHA1加密后信息
|
||||
*/
|
||||
publicFun.RS1 = function (info, privateKey, options) {
|
||||
if (typeof options === "string") {
|
||||
options = {
|
||||
hash: options
|
||||
}
|
||||
}
|
||||
return privateFun.createSign('RSA-SHA1', info, privateKey, options);
|
||||
}
|
||||
/**
|
||||
* ES256
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} ES256加密后信息
|
||||
*/
|
||||
publicFun.ES256 = function (info, privateKey, options) {
|
||||
return privateFun.createEcdsa()('256', info, privateKey, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* ES384
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} ES384加密后信息
|
||||
*/
|
||||
publicFun.ES384 = function (info, privateKey, options) {
|
||||
return privateFun.createEcdsa()('384', info, privateKey, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* ES512
|
||||
* @param {string} info 需加密信息体
|
||||
* @param {string} priviteKey 私钥
|
||||
* @param {object} options 配置
|
||||
* return {string} ES512加密后信息
|
||||
*/
|
||||
publicFun.ES512 = function (info, privateKey, options) {
|
||||
return privateFun.createEcdsa()('512', info, privateKey, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* base64 to base64Url
|
||||
* @param {string} info 需转换信息体
|
||||
* return {string} base64Url 信息体
|
||||
*/
|
||||
publicFun.setBase64Url = function (info) {
|
||||
return info.replace(/=/g, '')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_');
|
||||
}
|
||||
/**
|
||||
* String/object to base64
|
||||
* @param {string/object} info 需转换信息体
|
||||
* @param {object} options 可选项
|
||||
* return {string} base64 信息体
|
||||
*/
|
||||
publicFun.stringToBase64 = function (info, options) {
|
||||
options = options || {
|
||||
toUrl: false
|
||||
}
|
||||
let output = '';
|
||||
switch (typeof info) {
|
||||
case 'string': {
|
||||
output = info;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
output = JSON.stringify(info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
output = Buffer.from(output).toString('base64');
|
||||
if (options.toUrl) {
|
||||
return publicFun.setBase64Url(output);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* uuid生成器
|
||||
* return {string} uuid
|
||||
*/
|
||||
publicFun.uuidGeneration = function (info, options) {
|
||||
var template = {
|
||||
array: [],
|
||||
hexSingle: "0123456789abcdef"
|
||||
}
|
||||
for (var i = 0; i < 36; i++) {
|
||||
template.array[i] = template.hexSingle.substr(Math.floor(Math.random() * 0x10), 1);
|
||||
}
|
||||
template.array[14] = "4";
|
||||
template.array[19] = template.hexSingle.substr((template.array[19] & 0x3) | 0x8, 1);
|
||||
template.array[8] = template.array[13] = template.array[18] = template.array[23] = "-";
|
||||
return template.array.join("");
|
||||
}
|
||||
publicFun.getMicrosToMsStr = (inputStartTime, inputEndTime) => {
|
||||
if (inputStartTime === undefined || inputEndTime === undefined) return "0.00";
|
||||
let tmpSecondDiff = inputEndTime[0] - inputStartTime[0]
|
||||
let tmpNanoSecondDiff = inputEndTime[1] - inputStartTime[1]
|
||||
let tmpDiffInNanoSecond = tmpSecondDiff * TIMINGSUMMARY.NS_PER_SEC + tmpNanoSecondDiff;
|
||||
let tmpOutput = tmpDiffInNanoSecond / TIMINGSUMMARY.MS_PER_NS;
|
||||
if (tmpOutput < 0) {
|
||||
return "0.00"
|
||||
} else {
|
||||
return "" + tmpOutput.toFixed(2)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @desc RSA 公私钥 加密
|
||||
* @param {string/object} inputKey 密钥
|
||||
* @param {string} inputData 待处理数据
|
||||
* @param {object} inputHash 结果的编码格式,base64(默认)/hex
|
||||
* @return {string} 结果字符串
|
||||
*/
|
||||
publicFun.rsaPublicEncrypt = ( inputKey,inputData, inputHash="base64") => {
|
||||
if(typeof inputKey==="object"&& typeof inputKey.padding ==="string"){
|
||||
inputKey.padding=Crypto.constants[inputKey.padding];
|
||||
}
|
||||
return Crypto.publicEncrypt(inputKey,new Buffer.from(inputData, 'utf8')).toString(inputHash);
|
||||
}
|
||||
publicFun.rsaPrivateEncrypt = (inputKey,inputData, inputHash="base64") => {
|
||||
if(typeof inputKey==="object"&& typeof inputKey.padding ==="string"){
|
||||
inputKey.padding=Crypto.constants[inputKey.padding];
|
||||
}
|
||||
return Crypto.privateEncrypt(inputKey,new Buffer.from(inputData, 'utf8')).toString(inputHash);
|
||||
}
|
||||
/**
|
||||
* @desc RSA 公私钥 解密
|
||||
* @param {string/object} inputKey 密钥
|
||||
* @param {string} inputData 待处理数据
|
||||
* @param {object} inputHash 结果的编码格式,base64(默认)/hex
|
||||
* @return {string} 结果字符串
|
||||
*/
|
||||
publicFun.rsaPublicDecrypt = ( inputKey, inputData,inputHash="base64") => {
|
||||
if(typeof inputKey==="object"&& typeof inputKey.padding ==="string"){
|
||||
inputKey.padding=Crypto.constants[inputKey.padding];
|
||||
}
|
||||
return Crypto.publicDecrypt(inputKey, new Buffer.from(inputData, inputHash)).toString("utf-8");
|
||||
}
|
||||
publicFun.rsaPrivateDecrypt = (inputKey,inputData, inputHash="base64") => {
|
||||
if(typeof inputKey==="object"&& typeof inputKey.padding ==="string"){
|
||||
inputKey.padding=Crypto.constants[inputKey.padding];
|
||||
}
|
||||
return Crypto.privateDecrypt(inputKey, new Buffer.from(inputData, inputHash)).toString("utf-8");
|
||||
}
|
||||
exports.core = publicFun;
|
||||
|
||||
})();
|
@ -1,491 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
let _RedirectClass = require('./redirect');
|
||||
let _ApiUtil = require('./apiUtil');
|
||||
let _LibsCommon = require('./common');
|
||||
let _HttpPackageClass = new (require('./http.package').core)();
|
||||
const CONFIG = require('../config.json');
|
||||
let url = require('url'),
|
||||
querystring = require('querystring');
|
||||
class Main {
|
||||
constructor(input_args, input_callback) {
|
||||
if (Object.prototype.toString.call(input_args) === '[object SharedArrayBuffer]') {
|
||||
global._WORKER_DATA = input_args;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
switch (input_args.opr) {
|
||||
case 'exec_http': {
|
||||
this.execute(input_args.data, input_args.env, input_args.opts, null, (tmp_input_res) => {
|
||||
this.wakeTopThread(tmp_input_res);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (EXEC_ERR) {
|
||||
console.error(EXEC_ERR);
|
||||
this.wakeTopThread(EXEC_ERR.stack || EXEC_ERR);
|
||||
}
|
||||
return this.EXEC_RESULT;
|
||||
}
|
||||
//执行ajax http请求
|
||||
async execute(input_test_data, input_env, input_opts, input_callback, input_return_callback) {
|
||||
let tmp_request_script_data = {};
|
||||
input_test_data = _LibsCommon.deepCopy(input_test_data);
|
||||
input_env = input_env || _LibsCommon.parseEnv();
|
||||
let tmp_target_type_env = input_env.http;
|
||||
if (input_test_data.requestScript || tmp_target_type_env.requestScript) {
|
||||
tmp_request_script_data = _ApiUtil.scriptExecuteBeforeCode(
|
||||
input_test_data,
|
||||
input_test_data.requestScript || '',
|
||||
{
|
||||
env: input_env,
|
||||
fnCodeArr: input_opts.fnCodeArr,
|
||||
}
|
||||
);
|
||||
if (tmp_request_script_data.status === 'success') {
|
||||
input_test_data = tmp_request_script_data.data;
|
||||
input_env = tmp_request_script_data.env;
|
||||
}
|
||||
}
|
||||
tmp_target_type_env = input_env.http;
|
||||
if (input_test_data.timelimit === 'follow') {
|
||||
input_test_data.timelimit = global._TIMEOUTLIMIT || CONFIG.MAX_TIME_LIMIT;
|
||||
input_test_data.timelimitType = global._TIMEOUTLIMITTYPE || 'totalTime';
|
||||
}
|
||||
let tmp_result;
|
||||
await new Promise(function (resolve, reject) {
|
||||
let tmp_report_data = {
|
||||
reportList: tmp_request_script_data.reportList || [],
|
||||
response: '',
|
||||
},
|
||||
tmp_response_str = '';
|
||||
if (!input_test_data.hasOwnProperty('params') && input_test_data.hasOwnProperty('body')) {
|
||||
input_test_data.params = input_test_data.body;
|
||||
input_test_data.isBody = true;
|
||||
}
|
||||
if (Object.prototype.toString.call(input_test_data.params) === '[object Array]') {
|
||||
input_test_data.params = input_test_data.params;
|
||||
} else if (typeof input_test_data.params == 'object') {
|
||||
input_test_data.params = Object.assign({}, tmp_target_type_env.extraFormDataParam, input_test_data.params);
|
||||
} else {
|
||||
input_test_data.params = (input_test_data.params || '').toString();
|
||||
}
|
||||
input_test_data.headers = Object.assign({}, tmp_target_type_env.headerParam, input_test_data.headers || {});
|
||||
let template = {
|
||||
urlObject: {},
|
||||
matchUrlArray: [],
|
||||
chunk: {
|
||||
array: [],
|
||||
length: 0,
|
||||
},
|
||||
queryParam: [],
|
||||
jwt: '',
|
||||
},
|
||||
tmp_test_data = _ApiUtil.parseApiByEnvGlobalParam(input_test_data, input_env.envParam),
|
||||
tmp_ajax_xhr,
|
||||
tmp_post_data,
|
||||
tmp_multi_form;
|
||||
tmp_test_data.url = _ApiUtil.parseUri(tmp_test_data.url, tmp_target_type_env.baseUrlParam);
|
||||
template.queryParam = url.parse(tmp_test_data.url).query || [];
|
||||
input_env.envAuth = input_env.envAuth || {};
|
||||
switch (input_env.envAuth.status) {
|
||||
case '1': {
|
||||
if (input_env.envAuth.basicAuth) {
|
||||
tmp_test_data.headers['Authorization'] =
|
||||
'Basic ' +
|
||||
Buffer.from(
|
||||
(input_env.envAuth.basicAuth.username || '') + ':' + (input_env.envAuth.basicAuth.password || '')
|
||||
).toString('base64');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '2': {
|
||||
template.jwt = _LibsCommon.jwt(
|
||||
{
|
||||
alg: input_env.envAuth.jwtAuth.alg,
|
||||
typ: 'JWT',
|
||||
},
|
||||
input_env.envAuth.jwtAuth.payload,
|
||||
input_env.envAuth.jwtAuth.secretSalt
|
||||
);
|
||||
if (template.jwt == 'jwtError') {
|
||||
throw 'jwtError';
|
||||
} else if (input_env.envAuth.jwtAuth.isBearer) {
|
||||
template.jwt = `Bearer ${template.jwt}`;
|
||||
}
|
||||
switch (input_env.envAuth.jwtAuth.position) {
|
||||
case 'header': {
|
||||
tmp_test_data.headers[input_env.envAuth.jwtAuth.tokenName || 'tokenName'] = template.jwt;
|
||||
break;
|
||||
}
|
||||
case 'query': {
|
||||
if (tmp_test_data.url.indexOf('?') > -1) {
|
||||
tmp_test_data.url +=
|
||||
(template.queryParam.length > 0 ? '&' : '') +
|
||||
(input_env.envAuth.jwtAuth.tokenName || 'tokenName') +
|
||||
'=' +
|
||||
template.jwt;
|
||||
} else {
|
||||
tmp_test_data.url += '?' + (input_env.envAuth.jwtAuth.tokenName || 'tokenName') + '=' + template.jwt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
let tmp_query_str = querystring.stringify(
|
||||
Object.assign({}, tmp_target_type_env.queryParam, querystring.parse(url.parse(tmp_test_data.url).query))
|
||||
);
|
||||
if (tmp_query_str) {
|
||||
let tmp_url_param_index = tmp_test_data.url.indexOf('?');
|
||||
if (tmp_url_param_index > -1) {
|
||||
tmp_test_data.url = `${tmp_test_data.url.substr(0, tmp_url_param_index)}?${tmp_query_str}`;
|
||||
} else {
|
||||
tmp_test_data.url = `${tmp_test_data.url}?${tmp_query_str}`;
|
||||
}
|
||||
}
|
||||
template.urlObject = url.parse(tmp_test_data.url);
|
||||
let tmp_test_opts = {
|
||||
path: template.urlObject.path,
|
||||
hostname: template.urlObject.hostname,
|
||||
port: template.urlObject.port,
|
||||
protocol: template.urlObject.protocol,
|
||||
headers: tmp_test_data.headers,
|
||||
method: input_test_data.method || 'GET',
|
||||
};
|
||||
if (/"content-type":"multipart\/form-data/i.test(JSON.stringify(tmp_test_data.headers))) {
|
||||
tmp_test_data.isMuti = true;
|
||||
}
|
||||
tmp_post_data = tmp_test_data.params;
|
||||
if (input_test_data.bodyType !== 'binary') {
|
||||
tmp_report_data.requestBody = {
|
||||
body: tmp_test_data.params,
|
||||
requestType: typeof tmp_post_data == 'string' ? 1 : 0,
|
||||
};
|
||||
if (tmp_test_data.isMuti) {
|
||||
let tmpMutiCallbackObj = _ApiUtil.parseRequestBody(tmp_post_data);
|
||||
tmp_multi_form = tmpMutiCallbackObj.class;
|
||||
tmp_report_data.requestBody.body =
|
||||
typeof tmp_test_data.params == 'object' ? tmpMutiCallbackObj.params : tmp_post_data;
|
||||
} else {
|
||||
tmp_post_data =
|
||||
typeof tmp_post_data == 'object' ? querystring.stringify(tmp_post_data || {}) : tmp_post_data;
|
||||
}
|
||||
} else {
|
||||
tmp_report_data.requestBody = {
|
||||
body: `[binary]${tmp_test_data.binaryFileName}`,
|
||||
requestType: 1,
|
||||
};
|
||||
}
|
||||
try {
|
||||
tmp_report_data.general = {
|
||||
redirectTimes: 0,
|
||||
downloadSize: 0,
|
||||
downloadRate: 0,
|
||||
requestUrl: tmp_test_data.url,
|
||||
requestMethod: tmp_test_opts.method,
|
||||
name: input_test_data.name,
|
||||
timeLimit: input_test_data.timelimit,
|
||||
};
|
||||
if (input_test_data.timelimit > CONFIG.MAX_TIME_LIMIT || !input_test_data.timelimit) {
|
||||
input_test_data.timelimit = CONFIG.MAX_TIME_LIMIT;
|
||||
}
|
||||
tmp_report_data.requestHeaders = tmp_test_opts.headers;
|
||||
if (tmp_test_data.isMuti) {
|
||||
tmp_test_opts.headers = Object.assign({}, tmp_test_opts.headers, tmp_multi_form.getHeaders());
|
||||
} else {
|
||||
let tmpJsonStringifyHeaders = JSON.stringify(tmp_test_opts.headers);
|
||||
if (!/"content-length":/i.test(tmpJsonStringifyHeaders)) {
|
||||
tmp_test_opts.headers['Content-length'] = Buffer.byteLength(tmp_post_data);
|
||||
}
|
||||
if (!/"content-type":/i.test(tmpJsonStringifyHeaders)) {
|
||||
tmp_test_opts.headers['Content-Type'] = tmp_test_data.contentType || 'application/x-www-form-urlencoded';
|
||||
}
|
||||
}
|
||||
tmp_test_opts.headers = _HttpPackageClass.setCookieToHeaders(
|
||||
tmp_test_opts.headers,
|
||||
tmp_test_opts.hostname,
|
||||
input_opts.globalHeader
|
||||
);
|
||||
if (tmp_request_script_data.status && tmp_request_script_data.status !== 'success') {
|
||||
tmp_report_data.general.time = '0.00ms';
|
||||
tmp_report_data.general.status = tmp_request_script_data.status;
|
||||
tmp_report_data.errorReason = [tmp_request_script_data.msg];
|
||||
if (input_callback) input_callback(tmp_report_data);
|
||||
reject('error');
|
||||
return;
|
||||
}
|
||||
let tmp_fn_check_is_illegal_url = (tmp_input_hostname, tmp_input_total_time) => {
|
||||
let tmp_is_localhost = new RegExp(_LibsCommon.LOCAL_REGEXP_CONST).test(tmp_input_hostname);
|
||||
if (!tmp_input_hostname || tmp_is_localhost) {
|
||||
tmp_report_data.general.time = tmp_input_total_time.toFixed(2) + 'ms';
|
||||
tmp_report_data.general.status = 'error';
|
||||
if (input_callback) input_callback(tmp_report_data);
|
||||
if (tmp_is_localhost) {
|
||||
tmp_report_data.isLocal = true;
|
||||
tmp_report_data.errorReason = [global.eoLang['63be68fa-31fc-498c-b49c-d3b6db10a95b']];
|
||||
reject('localhost');
|
||||
} else {
|
||||
tmp_report_data.errorReason = [global.eoLang['d6fa1d73-6a43-477f-a6df-6752661c9df3']];
|
||||
reject('illegal');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
tmp_fn_parse_ajax_resolve = (tmp_input_total_time) => {
|
||||
tmp_report_data.general.time = tmp_input_total_time.toFixed(2) + 'ms';
|
||||
tmp_report_data.env = input_env;
|
||||
if (input_callback) input_callback(tmp_report_data);
|
||||
try {
|
||||
return {
|
||||
time: tmp_report_data.general.time,
|
||||
code: tmp_report_data.general.statusCode,
|
||||
response: tmp_response_str,
|
||||
header: tmp_report_data.responseHeaders,
|
||||
};
|
||||
} catch (childE) {
|
||||
return {
|
||||
time: tmp_report_data.general.time,
|
||||
code: tmp_report_data.general.statusCode,
|
||||
response: tmp_response_str,
|
||||
header: tmp_report_data.responseHeaders,
|
||||
};
|
||||
}
|
||||
};
|
||||
if (tmp_fn_check_is_illegal_url(tmp_test_opts.hostname, 0)) return;
|
||||
if (tmp_test_opts.method == 'GET') {
|
||||
template.matchUrlArray = tmp_test_opts.path.split('?');
|
||||
if (template.matchUrlArray.length > 2) {
|
||||
template.matchUrlArray = template.matchUrlArray.slice(2).join('?').split('&');
|
||||
tmp_test_opts.path += '&' + template.matchUrlArray[0];
|
||||
}
|
||||
}
|
||||
let tmp_fn_ajax_err = (tmp_input_err, tmp_input_total_time) => {
|
||||
if (tmp_report_data.general.status == 'timeout') {
|
||||
if (typeof input_test_data.timelimitContinue == 'boolean' && !input_test_data.timelimitContinue) {
|
||||
tmp_report_data.general.time = tmp_input_total_time.toFixed(2) + 'ms';
|
||||
if (input_callback) input_callback(tmp_report_data);
|
||||
reject('timeout');
|
||||
} else {
|
||||
resolve(tmp_fn_parse_ajax_resolve(tmp_input_total_time));
|
||||
}
|
||||
return;
|
||||
}
|
||||
tmp_report_data.general.status = 'error';
|
||||
tmp_report_data.errorReason = [tmp_input_err.name + ':' + tmp_input_err.message];
|
||||
// tmp_report_data.reportList.push({
|
||||
// type: 'error',
|
||||
// content: tmp_input_err.name + ':' + tmp_input_err.message
|
||||
// });
|
||||
resolve(tmp_fn_parse_ajax_resolve(tmp_input_total_time));
|
||||
},
|
||||
tmp_fn_ajax_end = (tmp_input_res, tmp_input_res_obj) => {
|
||||
tmp_response_str = tmp_report_data.response = tmp_input_res_obj.str;
|
||||
tmp_report_data.general['statusCode'] = tmp_input_res.statusCode;
|
||||
tmp_report_data.general.downloadSize = tmp_input_res_obj.chunk.length;
|
||||
tmp_report_data.general.downloadRate = (
|
||||
(tmp_input_res_obj.chunk.length / tmp_input_res_obj.contentDeliveryTiming / 1024) *
|
||||
1000
|
||||
).toFixed(2);
|
||||
if (input_test_data.responseScript || tmp_target_type_env.responseScript) {
|
||||
let tmpExecutResponseScriptResult = _ApiUtil.scriptExecuteAfterCode(
|
||||
{
|
||||
response: tmp_response_str,
|
||||
},
|
||||
input_test_data.responseScript,
|
||||
{
|
||||
env: input_env,
|
||||
functionCode: input_opts.fnCodeArr,
|
||||
globalHeader: input_opts.globalHeader,
|
||||
responseHeaders: tmp_input_res.headers,
|
||||
body: input_test_data.params || input_test_data.body,
|
||||
headers: tmp_ajax_xhr.getHeaders(),
|
||||
query: querystring.parse(url.parse(input_test_data.url).query),
|
||||
}
|
||||
);
|
||||
tmp_report_data.reportList = [
|
||||
...tmp_report_data.reportList,
|
||||
...(tmpExecutResponseScriptResult.reportList || []),
|
||||
];
|
||||
if (tmpExecutResponseScriptResult.status && tmpExecutResponseScriptResult.status !== 'success') {
|
||||
tmp_report_data.errorReason = [tmpExecutResponseScriptResult.msg];
|
||||
tmp_report_data.general.status = tmpExecutResponseScriptResult.status;
|
||||
tmp_report_data.general.time = tmp_input_res_obj.totalTime.toFixed(2) + 'ms';
|
||||
if (input_callback) input_callback(tmp_report_data);
|
||||
reject('error');
|
||||
return;
|
||||
}
|
||||
input_env = tmpExecutResponseScriptResult.env;
|
||||
tmp_response_str = tmp_report_data.response = tmpExecutResponseScriptResult.data;
|
||||
}
|
||||
_ApiUtil
|
||||
.parseResponse(
|
||||
tmp_input_res.headers,
|
||||
Buffer.concat(tmp_input_res_obj.chunk.array, tmp_input_res_obj.chunk.length),
|
||||
{
|
||||
path: tmp_test_opts.path,
|
||||
size: tmp_report_data.general.downloadSize,
|
||||
}
|
||||
)
|
||||
.then((tmp_input_file_obj) => {
|
||||
tmp_report_data.returnResultType = tmp_input_file_obj.type;
|
||||
if (tmp_input_file_obj.name) tmp_report_data.general.downloadUrl = tmp_input_file_obj.name;
|
||||
tmp_report_data.general.status = 'finish';
|
||||
tmp_report_data.responseHeaders = tmp_input_res.headers;
|
||||
resolve(tmp_fn_parse_ajax_resolve(tmp_input_res_obj.totalTime));
|
||||
});
|
||||
};
|
||||
let tmp_timeout_type_obj = {
|
||||
total: 0,
|
||||
first_byte: 1,
|
||||
},
|
||||
tmp_advanced_setting = {};
|
||||
if (input_test_data.sendNocacheToken) {
|
||||
tmp_advanced_setting.sendNocacheToken = 1;
|
||||
}
|
||||
if (input_test_data.checkSSL) {
|
||||
tmp_advanced_setting.checkSSL = 1;
|
||||
}
|
||||
if (input_test_data.sendEoToken) {
|
||||
tmp_advanced_setting.sendEoToken = 1;
|
||||
}
|
||||
_HttpPackageClass.socketReduce(
|
||||
{
|
||||
postData: tmp_test_data.isMuti ? tmp_multi_form : tmp_post_data,
|
||||
isMuti: tmp_test_data.isMuti,
|
||||
options: tmp_test_opts,
|
||||
timeoutLimit: input_test_data.timelimit,
|
||||
globalHeader: input_opts.globalHeader,
|
||||
timeoutLimitType: tmp_timeout_type_obj[input_test_data.timelimitType] || 'totalTime',
|
||||
advancedSetting: tmp_advanced_setting,
|
||||
messageEncoding: input_test_data.encode || 'utf-8',
|
||||
},
|
||||
(tmp_input_ajax_status, tmp_input_data_obj, tmp_input_xhr) => {
|
||||
tmp_ajax_xhr = tmp_input_xhr;
|
||||
if (tmp_input_ajax_status === 'ajaxTimeout') {
|
||||
tmp_report_data.general.status = 'timeout';
|
||||
return;
|
||||
}
|
||||
let tmp_http_total_time = _ApiUtil.getMicrosToMs(
|
||||
tmp_input_data_obj.summaryObj.startAt,
|
||||
tmp_input_data_obj.summaryObj.endAt
|
||||
);
|
||||
tmp_report_data.general.timingSummary = [_ApiUtil.getHttpTiming(tmp_input_data_obj.summaryObj)];
|
||||
switch (tmp_input_ajax_status) {
|
||||
case 'ajax_end': {
|
||||
tmp_report_data.requestHeaders = tmp_ajax_xhr.getHeaders();
|
||||
if (input_test_data.redirect || !input_test_data.hasOwnProperty('redirect')) {
|
||||
let tmp_redirect_class = new _RedirectClass.core();
|
||||
let tmp_redirect_obj = tmp_redirect_class.structureAjaxFun(
|
||||
tmp_test_opts,
|
||||
tmp_multi_form ? tmp_multi_form : tmp_post_data,
|
||||
tmp_input_data_obj.res
|
||||
);
|
||||
if (tmp_redirect_obj) {
|
||||
tmp_report_data.general.redirectTimes++;
|
||||
if (tmp_fn_check_is_illegal_url(tmp_redirect_obj.options.hostname, tmp_http_total_time)) return;
|
||||
_HttpPackageClass.socketReduce(
|
||||
{
|
||||
postData: tmp_redirect_obj.postData,
|
||||
isMuti: tmp_test_data.isMuti,
|
||||
options: tmp_redirect_obj.options,
|
||||
timeoutLimit: input_test_data.timelimit - tmp_http_total_time,
|
||||
globalHeader: input_opts.globalHeader,
|
||||
advancedSetting: tmp_advanced_setting,
|
||||
messageEncoding: input_test_data.encode || 'utf-8',
|
||||
},
|
||||
(tmpInputRedirectAjaxStatus, tmpInputRedirectDataObj) => {
|
||||
if (tmpInputRedirectAjaxStatus === 'ajaxTimeout') {
|
||||
tmp_report_data.general.status = 'timeout';
|
||||
return;
|
||||
}
|
||||
let tmpRedirectHttpTotalTime = _ApiUtil.getMicrosToMs(
|
||||
tmpInputRedirectDataObj.summaryObj.startAt,
|
||||
tmpInputRedirectDataObj.summaryObj.endAt
|
||||
);
|
||||
tmp_report_data.general.timingSummary.push(
|
||||
_ApiUtil.getHttpTiming(tmpInputRedirectDataObj.summaryObj)
|
||||
);
|
||||
switch (tmpInputRedirectAjaxStatus) {
|
||||
case 'ajax_end': {
|
||||
tmp_fn_ajax_end(tmpInputRedirectDataObj.res, {
|
||||
chunk: tmpInputRedirectDataObj.chunk,
|
||||
str: tmpInputRedirectDataObj.responseStr,
|
||||
totalTime: tmp_http_total_time + tmpRedirectHttpTotalTime,
|
||||
contentDeliveryTiming: _ApiUtil.getMicrosToMs(
|
||||
tmpInputRedirectDataObj.summaryObj.firstByteTiming,
|
||||
tmpInputRedirectDataObj.summaryObj.endAt
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ajaxErr': {
|
||||
tmp_fn_ajax_err(
|
||||
tmpInputRedirectDataObj.errObj,
|
||||
tmp_http_total_time + tmpRedirectHttpTotalTime
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmp_fn_ajax_end(tmp_input_data_obj.res, {
|
||||
chunk: tmp_input_data_obj.chunk,
|
||||
str: tmp_input_data_obj.responseStr,
|
||||
totalTime: tmp_http_total_time,
|
||||
contentDeliveryTiming: _ApiUtil.getMicrosToMs(
|
||||
tmp_input_data_obj.summaryObj.firstByteTiming,
|
||||
tmp_input_data_obj.summaryObj.endAt
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ajaxErr': {
|
||||
tmp_fn_ajax_err(tmp_input_data_obj.errObj, tmp_http_total_time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
_HttpPackageClass.clearAjaxTimeout();
|
||||
console.error(new Date() + 'automated pro.js 433:', e);
|
||||
tmp_report_data.reportList.push({
|
||||
type: 'error',
|
||||
content: e.name + ':' + e.message,
|
||||
});
|
||||
resolve(tmp_fn_parse_ajax_resolve(0));
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
tmp_result = response;
|
||||
})
|
||||
.catch((error) => {
|
||||
tmp_result = error;
|
||||
});
|
||||
if (input_test_data.delay) {
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(
|
||||
() => {
|
||||
resolve('success');
|
||||
},
|
||||
input_test_data.delay > CONFIG.MAX_TIME_DELAY ? CONFIG.MAX_TIME_DELAY : input_test_data.delay || 0
|
||||
);
|
||||
});
|
||||
}
|
||||
input_return_callback(tmp_result);
|
||||
}
|
||||
//异步操作,作用于纤程唤起
|
||||
wakeTopThread(input_text, input_current_fibers) {
|
||||
this.EXEC_RESULT = input_text;
|
||||
if (input_current_fibers) input_current_fibers.run();
|
||||
}
|
||||
}
|
||||
exports.core = Main;
|
||||
})();
|
@ -1,458 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
class mainClass {
|
||||
constructor() {}
|
||||
byContent(buf) {
|
||||
if (!(buf && buf.length > 1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) {
|
||||
return {
|
||||
ext: 'jpg',
|
||||
mime: 'image/jpeg'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) {
|
||||
return {
|
||||
ext: 'png',
|
||||
mime: 'image/png'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) {
|
||||
return {
|
||||
ext: 'gif',
|
||||
mime: 'image/gif'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) {
|
||||
return {
|
||||
ext: 'webp',
|
||||
mime: 'image/webp'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x46 && buf[1] === 0x4C && buf[2] === 0x49 && buf[3] === 0x46) {
|
||||
return {
|
||||
ext: 'flif',
|
||||
mime: 'image/flif'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `tif` check
|
||||
if (((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) && buf[8] === 0x43 && buf[9] === 0x52) {
|
||||
return {
|
||||
ext: 'cr2',
|
||||
mime: 'image/x-canon-cr2'
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) {
|
||||
return {
|
||||
ext: 'tif',
|
||||
mime: 'image/tiff'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x42 && buf[1] === 0x4D) {
|
||||
return {
|
||||
ext: 'bmp',
|
||||
mime: 'image/bmp'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0xBC) {
|
||||
return {
|
||||
ext: 'jxr',
|
||||
mime: 'image/vnd.ms-photo'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x38 && buf[1] === 0x42 && buf[2] === 0x50 && buf[3] === 0x53) {
|
||||
return {
|
||||
ext: 'psd',
|
||||
mime: 'image/vnd.adobe.photoshop'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `zip` check
|
||||
if (buf[0] === 0x50 && buf[1] === 0x4B && buf[2] === 0x3 && buf[3] === 0x4 && buf[30] === 0x6D && buf[31] === 0x69 && buf[32] === 0x6D && buf[33] === 0x65 && buf[34] === 0x74 && buf[35] === 0x79 && buf[36] === 0x70 && buf[37] === 0x65 && buf[38] === 0x61 && buf[39] === 0x70 && buf[40] === 0x70 && buf[41] === 0x6C && buf[42] === 0x69 && buf[43] === 0x63 && buf[44] === 0x61 && buf[45] === 0x74 && buf[46] === 0x69 && buf[47] === 0x6F && buf[48] === 0x6E && buf[49] === 0x2F && buf[50] === 0x65 && buf[51] === 0x70 && buf[52] === 0x75 && buf[53] === 0x62 && buf[54] === 0x2B && buf[55] === 0x7A && buf[56] === 0x69 && buf[57] === 0x70) {
|
||||
return {
|
||||
ext: 'epub',
|
||||
mime: 'application/epub+zip'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `zip` check
|
||||
// assumes signed .xpi from addons.mozilla.org
|
||||
if (buf[0] === 0x50 && buf[1] === 0x4B && buf[2] === 0x3 && buf[3] === 0x4 && buf[30] === 0x4D && buf[31] === 0x45 && buf[32] === 0x54 && buf[33] === 0x41 && buf[34] === 0x2D && buf[35] === 0x49 && buf[36] === 0x4E && buf[37] === 0x46 && buf[38] === 0x2F && buf[39] === 0x6D && buf[40] === 0x6F && buf[41] === 0x7A && buf[42] === 0x69 && buf[43] === 0x6C && buf[44] === 0x6C && buf[45] === 0x61 && buf[46] === 0x2E && buf[47] === 0x72 && buf[48] === 0x73 && buf[49] === 0x61) {
|
||||
return {
|
||||
ext: 'xpi',
|
||||
mime: 'application/x-xpinstall'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x50 && buf[1] === 0x4B && (buf[2] === 0x3 || buf[2] === 0x5 || buf[2] === 0x7) && (buf[3] === 0x4 || buf[3] === 0x6 || buf[3] === 0x8)) {
|
||||
return {
|
||||
ext: 'zip',
|
||||
mime: 'application/zip'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[257] === 0x75 && buf[258] === 0x73 && buf[259] === 0x74 && buf[260] === 0x61 && buf[261] === 0x72) {
|
||||
return {
|
||||
ext: 'tar',
|
||||
mime: 'application/x-tar'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x61 && buf[2] === 0x72 && buf[3] === 0x21 && buf[4] === 0x1A && buf[5] === 0x7 && (buf[6] === 0x0 || buf[6] === 0x1)) {
|
||||
return {
|
||||
ext: 'rar',
|
||||
mime: 'application/x-rar-compressed'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x8) {
|
||||
return {
|
||||
ext: 'gz',
|
||||
mime: 'application/gzip'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x42 && buf[1] === 0x5A && buf[2] === 0x68) {
|
||||
return {
|
||||
ext: 'bz2',
|
||||
mime: 'application/x-bzip2'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x37 && buf[1] === 0x7A && buf[2] === 0xBC && buf[3] === 0xAF && buf[4] === 0x27 && buf[5] === 0x1C) {
|
||||
return {
|
||||
ext: '7z',
|
||||
mime: 'application/x-7z-compressed'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x78 && buf[1] === 0x01) {
|
||||
return {
|
||||
ext: 'dmg',
|
||||
mime: 'application/x-apple-diskimage'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && (buf[3] === 0x18 || buf[3] === 0x20) && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) ||
|
||||
(buf[0] === 0x33 && buf[1] === 0x67 && buf[2] === 0x70 && buf[3] === 0x35) ||
|
||||
(buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x6D && buf[9] === 0x70 && buf[10] === 0x34 && buf[11] === 0x32 && buf[16] === 0x6D && buf[17] === 0x70 && buf[18] === 0x34 && buf[19] === 0x31 && buf[20] === 0x6D && buf[21] === 0x70 && buf[22] === 0x34 && buf[23] === 0x32 && buf[24] === 0x69 && buf[25] === 0x73 && buf[26] === 0x6F && buf[27] === 0x6D) ||
|
||||
(buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x69 && buf[9] === 0x73 && buf[10] === 0x6F && buf[11] === 0x6D) ||
|
||||
(buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1c && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x6D && buf[9] === 0x70 && buf[10] === 0x34 && buf[11] === 0x32 && buf[12] === 0x0 && buf[13] === 0x0 && buf[14] === 0x0 && buf[15] === 0x0)
|
||||
) {
|
||||
return {
|
||||
ext: 'mp4',
|
||||
mime: 'video/mp4'
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x56)) {
|
||||
return {
|
||||
ext: 'm4v',
|
||||
mime: 'video/x-m4v'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4D && buf[1] === 0x54 && buf[2] === 0x68 && buf[3] === 0x64) {
|
||||
return {
|
||||
ext: 'mid',
|
||||
mime: 'audio/midi'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before the `webm` check
|
||||
if (buf[31] === 0x6D && buf[32] === 0x61 && buf[33] === 0x74 && buf[34] === 0x72 && buf[35] === 0x6f && buf[36] === 0x73 && buf[37] === 0x6B && buf[38] === 0x61) {
|
||||
return {
|
||||
ext: 'mkv',
|
||||
mime: 'video/x-matroska'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x1A && buf[1] === 0x45 && buf[2] === 0xDF && buf[3] === 0xA3) {
|
||||
return {
|
||||
ext: 'webm',
|
||||
mime: 'video/webm'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x14 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) {
|
||||
return {
|
||||
ext: 'mov',
|
||||
mime: 'video/quicktime'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x41 && buf[9] === 0x56 && buf[10] === 0x49) {
|
||||
return {
|
||||
ext: 'avi',
|
||||
mime: 'video/x-msvideo'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x30 && buf[1] === 0x26 && buf[2] === 0xB2 && buf[3] === 0x75 && buf[4] === 0x8E && buf[5] === 0x66 && buf[6] === 0xCF && buf[7] === 0x11 && buf[8] === 0xA6 && buf[9] === 0xD9) {
|
||||
return {
|
||||
ext: 'wmv',
|
||||
mime: 'video/x-ms-wmv'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x1 && buf[3].toString(16)[0] === 'b') {
|
||||
return {
|
||||
ext: 'mpg',
|
||||
mime: 'video/mpeg'
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x49 && buf[1] === 0x44 && buf[2] === 0x33) || (buf[0] === 0xFF && buf[1] === 0xfb)) {
|
||||
return {
|
||||
ext: 'mp3',
|
||||
mime: 'audio/mpeg'
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x41) || (buf[0] === 0x4D && buf[1] === 0x34 && buf[2] === 0x41 && buf[3] === 0x20)) {
|
||||
return {
|
||||
ext: 'm4a',
|
||||
mime: 'audio/m4a'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `ogg` check
|
||||
if (buf[28] === 0x4F && buf[29] === 0x70 && buf[30] === 0x75 && buf[31] === 0x73 && buf[32] === 0x48 && buf[33] === 0x65 && buf[34] === 0x61 && buf[35] === 0x64) {
|
||||
return {
|
||||
ext: 'opus',
|
||||
mime: 'audio/opus'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4F && buf[1] === 0x67 && buf[2] === 0x67 && buf[3] === 0x53) {
|
||||
return {
|
||||
ext: 'ogg',
|
||||
mime: 'audio/ogg'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43) {
|
||||
return {
|
||||
ext: 'flac',
|
||||
mime: 'audio/x-flac'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45) {
|
||||
return {
|
||||
ext: 'wav',
|
||||
mime: 'audio/x-wav'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D && buf[4] === 0x52 && buf[5] === 0x0A) {
|
||||
return {
|
||||
ext: 'amr',
|
||||
mime: 'audio/amr'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x25 && buf[1] === 0x50 && buf[2] === 0x44 && buf[3] === 0x46) {
|
||||
return {
|
||||
ext: 'pdf',
|
||||
mime: 'application/pdf'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4D && buf[1] === 0x5A) {
|
||||
return {
|
||||
ext: 'exe',
|
||||
mime: 'application/x-msdownload'
|
||||
};
|
||||
}
|
||||
|
||||
if ((buf[0] === 0x43 || buf[0] === 0x46) && buf[1] === 0x57 && buf[2] === 0x53) {
|
||||
return {
|
||||
ext: 'swf',
|
||||
mime: 'application/x-shockwave-flash'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x7B && buf[1] === 0x5C && buf[2] === 0x72 && buf[3] === 0x74 && buf[4] === 0x66) {
|
||||
return {
|
||||
ext: 'rtf',
|
||||
mime: 'application/rtf'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x46) &&
|
||||
(
|
||||
(buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) ||
|
||||
(buf[4] === 0x4F && buf[5] === 0x54 && buf[6] === 0x54 && buf[7] === 0x4F)
|
||||
)
|
||||
) {
|
||||
return {
|
||||
ext: 'woff',
|
||||
mime: 'application/font-woff'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x32) &&
|
||||
(
|
||||
(buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) ||
|
||||
(buf[4] === 0x4F && buf[5] === 0x54 && buf[6] === 0x54 && buf[7] === 0x4F)
|
||||
)
|
||||
) {
|
||||
return {
|
||||
ext: 'woff2',
|
||||
mime: 'application/font-woff'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[34] === 0x4C && buf[35] === 0x50) &&
|
||||
(
|
||||
(buf[8] === 0x00 && buf[9] === 0x00 && buf[10] === 0x01) ||
|
||||
(buf[8] === 0x01 && buf[9] === 0x00 && buf[10] === 0x02) ||
|
||||
(buf[8] === 0x02 && buf[9] === 0x00 && buf[10] === 0x02)
|
||||
)
|
||||
) {
|
||||
return {
|
||||
ext: 'eot',
|
||||
mime: 'application/octet-stream'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x00 && buf[1] === 0x01 && buf[2] === 0x00 && buf[3] === 0x00 && buf[4] === 0x00) {
|
||||
return {
|
||||
ext: 'ttf',
|
||||
mime: 'application/font-sfnt'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4F && buf[1] === 0x54 && buf[2] === 0x54 && buf[3] === 0x4F && buf[4] === 0x00) {
|
||||
return {
|
||||
ext: 'otf',
|
||||
mime: 'application/font-sfnt'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x00 && buf[1] === 0x00 && buf[2] === 0x01 && buf[3] === 0x00) {
|
||||
return {
|
||||
ext: 'ico',
|
||||
mime: 'image/x-icon'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x46 && buf[1] === 0x4C && buf[2] === 0x56 && buf[3] === 0x01) {
|
||||
return {
|
||||
ext: 'flv',
|
||||
mime: 'video/x-flv'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x25 && buf[1] === 0x21) {
|
||||
return {
|
||||
ext: 'ps',
|
||||
mime: 'application/postscript'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xFD && buf[1] === 0x37 && buf[2] === 0x7A && buf[3] === 0x58 && buf[4] === 0x5A && buf[5] === 0x00) {
|
||||
return {
|
||||
ext: 'xz',
|
||||
mime: 'application/x-xz'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x53 && buf[1] === 0x51 && buf[2] === 0x4C && buf[3] === 0x69) {
|
||||
return {
|
||||
ext: 'sqlite',
|
||||
mime: 'application/x-sqlite3'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4E && buf[1] === 0x45 && buf[2] === 0x53 && buf[3] === 0x1A) {
|
||||
return {
|
||||
ext: 'nes',
|
||||
mime: 'application/x-nintendo-nes-rom'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x43 && buf[1] === 0x72 && buf[2] === 0x32 && buf[3] === 0x34) {
|
||||
return {
|
||||
ext: 'crx',
|
||||
mime: 'application/x-google-chrome-extension'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[0] === 0x4D && buf[1] === 0x53 && buf[2] === 0x43 && buf[3] === 0x46) ||
|
||||
(buf[0] === 0x49 && buf[1] === 0x53 && buf[2] === 0x63 && buf[3] === 0x28)
|
||||
) {
|
||||
return {
|
||||
ext: 'cab',
|
||||
mime: 'application/vnd.ms-cab-compressed'
|
||||
};
|
||||
}
|
||||
|
||||
// needs to be before `ar` check
|
||||
if (buf[0] === 0x21 && buf[1] === 0x3C && buf[2] === 0x61 && buf[3] === 0x72 && buf[4] === 0x63 && buf[5] === 0x68 && buf[6] === 0x3E && buf[7] === 0x0A && buf[8] === 0x64 && buf[9] === 0x65 && buf[10] === 0x62 && buf[11] === 0x69 && buf[12] === 0x61 && buf[13] === 0x6E && buf[14] === 0x2D && buf[15] === 0x62 && buf[16] === 0x69 && buf[17] === 0x6E && buf[18] === 0x61 && buf[19] === 0x72 && buf[20] === 0x79) {
|
||||
return {
|
||||
ext: 'deb',
|
||||
mime: 'application/x-deb'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x21 && buf[1] === 0x3C && buf[2] === 0x61 && buf[3] === 0x72 && buf[4] === 0x63 && buf[5] === 0x68 && buf[6] === 0x3E) {
|
||||
return {
|
||||
ext: 'ar',
|
||||
mime: 'application/x-unix-archive'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xED && buf[1] === 0xAB && buf[2] === 0xEE && buf[3] === 0xDB) {
|
||||
return {
|
||||
ext: 'rpm',
|
||||
mime: 'application/x-rpm'
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
(buf[0] === 0x1F && buf[1] === 0xA0) ||
|
||||
(buf[0] === 0x1F && buf[1] === 0x9D)
|
||||
) {
|
||||
return {
|
||||
ext: 'Z',
|
||||
mime: 'application/x-compress'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0x4C && buf[1] === 0x5A && buf[2] === 0x49 && buf[3] === 0x50) {
|
||||
return {
|
||||
ext: 'lz',
|
||||
mime: 'application/x-lzip'
|
||||
};
|
||||
}
|
||||
|
||||
if (buf[0] === 0xD0 && buf[1] === 0xCF && buf[2] === 0x11 && buf[3] === 0xE0 && buf[4] === 0xA1 && buf[5] === 0xB1 && buf[6] === 0x1A && buf[7] === 0xE1) {
|
||||
return {
|
||||
ext: 'msi',
|
||||
mime: 'application/x-msi'
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
exports.core = mainClass;
|
||||
})();
|
@ -1,289 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
var http = require("http"),
|
||||
https = require('https'),
|
||||
zlib = require('zlib'),
|
||||
iconv = require("iconv-lite");
|
||||
const _LibsEncrypt = require("./encrypt").core;
|
||||
global.PROXY_OBJ = {};
|
||||
const SOCKET_HANG_UP_TIP_TEXT_OBJ={
|
||||
SAAS_SERVER:"无法访问目标地址,请检查接口是否能被正常访问,如果您使用的是服务器方式测试,请检查测试服务器能否访问目标地址,是否存在网络隔离或防火墙,您可以尝试切换到 PC 客户端。",
|
||||
}
|
||||
class mainClass {
|
||||
constructor() {}
|
||||
/**
|
||||
* @desc 设置默认的请求头部
|
||||
*/
|
||||
setDefaultRequestHeader(inputHeaderObj = {}, inputOptions = {}) {
|
||||
let TMP_DEAFULT_HEADER_OBJ = {
|
||||
"User-Agent": "Eoapi",
|
||||
"Accept":"*/*"
|
||||
};
|
||||
if (inputOptions.sendNocacheToken) {
|
||||
TMP_DEAFULT_HEADER_OBJ["Cache-Control"] = "no-cache";
|
||||
}
|
||||
if (inputOptions.sendEoToken) {
|
||||
TMP_DEAFULT_HEADER_OBJ["Eo-Token"] = _LibsEncrypt.uuidGeneration();
|
||||
}
|
||||
let tmpRepareStr = JSON.stringify(inputHeaderObj);
|
||||
for (let key in TMP_DEAFULT_HEADER_OBJ) {
|
||||
let val = TMP_DEAFULT_HEADER_OBJ[key];
|
||||
if (!new RegExp(`"${key}":`, "i").test(tmpRepareStr)) {
|
||||
inputHeaderObj[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @desc ajax请求数据信息处理
|
||||
*/
|
||||
socketReduce(inputTestData = {}, inputCallback) {
|
||||
let _MainClass = this;
|
||||
async function main() {
|
||||
let tmpEncoding=inputTestData.messageEncoding||"utf-8";
|
||||
inputTestData.advancedSetting = inputTestData.advancedSetting || {
|
||||
requestRedirect: 1,
|
||||
sendNocacheToken: 0,
|
||||
checkSSL: 0,
|
||||
sendEoToken: 1
|
||||
};
|
||||
let tmpSummaryObj = {
|
||||
startAt: undefined,
|
||||
dnsTiming: undefined,
|
||||
tcpTiming: undefined,
|
||||
tlsTiming: undefined,
|
||||
requestSentTiming: undefined,
|
||||
firstByteTiming: undefined,
|
||||
endAt: undefined
|
||||
},
|
||||
tmpChunk = {
|
||||
array: [],
|
||||
length: 0
|
||||
},
|
||||
tmpAjaxXhr={}, tmpResponseString = "",
|
||||
tmpProtocol, tmpTimer;
|
||||
if (inputTestData.options.method == 'GET') {
|
||||
let tmpMatchUrlArr = inputTestData.options.path.split('?');
|
||||
if (tmpMatchUrlArr.length > 2) {
|
||||
tmpMatchUrlArr = tmpMatchUrlArr.slice(2).join('?').split('&');
|
||||
inputTestData.options.path += '&' + tmpMatchUrlArr[0];
|
||||
}
|
||||
}
|
||||
switch (inputTestData.options.protocol) {
|
||||
case 'https:': {
|
||||
if (!inputTestData.advancedSetting.checkSSL){
|
||||
inputTestData.options.rejectUnauthorized = false;
|
||||
inputTestData.options.minVersion="TLSv1";
|
||||
}
|
||||
tmpProtocol = https;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpProtocol = http;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_MainClass.setDefaultRequestHeader(inputTestData.options.headers, inputTestData.advancedSetting);
|
||||
let tmpPathArr = (inputTestData.options.path || "").split("?");
|
||||
tmpPathArr[0] = encodeURI(decodeURI(tmpPathArr[0]));
|
||||
inputTestData.options.path = tmpPathArr.join("?");
|
||||
try {
|
||||
tmpAjaxXhr = tmpProtocol.request(inputTestData.options, (tmpInputRes) => {
|
||||
tmpInputRes.on('data', (tmpInputChunk) => {
|
||||
tmpChunk.array.push(tmpInputChunk);
|
||||
tmpChunk.length += tmpInputChunk.length;
|
||||
tmpResponseString += tmpInputChunk;
|
||||
});
|
||||
tmpInputRes.once('readable', () => {
|
||||
if (inputTestData.timeoutLimitType === "firstByte" && tmpTimer) { //首字节时间超时
|
||||
clearTimeout(tmpTimer);
|
||||
}
|
||||
tmpSummaryObj.firstByteTiming = process.hrtime();
|
||||
})
|
||||
tmpInputRes.on('end', () => {
|
||||
tmpSummaryObj.endAt = process.hrtime();
|
||||
if (tmpTimer) {
|
||||
clearTimeout(tmpTimer);
|
||||
}
|
||||
if (tmpInputRes.headers['set-cookie']) {
|
||||
_MainClass.setCookieToHeaders({
|
||||
'cookie': tmpInputRes.headers['set-cookie'].join(';')
|
||||
}, inputTestData.options.hostname, inputTestData.globalHeader);
|
||||
}
|
||||
let tmpBuffer=Buffer.concat(tmpChunk.array, tmpChunk.length);
|
||||
let tmpFnZlibCallback=(inputErr,inputBuff)=>{
|
||||
if(!inputErr){
|
||||
tmpBuffer=inputBuff;
|
||||
}
|
||||
if(tmpEncoding==="gbk"){
|
||||
tmpBuffer=Buffer.from(iconv.decode(tmpBuffer,'gbk'));
|
||||
}
|
||||
let tmpResponseStr;
|
||||
if(inputTestData.pckSplitByHeader){//是否分割报文头
|
||||
tmpResponseStr=tmpBuffer.toString("utf8",4);
|
||||
}else{
|
||||
tmpResponseStr=tmpBuffer.toString('utf8');
|
||||
}
|
||||
inputCallback("ajax_end", {
|
||||
res: tmpInputRes,
|
||||
chunk: tmpChunk,
|
||||
responseStr: tmpResponseStr,
|
||||
summaryObj: tmpSummaryObj
|
||||
}, tmpAjaxXhr)
|
||||
}
|
||||
switch (tmpInputRes.headers['content-encoding']) {
|
||||
case 'br': {
|
||||
zlib.brotliDecompress(tmpBuffer, tmpFnZlibCallback)
|
||||
break;
|
||||
}
|
||||
case 'gzip': {
|
||||
zlib.gunzip(tmpBuffer, tmpFnZlibCallback)
|
||||
break;
|
||||
}
|
||||
case 'deflate': {
|
||||
zlib.inflate(tmpBuffer, tmpFnZlibCallback)
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpFnZlibCallback(true,tmpBuffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
} catch (REQUEST_ERR) {
|
||||
inputCallback("ajaxErr", {
|
||||
summaryObj: tmpSummaryObj,
|
||||
errObj: REQUEST_ERR
|
||||
}, tmpAjaxXhr);
|
||||
return;
|
||||
}
|
||||
|
||||
tmpAjaxXhr.on('socket', (socket) => {
|
||||
tmpSummaryObj.startAt = process.hrtime();
|
||||
_MainClass.ajaxTimer = tmpTimer = setTimeout(function () {
|
||||
tmpSummaryObj.endAt = process.hrtime();
|
||||
inputCallback("ajaxTimeout", {
|
||||
summaryObj: tmpSummaryObj
|
||||
}, tmpAjaxXhr)
|
||||
clearTimeout(tmpTimer);
|
||||
tmpAjaxXhr.abort();
|
||||
}, inputTestData.timeoutLimit);
|
||||
socket.on('lookup', () => {
|
||||
tmpSummaryObj.dnsTiming = process.hrtime()
|
||||
})
|
||||
socket.on('connect', () => {
|
||||
tmpSummaryObj.tcpTiming = process.hrtime()
|
||||
})
|
||||
socket.on('secureConnect', () => {
|
||||
tmpSummaryObj.tlsTiming = process.hrtime();
|
||||
})
|
||||
});
|
||||
|
||||
tmpAjaxXhr.on('error', (tmpInputErr) => {
|
||||
if (tmpTimer) clearTimeout(tmpTimer);
|
||||
inputCallback("ajaxErr", {
|
||||
summaryObj: tmpSummaryObj,
|
||||
errObj: /getaddrinfo enotfound/i.test(tmpInputErr.message) ? {
|
||||
name: "API请求地址有误",
|
||||
message: "请检查是否正确填写URL以及URL是否允许访问"
|
||||
} : /socket hang up/i.test(tmpInputErr.message) ? {
|
||||
name: "请求错误",
|
||||
message: SOCKET_HANG_UP_TIP_TEXT_OBJ["SAAS_SERVER"]||"无法访问目标地址,请检查接口是否能被正常访问,是否存在网络隔离或防火墙。"
|
||||
} :tmpInputErr
|
||||
}, tmpAjaxXhr)
|
||||
});
|
||||
if (!inputTestData.postData) {
|
||||
tmpAjaxXhr.end();
|
||||
} else if (inputTestData.isMuti) {
|
||||
inputTestData.postData.getLength((tmpInputErr, tmpInputLength) => {
|
||||
if (!tmpInputErr) {
|
||||
tmpAjaxXhr.setHeader('content-length', tmpInputLength);
|
||||
}
|
||||
inputTestData.postData.pipe(tmpAjaxXhr);
|
||||
})
|
||||
} else {
|
||||
if(typeof inputTestData.postData==="string"){
|
||||
if(tmpEncoding==="gbk"){
|
||||
inputTestData.postData=iconv.encode(inputTestData.postData,'gbk');
|
||||
tmpAjaxXhr.setHeader('Content-Length', Buffer.byteLength(inputTestData.postData));
|
||||
}else{
|
||||
inputTestData.postData=Buffer.from(inputTestData.postData);
|
||||
}
|
||||
if(inputTestData.pckSplitByHeader)inputTestData.postData=_MainClass.writeInt(inputTestData.postData,Buffer.byteLength(inputTestData.postData,tmpEncoding));
|
||||
}
|
||||
tmpAjaxXhr.write(inputTestData.postData);
|
||||
tmpAjaxXhr.end();
|
||||
}
|
||||
}
|
||||
main();
|
||||
}
|
||||
writeInt(inputBuff,inputLen){
|
||||
let tmpBytes=new Array(4);
|
||||
tmpBytes[0]=inputLen >> 24;
|
||||
tmpBytes[1]=inputLen >> 16;
|
||||
tmpBytes[2]=inputLen >> 8;
|
||||
tmpBytes[3]=inputLen;
|
||||
return Buffer.concat([new Buffer(tmpBytes),inputBuff]);
|
||||
}
|
||||
/**
|
||||
* @desc 将cookie注入headers
|
||||
*/
|
||||
setCookieToHeaders(inputHeaders, inputDomain, inputGlobalObj) {
|
||||
inputGlobalObj = inputGlobalObj || {};
|
||||
let tmpReturnObj, tmpSplitCookieArr = [],
|
||||
tmpSplitCookieParamArr = [],
|
||||
tmpTargetCookirStr = "";
|
||||
try {
|
||||
tmpReturnObj = JSON.parse(JSON.stringify(inputHeaders || {}).replace(/"cookie":/i, '"cookie":'));
|
||||
if(!inputGlobalObj[inputDomain]){
|
||||
for(let key in inputGlobalObj){
|
||||
if(inputDomain.indexOf(key)>-1){
|
||||
inputDomain=key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmpReturnObj.cookie) {
|
||||
tmpSplitCookieArr = tmpReturnObj.cookie.split(';');
|
||||
if (inputGlobalObj[inputDomain]) {
|
||||
if (inputGlobalObj[inputDomain]['cookie']) {
|
||||
tmpTargetCookirStr = inputGlobalObj[inputDomain]['cookie'][0] || '';
|
||||
for (let key in tmpSplitCookieArr) {
|
||||
if (tmpSplitCookieArr[key]) {
|
||||
let splitString = tmpSplitCookieArr[key].split('=')[0];
|
||||
if (tmpTargetCookirStr.indexOf(splitString) > -1) {
|
||||
tmpSplitCookieParamArr = tmpTargetCookirStr.split(splitString + '=');
|
||||
if (tmpSplitCookieParamArr.length > 1) {
|
||||
tmpTargetCookirStr = tmpTargetCookirStr.replace(splitString + '=' + tmpSplitCookieParamArr[1].split(';')[0], tmpSplitCookieArr[key]);
|
||||
} else {
|
||||
tmpTargetCookirStr = tmpTargetCookirStr.replace(splitString, tmpSplitCookieArr[key]);
|
||||
}
|
||||
} else {
|
||||
tmpTargetCookirStr = tmpTargetCookirStr+(/;$/.test(tmpTargetCookirStr)?"":';')+tmpSplitCookieArr[key] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputGlobalObj[inputDomain]['cookie'] = [tmpTargetCookirStr];
|
||||
} else {
|
||||
inputGlobalObj[inputDomain]['cookie'] = [tmpReturnObj.cookie];
|
||||
}
|
||||
} else {
|
||||
inputGlobalObj[inputDomain] = {
|
||||
cookie: [tmpReturnObj.cookie]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {}
|
||||
if (inputGlobalObj[inputDomain]) {
|
||||
tmpReturnObj.cookie = inputGlobalObj[inputDomain]['cookie'].join(';');
|
||||
}
|
||||
return tmpReturnObj;
|
||||
}
|
||||
clearAjaxTimeout() {
|
||||
if (this.ajaxTimer) clearTimeout(this.ajaxTimer);
|
||||
}
|
||||
}
|
||||
exports.core = mainClass;
|
||||
})();
|
@ -1,73 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
let url = require("url");
|
||||
|
||||
class redirectClass {
|
||||
constructor() {}
|
||||
checkRedirectStatusFun(inputRes) {
|
||||
let tmpLocaltion=inputRes.headers['location'];
|
||||
if (inputRes.statusCode >= 300 && inputRes.statusCode < 400 && tmpLocaltion) {
|
||||
return {
|
||||
status:'3xx',
|
||||
uri:tmpLocaltion
|
||||
}
|
||||
}
|
||||
return {
|
||||
status:'xxx'
|
||||
}
|
||||
}
|
||||
structureAjaxFun(inputOption,inputPostData,inputRes){
|
||||
let tmp={
|
||||
redirectStatusObject:this.checkRedirectStatusFun(inputRes),
|
||||
callbackArg:{
|
||||
postData:typeof inputPostData==="string"?inputPostData:Object.assign({},inputPostData),
|
||||
options:null
|
||||
},
|
||||
protocol:null
|
||||
}
|
||||
switch(tmp.redirectStatusObject.status){
|
||||
case '3xx':{
|
||||
tmp.callbackArg.options=Object.assign({},inputOption,url.parse(tmp.redirectStatusObject.uri));
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!tmp.callbackArg.options.hostname){
|
||||
tmp.callbackArg.options.hostname=inputOption.hostname;
|
||||
tmp.callbackArg.options.protocol=inputOption.protocol;
|
||||
tmp.callbackArg.options.port=inputOption.port;
|
||||
tmp.callbackArg.options.auth=inputOption.auth;
|
||||
}
|
||||
if (inputRes.statusCode !== 307) {
|
||||
delete tmp.callbackArg.postData;
|
||||
if (tmp.callbackArg.options.headers) {
|
||||
for(let key in tmp.callbackArg.options.headers){
|
||||
if(/(host)|(content-type)|(content-length)/i.test(key)){
|
||||
delete tmp.callbackArg.options.headers[key];
|
||||
}
|
||||
}
|
||||
if (tmp.callbackArg.options.hostname !== inputOption.hostname.split(':')[0]) {
|
||||
for(let key in tmp.callbackArg.options.headers){
|
||||
if(/(authorization)/i.test(key)){
|
||||
delete tmp.callbackArg.options.headers[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch(inputRes.statusCode){
|
||||
case 301:
|
||||
case 302:
|
||||
case 303:{
|
||||
tmp.callbackArg.options.method="GET";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tmp.callbackArg;
|
||||
}
|
||||
}
|
||||
exports.core = redirectClass;
|
||||
})();
|
@ -1,3 +0,0 @@
|
||||
if (parseInt(process.versions.node.split('.')[0]) < 6) throw new Error('vm2 requires Node.js version 6 or newer.');
|
||||
|
||||
module.exports = require('./lib/main');
|
@ -1,35 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const pa = require('path');
|
||||
|
||||
const {NodeVM, VMError} = require('../');
|
||||
|
||||
if (process.argv[2]) {
|
||||
const path = pa.resolve(process.argv[2]);
|
||||
|
||||
console.log(`\x1B[90m[vm] creating VM for ${path}\x1B[39m`);
|
||||
const started = Date.now();
|
||||
|
||||
try {
|
||||
NodeVM.file(path, {
|
||||
verbose: true,
|
||||
require: {
|
||||
external: true
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\x1B[90m[vm] VM completed in ${Date.now() - started}ms\x1B[39m`);
|
||||
} catch (ex) {
|
||||
if (ex instanceof VMError) {
|
||||
console.error(`\x1B[31m[vm:error] ${ex.message}\x1B[39m`);
|
||||
} else {
|
||||
const {stack} = ex;
|
||||
|
||||
if (stack) {
|
||||
console.error(`\x1B[31m[vm:error] ${stack}\x1B[39m`);
|
||||
} else {
|
||||
console.error(`\x1B[31m[vm:error] ${ex}\x1B[39m`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,815 +0,0 @@
|
||||
/* global host */
|
||||
/* eslint-disable block-spacing, no-multi-spaces, brace-style, no-array-constructor, new-cap, no-use-before-define */
|
||||
|
||||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-invalid-this, no-shadow
|
||||
const global = this;
|
||||
|
||||
const local = host.Object.create(null);
|
||||
local.Object = Object;
|
||||
local.Array = Array;
|
||||
local.Reflect = host.Object.create(null);
|
||||
local.Reflect.ownKeys = Reflect.ownKeys;
|
||||
local.Reflect.enumerable = Reflect.enumerate;
|
||||
local.Reflect.getPrototypeOf = Reflect.getPrototypeOf;
|
||||
local.Reflect.construct = Reflect.construct;
|
||||
local.Reflect.apply = Reflect.apply;
|
||||
local.Reflect.set = Reflect.set;
|
||||
local.Reflect.deleteProperty = Reflect.deleteProperty;
|
||||
local.Reflect.has = Reflect.has;
|
||||
|
||||
// global is originally prototype of host.Object so it can be used to climb up from the sandbox.
|
||||
Object.setPrototypeOf(global, Object.prototype);
|
||||
|
||||
Object.defineProperties(global, {
|
||||
global: {value: global},
|
||||
GLOBAL: {value: global},
|
||||
root: {value: global},
|
||||
isVM: {value: true}
|
||||
});
|
||||
|
||||
const DEBUG = false;
|
||||
const OPNA = 'Operation not allowed on contextified object.';
|
||||
const captureStackTrace = Error.captureStackTrace;
|
||||
|
||||
const FROZEN_TRAPS = host.Object.create(null);
|
||||
FROZEN_TRAPS.set = (target, key) => false;
|
||||
FROZEN_TRAPS.setPrototypeOf = (target, key) => false;
|
||||
FROZEN_TRAPS.defineProperty = (target, key) => false;
|
||||
FROZEN_TRAPS.deleteProperty = (target, key) => false;
|
||||
FROZEN_TRAPS.isExtensible = (target, key) => false;
|
||||
FROZEN_TRAPS.preventExtensions = (target) => false;
|
||||
|
||||
// Map of contextified objects to original objects
|
||||
const Contextified = new host.WeakMap();
|
||||
const Decontextified = new host.WeakMap();
|
||||
|
||||
// We can't use host's hasInstance method
|
||||
const hasInstance = local.Object[Symbol.hasInstance];
|
||||
function instanceOf(value, construct) {
|
||||
try {
|
||||
return host.Reflect.apply(hasInstance, construct, [value]);
|
||||
} catch (ex) {
|
||||
// Never pass the handled expcetion through!
|
||||
throw new VMError('Unable to perform instanceOf check.');
|
||||
// This exception actually never get to the user. It only instructs the caller to return null because we wasn't able to perform instanceOf check.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VMError definition.
|
||||
*/
|
||||
|
||||
class VMError extends Error {
|
||||
constructor(message, code) {
|
||||
super(message);
|
||||
|
||||
this.name = 'VMError';
|
||||
this.code = code;
|
||||
|
||||
captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
global.VMError = VMError;
|
||||
|
||||
/*
|
||||
* This function will throw a TypeError for accessing properties
|
||||
* on a strict mode function
|
||||
*/
|
||||
function throwCallerCalleeArgumentsAccess(key) {
|
||||
'use strict';
|
||||
throwCallerCalleeArgumentsAccess[key];
|
||||
return new VMError('Unreachable');
|
||||
}
|
||||
|
||||
/*
|
||||
* Proxy Helper
|
||||
*
|
||||
* Here we track Proxy creations so that we know for every proxy in the VM the
|
||||
* target. If the Proxy is given to decontextify we are going to lookup
|
||||
* the target and unsing this non proxy as target for the decontextify proxy.
|
||||
*
|
||||
*/
|
||||
|
||||
const ProxyHelper = host.Object.create(null);
|
||||
|
||||
// Marker for revoked proxy objects
|
||||
ProxyHelper.revoked = 'Revoked';
|
||||
|
||||
// Tracks for every proxy the target.
|
||||
ProxyHelper.tracker = new host.WeakMap();
|
||||
|
||||
// Gets the target of a proxy recursively until target is not any more a proxy
|
||||
ProxyHelper.getTarget = (proxy) => {
|
||||
let obj = proxy;
|
||||
let next;
|
||||
while ((next = ProxyHelper.tracker.get(obj))!==undefined) {
|
||||
obj = next;
|
||||
}
|
||||
// Target could be revoked.
|
||||
if (obj === ProxyHelper.revoked) {
|
||||
obj = host.Object.create(null);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
// This is not so nice, I would prefer globalThis.Proxy but globalThis is relatively new
|
||||
Proxy = ((ProxyFunc) => {
|
||||
// Handle Proxy.revocable()
|
||||
const ProxyRevocableHandler = host.Object.create(null);
|
||||
ProxyRevocableHandler.apply = (target, thiz, args) => {
|
||||
const proxyTarget = args[0];
|
||||
const ret = local.Reflect.apply(target, thiz, args);
|
||||
const proxy = ret.proxy;
|
||||
ProxyHelper.tracker.set(proxy, proxyTarget);
|
||||
const revokeHandler = host.Object.create(null);
|
||||
revokeHandler.apply = (rTarget, rThiz, rArgs) => {
|
||||
const rRet = local.Reflect.apply(rTarget, rThiz, rArgs);
|
||||
ProxyHelper.tracker.set(proxy, ProxyHelper.revoked);
|
||||
return rRet;
|
||||
};
|
||||
ret.revoke = new host.Proxy(ret.revoke, revokeHandler);
|
||||
return ret;
|
||||
};
|
||||
ProxyFunc.revocable = new host.Proxy(Proxy.revocable, ProxyRevocableHandler);
|
||||
// Handle new Proxy()
|
||||
const ProxyHandler = host.Object.create(null);
|
||||
ProxyHandler.construct = (target, args, newTarget) => {
|
||||
const proxyTarget = args[0];
|
||||
const proxy = local.Reflect.construct(target, args, newTarget);
|
||||
ProxyHelper.tracker.set(proxy, proxyTarget);
|
||||
return proxy;
|
||||
};
|
||||
return new host.Proxy(ProxyFunc, ProxyHandler);
|
||||
})(Proxy);
|
||||
|
||||
/**
|
||||
* Decontextify.
|
||||
*/
|
||||
|
||||
const Decontextify = host.Object.create(null);
|
||||
Decontextify.proxies = new host.WeakMap();
|
||||
|
||||
Decontextify.arguments = args => {
|
||||
if (!host.Array.isArray(args)) return new host.Array();
|
||||
|
||||
try {
|
||||
const arr = new host.Array();
|
||||
for (let i = 0, l = args.length; i < l; i++) arr[i] = Decontextify.value(args[i]);
|
||||
return arr;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through!
|
||||
return new host.Array();
|
||||
}
|
||||
};
|
||||
Decontextify.instance = (instance, klass, deepTraps, flags, toStringTag) => {
|
||||
if (typeof instance === 'function') return Decontextify.function(instance);
|
||||
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return instance;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (key === 'constructor') return klass;
|
||||
if (key === '__proto__') return klass.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return host.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return host.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return host.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return host.Object.prototype.__lookupSetter__;
|
||||
if (key === host.Symbol.toStringTag && toStringTag) return toStringTag;
|
||||
|
||||
try {
|
||||
return Decontextify.value(instance[key], null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return klass && klass.prototype;
|
||||
};
|
||||
|
||||
return Decontextify.object(instance, base, deepTraps, flags);
|
||||
};
|
||||
Decontextify.function = (fnc, traps, deepTraps, flags, mock) => {
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
// eslint-disable-next-line prefer-const
|
||||
let proxy;
|
||||
|
||||
base.apply = (target, context, args) => {
|
||||
context = Contextify.value(context);
|
||||
|
||||
// Set context of all arguments to vm's context.
|
||||
args = Contextify.arguments(args);
|
||||
|
||||
try {
|
||||
return Decontextify.value(fnc.apply(context, args));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.construct = (target, args, newTarget) => {
|
||||
args = Contextify.arguments(args);
|
||||
|
||||
try {
|
||||
return Decontextify.instance(new fnc(...args), proxy, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return fnc;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (mock && host.Object.prototype.hasOwnProperty.call(mock, key)) return mock[key];
|
||||
if (key === 'constructor') return host.Function;
|
||||
if (key === '__proto__') return host.Function.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return host.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return host.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return host.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return host.Object.prototype.__lookupSetter__;
|
||||
|
||||
try {
|
||||
return Decontextify.value(fnc[key], null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return host.Function.prototype;
|
||||
};
|
||||
|
||||
proxy = Decontextify.object(fnc, host.Object.assign(base, traps), deepTraps);
|
||||
return proxy;
|
||||
};
|
||||
Decontextify.object = (object, traps, deepTraps, flags, mock) => {
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return object;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (mock && host.Object.prototype.hasOwnProperty.call(mock, key)) return mock[key];
|
||||
if (key === 'constructor') return host.Object;
|
||||
if (key === '__proto__') return host.Object.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return host.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return host.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return host.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return host.Object.prototype.__lookupSetter__;
|
||||
|
||||
try {
|
||||
return Decontextify.value(object[key], null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.set = (target, key, value, receiver) => {
|
||||
value = Contextify.value(value);
|
||||
|
||||
try {
|
||||
return local.Reflect.set(object, key, value);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getOwnPropertyDescriptor = (target, prop) => {
|
||||
let def;
|
||||
|
||||
try {
|
||||
def = host.Object.getOwnPropertyDescriptor(object, prop);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
|
||||
// Following code prevents V8 to throw
|
||||
// TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '<prop>'
|
||||
// which is either non-existant or configurable in the proxy target
|
||||
|
||||
if (!def) {
|
||||
return undefined;
|
||||
} else if (def.get || def.set) {
|
||||
return {
|
||||
get: Decontextify.value(def.get) || undefined,
|
||||
set: Decontextify.value(def.set) || undefined,
|
||||
enumerable: def.enumerable === true,
|
||||
configurable: def.configurable === true
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
value: Decontextify.value(def.value),
|
||||
writable: def.writable === true,
|
||||
enumerable: def.enumerable === true,
|
||||
configurable: def.configurable === true
|
||||
};
|
||||
}
|
||||
};
|
||||
base.defineProperty = (target, key, descriptor) => {
|
||||
// There's a chance accessing a property throws an error so we must not access them
|
||||
// in try catch to prevent contextyfing local objects.
|
||||
|
||||
const propertyDescriptor = host.Object.create(null);
|
||||
if (descriptor.get || descriptor.set) {
|
||||
propertyDescriptor.get = Contextify.value(descriptor.get, null, deepTraps, flags) || undefined;
|
||||
propertyDescriptor.set = Contextify.value(descriptor.set, null, deepTraps, flags) || undefined;
|
||||
propertyDescriptor.enumerable = descriptor.enumerable === true;
|
||||
propertyDescriptor.configurable = descriptor.configurable === true;
|
||||
} else {
|
||||
propertyDescriptor.value = Contextify.value(descriptor.value, null, deepTraps, flags);
|
||||
propertyDescriptor.writable = descriptor.writable === true;
|
||||
propertyDescriptor.enumerable = descriptor.enumerable === true;
|
||||
propertyDescriptor.configurable = descriptor.configurable === true;
|
||||
}
|
||||
|
||||
try {
|
||||
return host.Object.defineProperty(target, key, propertyDescriptor);
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.deleteProperty = (target, prop) => {
|
||||
try {
|
||||
return Decontextify.value(local.Reflect.deleteProperty(object, prop));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return host.Object.prototype;
|
||||
};
|
||||
base.setPrototypeOf = (target) => {
|
||||
throw new host.Error(OPNA);
|
||||
};
|
||||
base.has = (target, key) => {
|
||||
try {
|
||||
return Decontextify.value(local.Reflect.has(object, key));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.isExtensible = target => {
|
||||
try {
|
||||
return Decontextify.value(local.Object.isExtensible(object));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.ownKeys = target => {
|
||||
try {
|
||||
return Decontextify.value(local.Reflect.ownKeys(object));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.preventExtensions = target => {
|
||||
try {
|
||||
local.Object.preventExtensions(object);
|
||||
return true;
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
base.enumerate = target => {
|
||||
try {
|
||||
return Decontextify.value(local.Reflect.enumerate(object));
|
||||
} catch (e) {
|
||||
throw Decontextify.value(e);
|
||||
}
|
||||
};
|
||||
|
||||
const proxy = new host.Proxy(ProxyHelper.getTarget(object), host.Object.assign(base, traps, deepTraps));
|
||||
Decontextify.proxies.set(object, proxy);
|
||||
Decontextified.set(proxy, object);
|
||||
return proxy;
|
||||
};
|
||||
Decontextify.value = (value, traps, deepTraps, flags, mock) => {
|
||||
try {
|
||||
if (Contextified.has(value)) {
|
||||
// Contextified object has returned back from vm
|
||||
return Contextified.get(value);
|
||||
} else if (Decontextify.proxies.has(value)) {
|
||||
// Decontextified proxy already exists, reuse
|
||||
return Decontextify.proxies.get(value);
|
||||
}
|
||||
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
if (value === null) {
|
||||
return null;
|
||||
} else if (instanceOf(value, Number)) { return host.Number(value);
|
||||
} else if (instanceOf(value, String)) { return host.String(value);
|
||||
} else if (instanceOf(value, Boolean)) { return host.Boolean(value);
|
||||
} else if (instanceOf(value, Date)) { return Decontextify.instance(value, host.Date, deepTraps, flags, 'Date');
|
||||
} else if (instanceOf(value, RangeError)) { return Decontextify.instance(value, host.RangeError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, ReferenceError)) { return Decontextify.instance(value, host.ReferenceError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, SyntaxError)) { return Decontextify.instance(value, host.SyntaxError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, TypeError)) { return Decontextify.instance(value, host.TypeError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, VMError)) { return Decontextify.instance(value, host.VMError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, EvalError)) { return Decontextify.instance(value, host.EvalError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, URIError)) { return Decontextify.instance(value, host.URIError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, Error)) { return Decontextify.instance(value, host.Error, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, Array)) { return value;
|
||||
} else if (instanceOf(value, RegExp)) { return Decontextify.instance(value, host.RegExp, deepTraps, flags, 'RegExp');
|
||||
} else if (instanceOf(value, Map)) { return Decontextify.instance(value, host.Map, deepTraps, flags, 'Map');
|
||||
} else if (instanceOf(value, WeakMap)) { return Decontextify.instance(value, host.WeakMap, deepTraps, flags, 'WeakMap');
|
||||
} else if (instanceOf(value, Set)) { return Decontextify.instance(value, host.Set, deepTraps, flags, 'Set');
|
||||
} else if (instanceOf(value, WeakSet)) { return Decontextify.instance(value, host.WeakSet, deepTraps, flags, 'WeakSet');
|
||||
} else if (Promise && instanceOf(value, Promise)) { return Decontextify.instance(value, host.Promise, deepTraps, flags, 'Promise');
|
||||
} else if (local.Reflect.getPrototypeOf(value) === null) {
|
||||
return Decontextify.instance(value, null, deepTraps, flags);
|
||||
} else {
|
||||
return Decontextify.object(value, traps, deepTraps, flags, mock);
|
||||
}
|
||||
case 'function':
|
||||
return Decontextify.function(value, traps, deepTraps, flags, mock);
|
||||
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
|
||||
default: // string, number, boolean, symbol
|
||||
return value;
|
||||
}
|
||||
} catch (ex) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Contextify.
|
||||
*/
|
||||
|
||||
const Contextify = host.Object.create(null);
|
||||
Contextify.proxies = new host.WeakMap();
|
||||
|
||||
Contextify.arguments = args => {
|
||||
if (!host.Array.isArray(args)) return new local.Array();
|
||||
|
||||
try {
|
||||
const arr = new local.Array();
|
||||
for (let i = 0, l = args.length; i < l; i++) arr[i] = Contextify.value(args[i]);
|
||||
return arr;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through!
|
||||
return new local.Array();
|
||||
}
|
||||
};
|
||||
Contextify.instance = (instance, klass, deepTraps, flags, toStringTag) => {
|
||||
if (typeof instance === 'function') return Contextify.function(instance);
|
||||
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return instance;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (key === 'constructor') return klass;
|
||||
if (key === '__proto__') return klass.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return local.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return local.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return local.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return local.Object.prototype.__lookupSetter__;
|
||||
if (key === host.Symbol.toStringTag && toStringTag) return toStringTag;
|
||||
|
||||
try {
|
||||
return Contextify.value(host.Reflect.get(instance, key), null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return klass && klass.prototype;
|
||||
};
|
||||
|
||||
return Contextify.object(instance, base, deepTraps, flags);
|
||||
};
|
||||
Contextify.function = (fnc, traps, deepTraps, flags, mock) => {
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
// eslint-disable-next-line prefer-const
|
||||
let proxy;
|
||||
|
||||
base.apply = (target, context, args) => {
|
||||
context = Decontextify.value(context);
|
||||
|
||||
// Set context of all arguments to host's context.
|
||||
args = Decontextify.arguments(args);
|
||||
|
||||
try {
|
||||
return Contextify.value(fnc.apply(context, args));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.construct = (target, args, newTarget) => {
|
||||
// Fixes buffer unsafe allocation for node v6/7
|
||||
if (host.version < 8 && fnc === host.Buffer && 'number' === typeof args[0]) {
|
||||
args[0] = new Array(args[0]).fill(0);
|
||||
}
|
||||
|
||||
args = Decontextify.arguments(args);
|
||||
|
||||
try {
|
||||
return Contextify.instance(new fnc(...args), proxy, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return fnc;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (mock && host.Object.prototype.hasOwnProperty.call(mock, key)) return mock[key];
|
||||
if (key === 'constructor') return Function;
|
||||
if (key === '__proto__') return Function.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return local.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return local.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return local.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return local.Object.prototype.__lookupSetter__;
|
||||
|
||||
if (key === 'caller' || key === 'callee' || key === 'arguments') throw throwCallerCalleeArgumentsAccess(key);
|
||||
|
||||
try {
|
||||
return Contextify.value(host.Reflect.get(fnc, key), null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return Function.prototype;
|
||||
};
|
||||
|
||||
proxy = Contextify.object(fnc, host.Object.assign(base, traps), deepTraps);
|
||||
return proxy;
|
||||
};
|
||||
Contextify.object = (object, traps, deepTraps, flags, mock) => {
|
||||
// We must not use normal object because there's a chance object already contains malicious code in the prototype
|
||||
const base = host.Object.create(null);
|
||||
|
||||
base.get = (target, key, receiver) => {
|
||||
try {
|
||||
if (key === 'vmProxyTarget' && DEBUG) return object;
|
||||
if (key === 'isVMProxy') return true;
|
||||
if (mock && host.Object.prototype.hasOwnProperty.call(mock, key)) return mock[key];
|
||||
if (key === 'constructor') return Object;
|
||||
if (key === '__proto__') return Object.prototype;
|
||||
} catch (e) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key === '__defineGetter__') return local.Object.prototype.__defineGetter__;
|
||||
if (key === '__defineSetter__') return local.Object.prototype.__defineSetter__;
|
||||
if (key === '__lookupGetter__') return local.Object.prototype.__lookupGetter__;
|
||||
if (key === '__lookupSetter__') return local.Object.prototype.__lookupSetter__;
|
||||
|
||||
try {
|
||||
return Contextify.value(host.Reflect.get(object, key), null, deepTraps, flags);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.set = (target, key, value, receiver) => {
|
||||
if (key === '__proto__') return false;
|
||||
if (flags && flags.protected && typeof value === 'function') return false;
|
||||
|
||||
value = Decontextify.value(value);
|
||||
|
||||
try {
|
||||
return host.Reflect.set(object, key, value);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getOwnPropertyDescriptor = (target, prop) => {
|
||||
let def;
|
||||
|
||||
try {
|
||||
def = host.Object.getOwnPropertyDescriptor(object, prop);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
|
||||
// Following code prevents V8 to throw
|
||||
// TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '<prop>'
|
||||
// which is either non-existant or configurable in the proxy target
|
||||
|
||||
if (!def) {
|
||||
return undefined;
|
||||
} else if (def.get || def.set) {
|
||||
return {
|
||||
get: Contextify.value(def.get, null, deepTraps, flags) || undefined,
|
||||
set: Contextify.value(def.set, null, deepTraps, flags) || undefined,
|
||||
enumerable: def.enumerable === true,
|
||||
configurable: def.configurable === true
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
value: Contextify.value(def.value, null, deepTraps, flags),
|
||||
writable: def.writable === true,
|
||||
enumerable: def.enumerable === true,
|
||||
configurable: def.configurable === true
|
||||
};
|
||||
}
|
||||
};
|
||||
base.defineProperty = (target, key, descriptor) => {
|
||||
// There's a chance accessing a property throws an error so we must not access them
|
||||
// in try catch to prevent contextyfing local objects.
|
||||
|
||||
const descGet = descriptor.get;
|
||||
const descSet = descriptor.set;
|
||||
const descValue = descriptor.value;
|
||||
|
||||
if (flags && flags.protected) {
|
||||
if (descGet || descSet || typeof descValue === 'function') return false;
|
||||
}
|
||||
|
||||
const propertyDescriptor = host.Object.create(null);
|
||||
if (descGet || descSet) {
|
||||
propertyDescriptor.get = Decontextify.value(descGet, null, deepTraps, flags) || undefined;
|
||||
propertyDescriptor.set = Decontextify.value(descSet, null, deepTraps, flags) || undefined;
|
||||
propertyDescriptor.enumerable = descriptor.enumerable === true;
|
||||
propertyDescriptor.configurable = descriptor.configurable === true;
|
||||
} else {
|
||||
propertyDescriptor.value = Decontextify.value(descValue, null, deepTraps, flags);
|
||||
propertyDescriptor.writable = descriptor.writable === true;
|
||||
propertyDescriptor.enumerable = descriptor.enumerable === true;
|
||||
propertyDescriptor.configurable = descriptor.configurable === true;
|
||||
}
|
||||
|
||||
try {
|
||||
return host.Object.defineProperty(object, key, propertyDescriptor);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.deleteProperty = (target, prop) => {
|
||||
try {
|
||||
return Contextify.value(host.Reflect.deleteProperty(object, prop));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.getPrototypeOf = (target) => {
|
||||
return local.Object.prototype;
|
||||
};
|
||||
base.setPrototypeOf = (target) => {
|
||||
throw new VMError(OPNA);
|
||||
};
|
||||
base.has = (target, key) => {
|
||||
try {
|
||||
return Contextify.value(host.Reflect.has(object, key));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.isExtensible = target => {
|
||||
try {
|
||||
return Contextify.value(host.Object.isExtensible(object));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.ownKeys = target => {
|
||||
try {
|
||||
return Contextify.value(host.Reflect.ownKeys(object));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.preventExtensions = target => {
|
||||
try {
|
||||
host.Object.preventExtensions(object);
|
||||
return true;
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
base.enumerate = target => {
|
||||
try {
|
||||
return Contextify.value(host.Reflect.enumerate(object));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
};
|
||||
|
||||
const proxy = new host.Proxy(object, host.Object.assign(base, traps, deepTraps));
|
||||
Contextify.proxies.set(object, proxy);
|
||||
Contextified.set(proxy, object);
|
||||
return proxy;
|
||||
};
|
||||
Contextify.value = (value, traps, deepTraps, flags, mock) => {
|
||||
try {
|
||||
if (Decontextified.has(value)) {
|
||||
// Decontextified object has returned back to vm
|
||||
return Decontextified.get(value);
|
||||
} else if (Contextify.proxies.has(value)) {
|
||||
// Contextified proxy already exists, reuse
|
||||
return Contextify.proxies.get(value);
|
||||
}
|
||||
|
||||
switch (typeof value) {
|
||||
case 'object':
|
||||
if (value === null) {
|
||||
return null;
|
||||
} else if (instanceOf(value, host.Number)) { return host.Number(value);
|
||||
} else if (instanceOf(value, host.String)) { return host.String(value);
|
||||
} else if (instanceOf(value, host.Boolean)) { return host.Boolean(value);
|
||||
} else if (instanceOf(value, host.Date)) { return Contextify.instance(value, Date, deepTraps, flags, 'Date');
|
||||
} else if (instanceOf(value, host.RangeError)) { return Contextify.instance(value, RangeError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.ReferenceError)) { return Contextify.instance(value, ReferenceError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.SyntaxError)) { return Contextify.instance(value, SyntaxError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.TypeError)) { return Contextify.instance(value, TypeError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.VMError)) { return Contextify.instance(value, VMError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.EvalError)) { return Contextify.instance(value, EvalError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.URIError)) { return Contextify.instance(value, URIError, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.Error)) { return Contextify.instance(value, Error, deepTraps, flags, 'Error');
|
||||
} else if (instanceOf(value, host.Array)) { return Contextify.instance(value, Array, deepTraps, flags, 'Array');
|
||||
} else if (instanceOf(value, host.RegExp)) { return Contextify.instance(value, RegExp, deepTraps, flags, 'RegExp');
|
||||
} else if (instanceOf(value, host.Map)) { return Contextify.instance(value, Map, deepTraps, flags, 'Map');
|
||||
} else if (instanceOf(value, host.WeakMap)) { return Contextify.instance(value, WeakMap, deepTraps, flags, 'WeakMap');
|
||||
} else if (instanceOf(value, host.Set)) { return Contextify.instance(value, Set, deepTraps, flags, 'Set');
|
||||
} else if (instanceOf(value, host.WeakSet)) { return Contextify.instance(value, WeakSet, deepTraps, flags, 'WeakSet');
|
||||
} else if (instanceOf(value, host.Promise)) { return Contextify.instance(value, Promise, deepTraps, flags, 'Promise');
|
||||
} else if (instanceOf(value, host.Buffer)) { return Contextify.instance(value, LocalBuffer, deepTraps, flags, 'Uint8Array');
|
||||
} else if (host.Reflect.getPrototypeOf(value) === null) {
|
||||
return Contextify.instance(value, null, deepTraps, flags);
|
||||
} else {
|
||||
return Contextify.object(value, traps, deepTraps, flags, mock);
|
||||
}
|
||||
case 'function':
|
||||
return Contextify.function(value, traps, deepTraps, flags, mock);
|
||||
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
|
||||
default: // string, number, boolean, symbol
|
||||
return value;
|
||||
}
|
||||
} catch (ex) {
|
||||
// Never pass the handled expcetion through! This block can't throw an exception under normal conditions.
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Contextify.globalValue = (value, name) => {
|
||||
return (global[name] = Contextify.value(value));
|
||||
};
|
||||
Contextify.readonly = (value, mock) => {
|
||||
return Contextify.value(value, null, FROZEN_TRAPS, null, mock);
|
||||
};
|
||||
Contextify.protected = (value, mock) => {
|
||||
return Contextify.value(value, null, null, {protected: true}, mock);
|
||||
};
|
||||
|
||||
const BufferMock = host.Object.create(null);
|
||||
BufferMock.allocUnsafe = function allocUnsafe(size) {
|
||||
return this.alloc(size);
|
||||
};
|
||||
BufferMock.allocUnsafeSlow = function allocUnsafeSlow(size) {
|
||||
return this.alloc(size);
|
||||
};
|
||||
/**
|
||||
* start
|
||||
* @author Eoapi
|
||||
* @desc Buffer默认取原始的Buffer,不做安全过滤,不能随意更改,会导致脚本步骤crypto执行错误
|
||||
*/
|
||||
const LocalBuffer = global.Buffer = Contextify.readonly(host.Buffer, BufferMock);
|
||||
// const LocalBuffer = global.Buffer = host.Buffer;
|
||||
//end
|
||||
const exportsMap = host.Object.create(null);
|
||||
exportsMap.Contextify = Contextify;
|
||||
exportsMap.Decontextify = Decontextify;
|
||||
exportsMap.Buffer = LocalBuffer;
|
||||
|
||||
return exportsMap;
|
@ -1,613 +0,0 @@
|
||||
/* eslint-disable global-require, no-use-before-define */
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const vm = require('vm');
|
||||
const pa = require('path');
|
||||
const {EventEmitter} = require('events');
|
||||
|
||||
const _compileToJS = function compileToJS(code, compiler, filename) {
|
||||
if ('function' === typeof compiler) return compiler(code, filename);
|
||||
|
||||
switch (compiler) {
|
||||
case 'coffeescript':
|
||||
case 'coffee-script':
|
||||
case 'cs':
|
||||
case 'text/coffeescript':
|
||||
try {
|
||||
return require('coffee-script').compile(code, {header: false, bare: true});
|
||||
} catch (ex) {
|
||||
throw new VMError('Coffee-Script compiler is not installed.');
|
||||
}
|
||||
|
||||
case 'javascript':
|
||||
case 'java-script':
|
||||
case 'js':
|
||||
case 'text/javascript':
|
||||
return code;
|
||||
|
||||
default:
|
||||
throw new VMError(`Unsupported compiler '${compiler}'.`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class Script
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
|
||||
class VMScript {
|
||||
/**
|
||||
* Create VMScript instance.
|
||||
*
|
||||
* @param {String} code Code to run.
|
||||
* @param {String} [filename] Filename that shows up in any stack traces produced from this script.
|
||||
* @return {VMScript}
|
||||
*/
|
||||
|
||||
constructor(code, filename) {
|
||||
this._code = String(code);
|
||||
this.filename = filename || 'vm.js';
|
||||
this._prefix = '';
|
||||
this._suffix = '';
|
||||
this._compiledVM = null;
|
||||
this._compiledNodeVM = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the code.
|
||||
* Will invalidate the code cache.
|
||||
*
|
||||
* @return {VMScript}
|
||||
*/
|
||||
|
||||
wrap(prefix, suffix) {
|
||||
const strPrefix = String(prefix);
|
||||
const strSuffix = String(suffix);
|
||||
if (this._prefix === strPrefix && this._suffix === strSuffix) return this;
|
||||
this._prefix = strPrefix;
|
||||
this._suffix = strSuffix;
|
||||
this._compiledVM = null;
|
||||
this._compiledNodeVM = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Noop.
|
||||
* We need to change the code depending whether it is run in VM or NodeVM.
|
||||
* This function cannot decide for which to compile.
|
||||
*
|
||||
* @deprecated Will be done on first run
|
||||
* @return {VMScript}
|
||||
*/
|
||||
|
||||
compile() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* For backwards compatibility.
|
||||
*
|
||||
* @return {String} The wrapped code
|
||||
*/
|
||||
get code() {
|
||||
return this._prefix + this._code + this._suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* For backwards compatibility.
|
||||
* Will invalidate the code cache.
|
||||
*
|
||||
* @param {String} newCode The new code to run.
|
||||
*/
|
||||
set code(newCode) {
|
||||
const strNewCode = String(newCode);
|
||||
if (strNewCode === this._prefix + this._code + this._suffix) return;
|
||||
this._code = strNewCode;
|
||||
this._prefix = '';
|
||||
this._suffix = '';
|
||||
this._compiledVM = null;
|
||||
this._compiledNodeVM = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will compile the code for VM and cache it
|
||||
*
|
||||
* @return {VMScript}
|
||||
*/
|
||||
_compileVM() {
|
||||
if (this._compiledVM) return this;
|
||||
|
||||
this._compiledVM = new vm.Script(this._prefix + this._code + this._suffix, {
|
||||
filename: this.filename,
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will compile the code for NodeVM and cache it
|
||||
*
|
||||
* @return {VMScript}
|
||||
*/
|
||||
_compileNodeVM() {
|
||||
if (this._compiledNodeVM) return this;
|
||||
|
||||
this._compiledNodeVM = new vm.Script('(function (exports, require, module, __filename, __dirname) { ' +
|
||||
this._prefix + this._code + this._suffix + '\n})', {
|
||||
filename: this.filename,
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadScript(filename) {
|
||||
const data = fs.readFileSync(filename, 'utf8');
|
||||
return new VMScript(data, filename);
|
||||
}
|
||||
|
||||
const SCRIPT_CACHE = {
|
||||
cf: loadScript(`${__dirname}/contextify.js`).wrap('(function(require, host) { ', '\n})')._compileVM(),
|
||||
sb: loadScript(`${__dirname}/sandbox.js`).wrap('(function (vm, host, Contextify, Decontextify, Buffer) { ', '\n})')._compileVM(),
|
||||
exp: new VMScript('({exports: {}})')._compileVM()
|
||||
};
|
||||
|
||||
/**
|
||||
* Class VM.
|
||||
*
|
||||
* @property {Object} options VM options.
|
||||
*/
|
||||
|
||||
class VM extends EventEmitter {
|
||||
/**
|
||||
* Create VM instance.
|
||||
*
|
||||
* @param {Object} [options] VM options.
|
||||
* @return {VM}
|
||||
*/
|
||||
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
// defaults
|
||||
this.options = {
|
||||
timeout: options.timeout,
|
||||
sandbox: options.sandbox,
|
||||
compiler: options.compiler || 'javascript',
|
||||
eval: options.eval === false ? false : true,
|
||||
wasm: options.wasm === false ? false : true
|
||||
};
|
||||
|
||||
const host = {
|
||||
version: parseInt(process.versions.node.split('.')[0]),
|
||||
console,
|
||||
String,
|
||||
Number,
|
||||
Buffer,
|
||||
Boolean,
|
||||
Array,
|
||||
Date,
|
||||
Error,
|
||||
EvalError,
|
||||
RangeError,
|
||||
ReferenceError,
|
||||
SyntaxError,
|
||||
TypeError,
|
||||
URIError,
|
||||
RegExp,
|
||||
Function,
|
||||
Object,
|
||||
VMError,
|
||||
Proxy,
|
||||
Reflect,
|
||||
Map,
|
||||
WeakMap,
|
||||
Set,
|
||||
WeakSet,
|
||||
Promise,
|
||||
Symbol,
|
||||
Object
|
||||
};
|
||||
|
||||
this._context = vm.createContext(undefined, {
|
||||
codeGeneration: {
|
||||
strings: this.options.eval,
|
||||
wasm: this.options.wasm
|
||||
}
|
||||
});
|
||||
|
||||
Reflect.defineProperty(this, '_internal', {
|
||||
value: SCRIPT_CACHE.cf._compiledVM.runInContext(this._context, {
|
||||
filename: SCRIPT_CACHE.cf.filename,
|
||||
displayErrors: false
|
||||
}).call(this._context, require, host)
|
||||
});
|
||||
|
||||
// prepare global sandbox
|
||||
if (this.options.sandbox) {
|
||||
if ('object' !== typeof this.options.sandbox) {
|
||||
throw new VMError('Sandbox must be object.');
|
||||
}
|
||||
|
||||
for (const name in this.options.sandbox) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.options.sandbox, name)) {
|
||||
this._internal.Contextify.globalValue(this.options.sandbox[name], name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes the object inside VM making it read-only. Not available for primitive values.
|
||||
*
|
||||
* @static
|
||||
* @param {*} object Object to freeze.
|
||||
* @param {String} [globalName] Whether to add the object to global.
|
||||
* @return {*} Object to freeze.
|
||||
*/
|
||||
|
||||
freeze(value, globalName) {
|
||||
this._internal.Contextify.readonly(value);
|
||||
if (globalName) this._internal.Contextify.globalValue(value, globalName);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values.
|
||||
*
|
||||
* @static
|
||||
* @param {*} object Object to protect.
|
||||
* @param {String} [globalName] Whether to add the object to global.
|
||||
* @return {*} Object to protect.
|
||||
*/
|
||||
|
||||
protect(value, globalName) {
|
||||
this._internal.Contextify.protected(value);
|
||||
if (globalName) this._internal.Contextify.globalValue(value, globalName);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the code in VM.
|
||||
*
|
||||
* @param {String} code Code to run.
|
||||
* @return {*} Result of executed code.
|
||||
*/
|
||||
|
||||
run(code) {
|
||||
if (this.options.compiler !== 'javascript') {
|
||||
code = _compileToJS(code, this.options.compiler);
|
||||
}
|
||||
|
||||
const script = code instanceof VMScript ? code : new VMScript(code);
|
||||
script._compileVM();
|
||||
|
||||
try {
|
||||
return this._internal.Decontextify.value(script._compiledVM.runInContext(this._context, {
|
||||
filename: script.filename,
|
||||
displayErrors: false,
|
||||
timeout: this.options.timeout
|
||||
}));
|
||||
} catch (e) {
|
||||
throw this._internal.Decontextify.value(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class NodeVM.
|
||||
*
|
||||
* @class
|
||||
* @extends {EventEmitter}
|
||||
* @property {Object} module Pointer to main module.
|
||||
*/
|
||||
|
||||
class NodeVM extends EventEmitter {
|
||||
/**
|
||||
* Create NodeVM instance.
|
||||
*
|
||||
* Unlike VM, NodeVM lets you use require same way like in regular node.
|
||||
*
|
||||
* @param {Object} [options] VM options.
|
||||
* @return {NodeVM}
|
||||
*/
|
||||
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
// defaults
|
||||
this.options = {
|
||||
sandbox: options.sandbox,
|
||||
console: options.console || 'inherit',
|
||||
require: options.require || false,
|
||||
compiler: options.compiler || 'javascript',
|
||||
eval: options.eval === false ? false : true,
|
||||
wasm: options.wasm === false ? false : true,
|
||||
nesting: options.nesting || false,
|
||||
wrapper: options.wrapper || 'commonjs',
|
||||
sourceExtensions: options.sourceExtensions || ['js']
|
||||
};
|
||||
|
||||
const host = {
|
||||
version: parseInt(process.versions.node.split('.')[0]),
|
||||
require,
|
||||
process,
|
||||
console,
|
||||
setTimeout,
|
||||
setInterval,
|
||||
setImmediate,
|
||||
clearTimeout,
|
||||
clearInterval,
|
||||
clearImmediate,
|
||||
String,
|
||||
Number,
|
||||
Buffer,
|
||||
Boolean,
|
||||
Array,
|
||||
Date,
|
||||
Error,
|
||||
EvalError,
|
||||
RangeError,
|
||||
ReferenceError,
|
||||
SyntaxError,
|
||||
TypeError,
|
||||
URIError,
|
||||
RegExp,
|
||||
Function,
|
||||
Object,
|
||||
VMError,
|
||||
Proxy,
|
||||
Reflect,
|
||||
Map,
|
||||
WeakMap,
|
||||
Set,
|
||||
WeakSet,
|
||||
Promise,
|
||||
Symbol
|
||||
};
|
||||
|
||||
if (this.options.nesting) {
|
||||
host.VM = VM;
|
||||
host.NodeVM = NodeVM;
|
||||
}
|
||||
|
||||
this._context = vm.createContext(undefined, {
|
||||
codeGeneration: {
|
||||
strings: this.options.eval,
|
||||
wasm: this.options.wasm
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, '_internal', {
|
||||
value: SCRIPT_CACHE.cf._compiledVM.runInContext(this._context, {
|
||||
filename: SCRIPT_CACHE.cf.filename,
|
||||
displayErrors: false
|
||||
}).call(this._context, require, host)
|
||||
});
|
||||
|
||||
const closure = SCRIPT_CACHE.sb._compiledVM.runInContext(this._context, {
|
||||
filename: SCRIPT_CACHE.sb.filename,
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
Object.defineProperty(this, '_prepareRequire', {
|
||||
value: closure.call(this._context, this, host, this._internal.Contextify, this._internal.Decontextify, this._internal.Buffer)
|
||||
});
|
||||
|
||||
// prepare global sandbox
|
||||
if (this.options.sandbox) {
|
||||
if ('object' !== typeof this.options.sandbox) {
|
||||
throw new VMError('Sandbox must be object.');
|
||||
}
|
||||
|
||||
for (const name in this.options.sandbox) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.options.sandbox, name)) {
|
||||
this._internal.Contextify.globalValue(this.options.sandbox[name], name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.require && this.options.require.import) {
|
||||
if (!Array.isArray(this.options.require.import)) {
|
||||
this.options.require.import = [this.options.require.import];
|
||||
}
|
||||
|
||||
for (let i = 0, l = this.options.require.import.length; i < l; i++) {
|
||||
this.require(this.options.require.import[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
call(method, ...args) {
|
||||
if ('function' === typeof method) {
|
||||
return method.apply(args);
|
||||
|
||||
} else {
|
||||
throw new VMError('Unrecognized method type.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes the object inside VM making it read-only. Not available for primitive values.
|
||||
*
|
||||
* @static
|
||||
* @param {*} object Object to freeze.
|
||||
* @param {String} [globalName] Whether to add the object to global.
|
||||
* @return {*} Object to freeze.
|
||||
*/
|
||||
|
||||
freeze(value, globalName) {
|
||||
this._internal.Contextify.readonly(value);
|
||||
if (global) this._internal.Contextify.globalValue(value, globalName);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protects the object inside VM making impossible to set functions as it's properties. Not available for primitive values.
|
||||
*
|
||||
* @static
|
||||
* @param {*} object Object to protect.
|
||||
* @param {String} [globalName] Whether to add the object to global.
|
||||
* @return {*} Object to protect.
|
||||
*/
|
||||
|
||||
protect(value, globalName) {
|
||||
this._internal.Contextify.protected(value);
|
||||
if (global) this._internal.Contextify.globalValue(value, globalName);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require a module in VM and return it's exports.
|
||||
*
|
||||
* @param {String} module Module name.
|
||||
* @return {*} Exported module.
|
||||
*/
|
||||
|
||||
require(module) {
|
||||
return this.run(`module.exports = require('${module}');`, 'vm.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the code in NodeVM.
|
||||
*
|
||||
* First time you run this method, code is executed same way like in node's regular `require` - it's executed with
|
||||
* `module`, `require`, `exports`, `__dirname`, `__filename` variables and expect result in `module.exports'.
|
||||
*
|
||||
* @param {String} code Code to run.
|
||||
* @param {String} [filename] Filename that shows up in any stack traces produced from this script.
|
||||
* @return {*} Result of executed code.
|
||||
*/
|
||||
|
||||
run(code, filename) {
|
||||
if (this.options.compiler !== 'javascript') {
|
||||
code = _compileToJS(code, this.options.compiler, filename);
|
||||
}
|
||||
|
||||
let dirname;
|
||||
let returned;
|
||||
|
||||
if (filename) {
|
||||
filename = pa.resolve(filename);
|
||||
dirname = pa.dirname(filename);
|
||||
} else {
|
||||
filename = null;
|
||||
dirname = null;
|
||||
}
|
||||
|
||||
const module = SCRIPT_CACHE.exp._compiledVM.runInContext(this._context, {
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
const script = code instanceof VMScript ? code : new VMScript(code, filename);
|
||||
script._compileNodeVM();
|
||||
|
||||
try {
|
||||
const closure = script._compiledNodeVM.runInContext(this._context, {
|
||||
filename: script.filename,
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
returned = closure.call(this._context, module.exports, this._prepareRequire(dirname), module, filename, dirname);
|
||||
} catch (e) {
|
||||
throw this._internal.Decontextify.value(e);
|
||||
}
|
||||
|
||||
if (this.options.wrapper === 'commonjs') {
|
||||
return this._internal.Decontextify.value(module.exports);
|
||||
} else {
|
||||
return this._internal.Decontextify.value(returned);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create NodeVM and run code inside it.
|
||||
*
|
||||
* @param {String} script Javascript code.
|
||||
* @param {String} [filename] File name (used in stack traces only).
|
||||
* @param {Object} [options] VM options.
|
||||
* @return {NodeVM} VM.
|
||||
*/
|
||||
|
||||
static code(script, filename, options) {
|
||||
if (filename != null) {
|
||||
if ('object' === typeof filename) {
|
||||
options = filename;
|
||||
filename = null;
|
||||
} else if ('string' === typeof filename) {
|
||||
filename = pa.resolve(filename);
|
||||
} else {
|
||||
throw new VMError('Invalid arguments.');
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.length > 3) {
|
||||
throw new VMError('Invalid number of arguments.');
|
||||
}
|
||||
|
||||
return new NodeVM(options).run(script, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create NodeVM and run script from file inside it.
|
||||
*
|
||||
* @param {String} [filename] File name (used in stack traces only).
|
||||
* @param {Object} [options] VM options.
|
||||
* @return {NodeVM} VM.
|
||||
*/
|
||||
|
||||
static file(filename, options) {
|
||||
filename = pa.resolve(filename);
|
||||
|
||||
if (!fs.existsSync(filename)) {
|
||||
throw new VMError(`Script '${filename}' not found.`);
|
||||
}
|
||||
|
||||
if (fs.statSync(filename).isDirectory()) {
|
||||
throw new VMError('Script must be file, got directory.');
|
||||
}
|
||||
|
||||
return new NodeVM(options).run(fs.readFileSync(filename, 'utf8'), filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VMError.
|
||||
*
|
||||
* @class
|
||||
* @extends {Error}
|
||||
* @property {String} stack Call stack.
|
||||
* @property {String} message Error message.
|
||||
*/
|
||||
|
||||
class VMError extends Error {
|
||||
/**
|
||||
* Create VMError instance.
|
||||
*
|
||||
* @param {String} message Error message.
|
||||
* @return {VMError}
|
||||
*/
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
|
||||
this.name = 'VMError';
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
exports.VMError = VMError;
|
||||
exports.NodeVM = NodeVM;
|
||||
exports.VM = VM;
|
||||
exports.VMScript = VMScript;
|
@ -1,530 +0,0 @@
|
||||
/* eslint-disable no-shadow, no-invalid-this */
|
||||
/* global vm, host, Contextify, Decontextify, VMError */
|
||||
|
||||
'use strict';
|
||||
|
||||
const {Script} = host.require('vm');
|
||||
const fs = host.require('fs');
|
||||
const pa = host.require('path');
|
||||
const match = (wildcard, s) => {
|
||||
const regexString = wildcard.replace(/\*/, '\\S*').replace(/\?/g, '.');
|
||||
const regex = new RegExp(regexString);
|
||||
return regex.test(s);
|
||||
};
|
||||
|
||||
const BUILTIN_MODULES = host.process.binding('natives');
|
||||
const parseJSON = JSON.parse;
|
||||
|
||||
/**
|
||||
* @param {Object} host Hosts's internal objects.
|
||||
*/
|
||||
|
||||
return ((vm, host) => {
|
||||
'use strict';
|
||||
|
||||
const global = this;
|
||||
|
||||
const TIMERS = new host.WeakMap(); // Contains map of timers created inside sandbox
|
||||
const BUILTINS = {};
|
||||
const CACHE = {};
|
||||
const EXTENSIONS = {
|
||||
['.json'](module, filename) {
|
||||
try {
|
||||
const code = fs.readFileSync(filename, 'utf8');
|
||||
module.exports = parseJSON(code);
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
},
|
||||
['.node'](module, filename) {
|
||||
if (vm.options.require.context === 'sandbox') throw new VMError('Native modules can be required only with context set to \'host\'.');
|
||||
|
||||
try {
|
||||
module.exports = Contextify.readonly(host.require(filename));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
|
||||
const ext = vm.options.sourceExtensions[i];
|
||||
|
||||
EXTENSIONS['.' + ext] = (module, filename, dirname) => {
|
||||
if (vm.options.require.context !== 'sandbox') {
|
||||
try {
|
||||
module.exports = Contextify.readonly(host.require(filename));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
} else {
|
||||
let closure;
|
||||
|
||||
try {
|
||||
// Load module
|
||||
let contents = fs.readFileSync(filename, 'utf8');
|
||||
if (typeof vm.options.compiler === 'function') {
|
||||
contents = vm.options.compiler(contents, filename);
|
||||
}
|
||||
|
||||
const code = `(function (exports, require, module, __filename, __dirname) { 'use strict'; ${contents} \n});`;
|
||||
|
||||
// Precompile script
|
||||
const script = new Script(code, {
|
||||
filename: filename || 'vm.js',
|
||||
displayErrors: false
|
||||
});
|
||||
|
||||
closure = script.runInContext(global, {
|
||||
filename: filename || 'vm.js',
|
||||
displayErrors: false
|
||||
});
|
||||
} catch (ex) {
|
||||
throw Contextify.value(ex);
|
||||
}
|
||||
|
||||
// run the script
|
||||
closure(module.exports, module.require, module, filename, dirname);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const _parseExternalOptions = (options) => {
|
||||
if (Array.isArray(options)) {
|
||||
return {
|
||||
external: options,
|
||||
transitive: false
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
external: options.modules,
|
||||
transitive: options.transitive
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve filename.
|
||||
*/
|
||||
|
||||
const _resolveFilename = (path) => {
|
||||
if (!path) return null;
|
||||
path = pa.resolve(path);
|
||||
|
||||
const exists = fs.existsSync(path);
|
||||
const isdir = exists ? fs.statSync(path).isDirectory() : false;
|
||||
|
||||
// direct file match
|
||||
if (exists && !isdir) return path;
|
||||
|
||||
// load as file
|
||||
|
||||
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
|
||||
const ext = vm.options.sourceExtensions[i];
|
||||
if (fs.existsSync(`${path}.${ext}`)) return `${path}.${ext}`;
|
||||
}
|
||||
if (fs.existsSync(`${path}.json`)) return `${path}.json`;
|
||||
if (fs.existsSync(`${path}.node`)) return `${path}.node`;
|
||||
|
||||
// load as module
|
||||
|
||||
if (fs.existsSync(`${path}/package.json`)) {
|
||||
let pkg;
|
||||
try {
|
||||
pkg = JSON.parse(fs.readFileSync(`${path}/package.json`, 'utf8'));
|
||||
} catch (ex) {
|
||||
throw new VMError(`Module '${path}' has invalid package.json`, 'EMODULEINVALID');
|
||||
}
|
||||
|
||||
let main;
|
||||
if (pkg && pkg.main) {
|
||||
main = _resolveFilename(`${path}/${pkg.main}`);
|
||||
if (!main) main = _resolveFilename(`${path}/index`);
|
||||
} else {
|
||||
main = _resolveFilename(`${path}/index`);
|
||||
}
|
||||
|
||||
return main;
|
||||
}
|
||||
|
||||
// load as directory
|
||||
|
||||
for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
|
||||
const ext = vm.options.sourceExtensions[i];
|
||||
if (fs.existsSync(`${path}/index.${ext}`)) return `${path}/index.${ext}`;
|
||||
}
|
||||
|
||||
if (fs.existsSync(`${path}/index.json`)) return `${path}/index.json`;
|
||||
if (fs.existsSync(`${path}/index.node`)) return `${path}/index.node`;
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builtin require.
|
||||
*/
|
||||
|
||||
const _requireBuiltin = (moduleName) => {
|
||||
if (moduleName === 'buffer') return ({Buffer});
|
||||
if (BUILTINS[moduleName]) return BUILTINS[moduleName].exports; // Only compiled builtins are stored here
|
||||
|
||||
if (moduleName === 'util') {
|
||||
return Contextify.readonly(host.require(moduleName), {
|
||||
// Allows VM context to use util.inherits
|
||||
inherits: (ctor, superCtor) => {
|
||||
ctor.super_ = superCtor;
|
||||
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (moduleName === 'events' || moduleName === 'internal/errors') {
|
||||
try {
|
||||
const script = new Script(`(function (exports, require, module, process, internalBinding) {
|
||||
'use strict';
|
||||
const primordials = global;
|
||||
${BUILTIN_MODULES[moduleName]}
|
||||
\n
|
||||
});`, {
|
||||
filename: `${moduleName}.vm.js`
|
||||
});
|
||||
|
||||
// setup module scope
|
||||
const module = BUILTINS[moduleName] = {
|
||||
exports: {},
|
||||
require: _requireBuiltin
|
||||
};
|
||||
|
||||
// run script
|
||||
script.runInContext(global)(module.exports, module.require, module, host.process, host.process.binding);
|
||||
|
||||
return module.exports;
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Contextify.readonly(host.require(moduleName));
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare require.
|
||||
*/
|
||||
|
||||
const _prepareRequire = (currentDirname, parentAllowsTransitive = false) => {
|
||||
const _require = moduleName => {
|
||||
if (vm.options.nesting && moduleName === 'vm2') return {VM: Contextify.readonly(host.VM), NodeVM: Contextify.readonly(host.NodeVM)};
|
||||
if (!vm.options.require) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
if (moduleName == null) throw new VMError("Module '' not found.", 'ENOTFOUND');
|
||||
if (typeof moduleName !== 'string') throw new VMError(`Invalid module name '${moduleName}'`, 'EINVALIDNAME');
|
||||
|
||||
let filename;
|
||||
let allowRequireTransitive = false;
|
||||
|
||||
// Mock?
|
||||
|
||||
if (vm.options.require.mock && vm.options.require.mock[moduleName]) {
|
||||
return Contextify.readonly(vm.options.require.mock[moduleName]);
|
||||
}
|
||||
|
||||
// Builtin?
|
||||
|
||||
if (BUILTIN_MODULES[moduleName]) {
|
||||
if (host.Array.isArray(vm.options.require.builtin)) {
|
||||
if (vm.options.require.builtin.indexOf('*') >= 0) {
|
||||
if (vm.options.require.builtin.indexOf(`-${moduleName}`) >= 0) {
|
||||
throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
}
|
||||
} else if (vm.options.require.builtin.indexOf(moduleName) === -1) {
|
||||
throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
}
|
||||
} else if (vm.options.require.builtin) {
|
||||
if (!vm.options.require.builtin[moduleName]) {
|
||||
throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
}
|
||||
} else {
|
||||
throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
}
|
||||
|
||||
return _requireBuiltin(moduleName);
|
||||
}
|
||||
|
||||
// External?
|
||||
|
||||
if (!vm.options.require.external) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
|
||||
|
||||
if (/^(\.|\.\/|\.\.\/)/.exec(moduleName)) {
|
||||
// Module is relative file, e.g. ./script.js or ../script.js
|
||||
|
||||
if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
|
||||
|
||||
filename = _resolveFilename(`${currentDirname}/${moduleName}`);
|
||||
} else if (/^(\/|\\|[a-zA-Z]:\\)/.exec(moduleName)) {
|
||||
// Module is absolute file, e.g. /script.js or //server/script.js or C:\script.js
|
||||
|
||||
filename = _resolveFilename(moduleName);
|
||||
} else {
|
||||
// Check node_modules in path
|
||||
|
||||
if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
|
||||
|
||||
if (typeof vm.options.require.external === 'object') {
|
||||
const { external, transitive } = _parseExternalOptions(vm.options.require.external);
|
||||
|
||||
const isWhitelisted = external.some(ext => match(ext, moduleName)) || (transitive && parentAllowsTransitive);
|
||||
if (!isWhitelisted) {
|
||||
throw new VMError(`The module '${moduleName}' is not whitelisted in VM.`, 'EDENIED');
|
||||
}
|
||||
|
||||
allowRequireTransitive = true;
|
||||
}
|
||||
|
||||
const paths = currentDirname.split(pa.sep);
|
||||
|
||||
while (paths.length) {
|
||||
const path = paths.join(pa.sep);
|
||||
|
||||
// console.log moduleName, "#{path}#{pa.sep}node_modules#{pa.sep}#{moduleName}"
|
||||
|
||||
filename = _resolveFilename(`${path}${pa.sep}node_modules${pa.sep}${moduleName}`);
|
||||
if (filename) break;
|
||||
|
||||
paths.pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!filename && vm.options.require.resolve) {
|
||||
filename = _resolveFilename(vm.options.require.resolve(moduleName, currentDirname));
|
||||
}
|
||||
if (!filename) throw new VMError(`Cannot find module '${moduleName}'`, 'ENOTFOUND');
|
||||
|
||||
// return cache whenever possible
|
||||
if (CACHE[filename]) return CACHE[filename].exports;
|
||||
|
||||
const dirname = pa.dirname(filename);
|
||||
const extname = pa.extname(filename);
|
||||
|
||||
if (vm.options.require.root) {
|
||||
const rootPaths = Array.isArray(vm.options.require.root) ? vm.options.require.root : [vm.options.require.root];
|
||||
const allowedModule = rootPaths.some(path => dirname.startsWith(pa.resolve(path)));
|
||||
|
||||
if (!allowedModule) {
|
||||
throw new VMError(`Module '${moduleName}' is not allowed to be required. The path is outside the border!`, 'EDENIED');
|
||||
}
|
||||
}
|
||||
|
||||
const module = CACHE[filename] = {
|
||||
filename,
|
||||
exports: {},
|
||||
require: _prepareRequire(dirname, allowRequireTransitive)
|
||||
};
|
||||
|
||||
// lookup extensions
|
||||
if (EXTENSIONS[extname]) {
|
||||
EXTENSIONS[extname](module, filename, dirname);
|
||||
return module.exports;
|
||||
}
|
||||
|
||||
throw new VMError(`Failed to load '${moduleName}': Unknown type.`, 'ELOADFAIL');
|
||||
};
|
||||
|
||||
return _require;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare sandbox.
|
||||
*/
|
||||
|
||||
global.setTimeout = (callback, delay, ...args) => {
|
||||
const tmr = host.setTimeout(Decontextify.value(() => {
|
||||
callback(...args);
|
||||
}), Decontextify.value(delay));
|
||||
|
||||
const local = {
|
||||
ref: () => tmr.ref(),
|
||||
unref: () => tmr.unref()
|
||||
};
|
||||
|
||||
TIMERS.set(local, tmr);
|
||||
return local;
|
||||
};
|
||||
|
||||
global.setInterval = (callback, interval, ...args) => {
|
||||
const tmr = host.setInterval(Decontextify.value(() => {
|
||||
callback(...args);
|
||||
}), Decontextify.value(interval));
|
||||
|
||||
const local = {
|
||||
ref: () => tmr.ref(),
|
||||
unref: () => tmr.unref()
|
||||
};
|
||||
|
||||
TIMERS.set(local, tmr);
|
||||
return local;
|
||||
};
|
||||
|
||||
global.setImmediate = (callback, ...args) => {
|
||||
const tmr = host.setImmediate(Decontextify.value(() => {
|
||||
callback(...args);
|
||||
}));
|
||||
|
||||
const local = {
|
||||
ref: () => tmr.ref(),
|
||||
unref: () => tmr.unref()
|
||||
};
|
||||
|
||||
TIMERS.set(local, tmr);
|
||||
return local;
|
||||
};
|
||||
|
||||
global.clearTimeout = (local) => {
|
||||
host.clearTimeout(TIMERS.get(local));
|
||||
return null;
|
||||
};
|
||||
|
||||
global.clearInterval = (local) => {
|
||||
host.clearInterval(TIMERS.get(local));
|
||||
return null;
|
||||
};
|
||||
|
||||
global.clearImmediate = (local) => {
|
||||
host.clearImmediate(TIMERS.get(local));
|
||||
return null;
|
||||
};
|
||||
|
||||
global.process = {
|
||||
argv: [],
|
||||
title: host.process.title,
|
||||
version: host.process.version,
|
||||
versions: Contextify.readonly(host.process.versions),
|
||||
arch: host.process.arch,
|
||||
platform: host.process.platform,
|
||||
env: {},
|
||||
pid: host.process.pid,
|
||||
features: Contextify.readonly(host.process.features),
|
||||
nextTick(callback, ...args) {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new Error('Callback must be a function.');
|
||||
}
|
||||
|
||||
try {
|
||||
return host.process.nextTick(Decontextify.value(() => {
|
||||
callback(...args);
|
||||
}));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
},
|
||||
hrtime() {
|
||||
try {
|
||||
return host.process.hrtime();
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
},
|
||||
cwd() {
|
||||
try {
|
||||
return host.process.cwd();
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
},
|
||||
on(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new Error(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
try {
|
||||
host.process.on(name, Decontextify.value(handler));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
once(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new Error(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
try {
|
||||
host.process.once(name, Decontextify.value(handler));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
listeners(name) {
|
||||
// Filter out listeners, which were not created in this sandbox (isVMProxy is undefined)
|
||||
return Contextify.value(host.process.listeners(name).filter(listener => !Contextify.value(listener).isVMProxy));
|
||||
},
|
||||
|
||||
removeListener(name, handler) {
|
||||
try {
|
||||
host.process.removeListener(name, Decontextify.value(handler));
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
umask() {
|
||||
if (arguments.length) {
|
||||
throw new Error('Access denied to set umask.');
|
||||
}
|
||||
|
||||
try {
|
||||
return host.process.umask();
|
||||
} catch (e) {
|
||||
throw Contextify.value(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (vm.options.console === 'inherit') {
|
||||
global.console = Contextify.readonly(host.console);
|
||||
} else if (vm.options.console === 'redirect') {
|
||||
global.console = {
|
||||
debug(...args) {
|
||||
vm.emit('console.debug', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
log(...args) {
|
||||
vm.emit('console.log', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
info(...args) {
|
||||
vm.emit('console.info', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
warn(...args) {
|
||||
vm.emit('console.warn', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
error(...args) {
|
||||
vm.emit('console.error', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
dir(...args) {
|
||||
vm.emit('console.dir', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
},
|
||||
time: () => {},
|
||||
timeEnd: () => {},
|
||||
trace(...args) {
|
||||
vm.emit('console.trace', ...Decontextify.arguments(args));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Return contextized require.
|
||||
*/
|
||||
|
||||
return _prepareRequire;
|
||||
})(vm, host);
|
@ -1,7 +0,0 @@
|
||||
const match = (wildcard, s) => {
|
||||
const regexString = wildcard.replace(/\*/, '\\S*').replace(/\?/g, '.');
|
||||
const regex = new RegExp(regexString);
|
||||
return regex.test(s);
|
||||
};
|
||||
|
||||
module.exports = {match};
|
@ -1,112 +0,0 @@
|
||||
(() => {
|
||||
'use strict';
|
||||
class mainClass {
|
||||
constructor() {}
|
||||
jsonToXml() {
|
||||
var XML = function () {};
|
||||
|
||||
XML.ObjTree = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
XML.ObjTree.prototype.xmlDecl = '<?xml version="1.0" encoding="UTF-8" ?>\n';
|
||||
XML.ObjTree.prototype.attr_prefix = '-';
|
||||
|
||||
XML.ObjTree.prototype.writeXML = function (tree,attr_obj) {
|
||||
var xml = this.hash_to_xml(null, tree,attr_obj);
|
||||
return this.xmlDecl + xml;
|
||||
};
|
||||
|
||||
|
||||
XML.ObjTree.prototype.hash_to_xml = function (name, tree,attr_obj) {
|
||||
var elem = [];
|
||||
var attr = [];
|
||||
for (var key in tree) {
|
||||
if (!tree.hasOwnProperty(key)) continue;
|
||||
var val = tree[key],tmp_attr_obj={};
|
||||
if(attr_obj[key]){
|
||||
if(attr_obj[key] instanceof Array){
|
||||
if(typeof (val) == "object" && val.constructor == Array&&attr_obj[key][1]){//如果是数组,且没有子对象,则走此内容
|
||||
tmp_attr_obj=attr_obj[key];
|
||||
}else{
|
||||
tmp_attr_obj=attr_obj[key][1]||{};if(attr_obj[key][0])key = `${key} ${attr_obj[key][0]||""}`;
|
||||
}
|
||||
}
|
||||
else if(attr_obj[key])key = `${key} ${attr_obj[key]||""}`;
|
||||
}
|
||||
key=key.replace(/\s\s/g," ")
|
||||
if (key.charAt(0) != this.attr_prefix) {
|
||||
if (typeof (val) == "undefined" || val == null) {
|
||||
elem[elem.length] = "<" + key + " />";
|
||||
} else if (typeof (val) == "object" && val.constructor == Array) {
|
||||
elem[elem.length] = this.array_to_xml(key, val,tmp_attr_obj);
|
||||
} else if (typeof (val) == "object") {
|
||||
elem[elem.length] = this.hash_to_xml(key, val,tmp_attr_obj);
|
||||
} else {
|
||||
elem[elem.length] = this.scalar_to_xml(key, val);
|
||||
}
|
||||
} else {
|
||||
attr[attr.length] = " " + (key.substring(1)) + '="' + (this.xml_escape(val)) + '"';
|
||||
}
|
||||
}
|
||||
var jattr = attr.join("");
|
||||
var jelem = elem.join("");
|
||||
if (typeof (name) == "undefined" || name == null) {
|
||||
// no tag
|
||||
} else if (elem.length > 0) {
|
||||
if (jelem.match(/\n/)) {
|
||||
jelem = "<" + name + jattr + ">\n" + jelem + "</" + (name || "").split(" ")[0] + ">\n";
|
||||
} else {
|
||||
jelem = "<" + name + jattr + ">" + jelem + "</" + (name || "").split(" ")[0] + ">\n";
|
||||
}
|
||||
} else {
|
||||
jelem = "<" + name + jattr + " />\n";
|
||||
}
|
||||
return jelem;
|
||||
};
|
||||
|
||||
|
||||
XML.ObjTree.prototype.array_to_xml = function (name, array,attr_obj) {
|
||||
var out = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var val = array[i];
|
||||
let tmp_name=attr_obj[0]&&attr_obj[0][i]?`${name} ${typeof(attr_obj[0]==="string")?attr_obj[0]:attr_obj[0][i]}`:name;
|
||||
if (typeof (val) == "undefined" || val == null) {
|
||||
out[out.length] = "<" + tmp_name + " />";
|
||||
} else if (typeof (val) == "object" && val.constructor == Array) {
|
||||
out[out.length] = this.array_to_xml(tmp_name, val,attr_obj[i+1]);
|
||||
} else if (typeof (val) == "object") {
|
||||
out[out.length] = this.hash_to_xml(tmp_name, val,attr_obj[i+1]);
|
||||
} else {
|
||||
out[out.length] = this.scalar_to_xml(tmp_name, val);
|
||||
}
|
||||
}
|
||||
return out.join("");
|
||||
};
|
||||
|
||||
XML.ObjTree.prototype.scalar_to_xml = function (name, text) {
|
||||
if (name == "#text") {
|
||||
return this.xml_escape(text);
|
||||
} else {
|
||||
return "<" + name + ">" + this.xml_escape(text) + "</" + (name || "").split(" ")[0] + ">\n";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
XML.ObjTree.prototype.xml_escape = function (text) {
|
||||
let tmpResult=String(text);
|
||||
if(/<!\[CDATA/.test(tmpResult)&&/]]>/.test(tmpResult)){
|
||||
let tmpPreIndex=tmpResult.indexOf("<![CDATA[");
|
||||
let tmpLastIndex=tmpResult.substr(tmpPreIndex,tmpResult.length).indexOf("]]>")+3;
|
||||
return tmpResult.substr(0,tmpPreIndex).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')+tmpResult.substr(tmpPreIndex,tmpLastIndex)+tmpResult.substr(tmpLastIndex,tmpResult.length).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
return String(text).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
};
|
||||
return function (input,inputXmlAttrObj) {
|
||||
var xotree = new XML.ObjTree();
|
||||
return xotree.writeXML(input,inputXmlAttrObj||{});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.core = mainClass;
|
||||
})();
|
@ -1,24 +0,0 @@
|
||||
let _LibsFlowCommon = require('./unit.js');
|
||||
let _LibsCommon = require('./libs/common.js');
|
||||
process.on('message', (message) => {
|
||||
switch (message.action) {
|
||||
case 'ajax': {
|
||||
message.data.env = _LibsCommon.parseEnv(message.data.env);
|
||||
new _LibsFlowCommon.core().main(message.data, (tmpInputReport, tmpInputHistory) => {
|
||||
['general', 'requestInfo', 'resultInfo'].forEach((keyName) => {
|
||||
if (typeof tmpInputHistory[keyName] === 'string')
|
||||
tmpInputHistory[keyName] = JSON.parse(tmpInputHistory[keyName]);
|
||||
});
|
||||
process.send({
|
||||
action: 'finish',
|
||||
data: {
|
||||
id: message.id,
|
||||
report: tmpInputReport,
|
||||
history: tmpInputHistory,
|
||||
},
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
@ -1,830 +0,0 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
var url = require('url'),
|
||||
querystring = require('querystring'),
|
||||
_LibsCommon = require('./libs/common'),
|
||||
_LibsApiUtil = require('./libs/apiUtil'),
|
||||
_Formdata = require('form-data'),
|
||||
parse = {},
|
||||
privateFun = {},
|
||||
_ContentDisposition = require('content-disposition'),
|
||||
_RedirectClass = require('./libs/redirect'),
|
||||
_HttpPackageClass = new (require('./libs/http.package').core)(),
|
||||
_GetFileClass = new (require('./libs/getFile.package').core)(),
|
||||
_LibsMineType = require('./libs/mineType.package');
|
||||
let CONFIG = require('./config.json');
|
||||
const _EO_LANG_OBJ = require('./lang.json');
|
||||
var iconv = require('iconv-lite');
|
||||
global.eoLang = _EO_LANG_OBJ['cn'];
|
||||
/**
|
||||
* 解析uri信息
|
||||
* @param {number} protocol 请求协议
|
||||
* @param {string} uri 原始数据
|
||||
* @return uri
|
||||
*/
|
||||
parse.uri = function (protocol, uri) {
|
||||
if (!/((http:\/\/)|(https:\/\/))/.test(uri)) {
|
||||
uri = (protocol == '1' ? 'https://' : 'http://') + uri;
|
||||
}
|
||||
return uri;
|
||||
};
|
||||
|
||||
/**
|
||||
* 渲染请求数据
|
||||
* @param {object} inputTestData 请求数据信息
|
||||
* @param {array} response 返回信息体列表
|
||||
* @return {object} request信息
|
||||
*/
|
||||
privateFun.parseTestData = function (inputTestData, env) {
|
||||
return new Promise(async (resolve) => {
|
||||
var template = {
|
||||
pathObject: null,
|
||||
uri: '',
|
||||
options: {
|
||||
uri: '',
|
||||
method: inputTestData.method,
|
||||
headers: {},
|
||||
},
|
||||
beforeObject: null,
|
||||
body: null,
|
||||
formToJsonBody: [],
|
||||
label: {
|
||||
muti: false,
|
||||
},
|
||||
jwt: '',
|
||||
},
|
||||
tmpHeaderObj = {},
|
||||
tmpBinaryFileName,
|
||||
tmpRequestType = inputTestData.requestType.toString();
|
||||
try {
|
||||
inputTestData.headers.map(function (val, key) {
|
||||
tmpHeaderObj[val.headerName] = val.headerValue;
|
||||
});
|
||||
switch (inputTestData.auth.status) {
|
||||
case '1': {
|
||||
if (inputTestData.auth.basicAuth) {
|
||||
tmpHeaderObj['Authorization'] =
|
||||
'Basic ' +
|
||||
Buffer.from(
|
||||
(inputTestData.auth.basicAuth.username || '') + ':' + (inputTestData.auth.basicAuth.password || '')
|
||||
).toString('base64');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '2': {
|
||||
template.jwt = _LibsCommon.jwt(
|
||||
{
|
||||
alg: inputTestData.auth.jwtAuth.alg,
|
||||
typ: 'JWT',
|
||||
},
|
||||
inputTestData.auth.jwtAuth.payload,
|
||||
inputTestData.auth.jwtAuth.secretSalt
|
||||
);
|
||||
switch (template.jwt) {
|
||||
case 'jwtError': {
|
||||
resolve({
|
||||
status: 'preCode error',
|
||||
content: global.eoLang['213d3b0f-b267-4d5c-9512-0a06e2a5a522'],
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (inputTestData.auth.jwtAuth.isBearer) {
|
||||
template.jwt = `Bearer ${template.jwt}`;
|
||||
}
|
||||
switch (inputTestData.auth.jwtAuth.position) {
|
||||
case 'header': {
|
||||
tmpHeaderObj[inputTestData.auth.jwtAuth.tokenName || 'tokenName'] = template.jwt;
|
||||
break;
|
||||
}
|
||||
case 'query': {
|
||||
if (inputTestData.URL.indexOf('?') > -1) {
|
||||
inputTestData.URL +=
|
||||
(inputTestData.URL.replace(/(((?!\?).)*)\?/, '') ? '&' : '') +
|
||||
(inputTestData.auth.jwtAuth.tokenName || 'tokenName') +
|
||||
'=' +
|
||||
template.jwt;
|
||||
} else {
|
||||
inputTestData.URL += '?' + (inputTestData.auth.jwtAuth.tokenName || 'tokenName') + '=' + template.jwt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
let tmpNewUri =
|
||||
inputTestData.URL.indexOf('?') === -1 ? '' : inputTestData.URL.replace(/(((?!\?).)*)\?/, '') || '';
|
||||
switch (tmpRequestType) {
|
||||
case '0': {
|
||||
let tmpParamObj = {};
|
||||
inputTestData.params.map(function (val, key) {
|
||||
if ((val.paramType || 0).toString() == '1') {
|
||||
switch (Object.prototype.toString.call(tmpParamObj[val.paramKey])) {
|
||||
case '[object Array]': {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpParamObj[val.paramKey] = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
let tmpFileNameArr = (val.paramInfo || '').split(','),
|
||||
tmpFileArr = val.files || [];
|
||||
tmpFileArr.map((tmpFileVal, tmpFileKey) => {
|
||||
if (typeof tmpFileVal === 'object') {
|
||||
tmpParamObj[val.paramKey].push(tmpFileVal);
|
||||
} else {
|
||||
tmpParamObj[val.paramKey].push({
|
||||
name: tmpFileNameArr[tmpFileKey] || '',
|
||||
dataUrl: tmpFileVal,
|
||||
});
|
||||
}
|
||||
});
|
||||
template.label.muti = true;
|
||||
} else {
|
||||
switch (Object.prototype.toString.call(tmpParamObj[val.paramKey])) {
|
||||
case '[object Array]': {
|
||||
tmpParamObj[val.paramKey].push(val.paramInfo || '');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (tmpParamObj[val.paramKey]) {
|
||||
tmpParamObj[val.paramKey] = [tmpParamObj[val.paramKey], val.paramInfo || ''];
|
||||
} else {
|
||||
tmpParamObj[val.paramKey] = val.paramInfo || '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
await _LibsApiUtil
|
||||
.requestPreReduceByPromise(
|
||||
{
|
||||
requestType: inputTestData.requestType,
|
||||
url: inputTestData.URL,
|
||||
headers: tmpHeaderObj,
|
||||
params: tmpParamObj,
|
||||
raw: '',
|
||||
query: querystring.parse(tmpNewUri),
|
||||
env: env,
|
||||
apiRequestType: inputTestData.methodType,
|
||||
},
|
||||
inputTestData.beforeInject,
|
||||
{
|
||||
functionCode: inputTestData.functionCode,
|
||||
globalHeader: inputTestData.globalHeader,
|
||||
}
|
||||
)
|
||||
.then((tmpInputDataObj) => {
|
||||
template.beforeObject = tmpInputDataObj;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case '2':
|
||||
case '3': {
|
||||
template.formToJsonBody = _LibsCommon.bodyQueryToJson(inputTestData.params, {
|
||||
apiRequestParamJsonType:
|
||||
inputTestData.requestType.toString() == '2' ? inputTestData.apiRequestParamJsonType || '0' : '0',
|
||||
isXml: tmpRequestType === '3',
|
||||
});
|
||||
let tmpWantToExecuteData = {
|
||||
requestType: inputTestData.requestType,
|
||||
url: inputTestData.URL,
|
||||
headers: tmpHeaderObj,
|
||||
params: {},
|
||||
raw: '',
|
||||
query: querystring.parse(tmpNewUri),
|
||||
env: env,
|
||||
apiRequestType: inputTestData.methodType,
|
||||
};
|
||||
if (tmpRequestType === '3') {
|
||||
tmpWantToExecuteData.raw = template.formToJsonBody.value;
|
||||
tmpWantToExecuteData.xmlAttrObj = template.formToJsonBody.attr;
|
||||
} else {
|
||||
tmpWantToExecuteData.raw = template.formToJsonBody;
|
||||
}
|
||||
await _LibsApiUtil
|
||||
.requestPreReduceByPromise(tmpWantToExecuteData, inputTestData.beforeInject, {
|
||||
functionCode: inputTestData.functionCode,
|
||||
globalHeader: inputTestData.globalHeader,
|
||||
})
|
||||
.then((tmpInputDataObj) => {
|
||||
template.beforeObject = tmpInputDataObj;
|
||||
});
|
||||
break;
|
||||
}
|
||||
case '4': {
|
||||
await _LibsApiUtil
|
||||
.requestPreReduceByPromise(
|
||||
{
|
||||
requestType: '4',
|
||||
url: inputTestData.URL,
|
||||
headers: tmpHeaderObj,
|
||||
query: querystring.parse(tmpNewUri),
|
||||
env: env,
|
||||
binary: inputTestData.params.dataUrl,
|
||||
apiRequestType: inputTestData.methodType,
|
||||
},
|
||||
inputTestData.beforeInject,
|
||||
{
|
||||
functionCode: inputTestData.functionCode,
|
||||
globalHeader: inputTestData.globalHeader,
|
||||
}
|
||||
)
|
||||
.then((tmpInputDataObj) => {
|
||||
template.beforeObject = tmpInputDataObj;
|
||||
});
|
||||
template.body = Buffer.from(
|
||||
(inputTestData.params.dataUrl || '').replace(/^data:(.*);base64,/gi, ''),
|
||||
'base64'
|
||||
);
|
||||
tmpBinaryFileName = `[binary]${inputTestData.params.name}`;
|
||||
break;
|
||||
}
|
||||
case '1': {
|
||||
await _LibsApiUtil
|
||||
.requestPreReduceByPromise(
|
||||
{
|
||||
requestType: '1',
|
||||
url: inputTestData.URL,
|
||||
headers: tmpHeaderObj,
|
||||
raw: inputTestData.params,
|
||||
query: querystring.parse(tmpNewUri),
|
||||
env: env,
|
||||
apiRequestType: inputTestData.methodType,
|
||||
},
|
||||
inputTestData.beforeInject,
|
||||
{
|
||||
functionCode: inputTestData.functionCode,
|
||||
globalHeader: inputTestData.globalHeader,
|
||||
}
|
||||
)
|
||||
.then((tmpInputDataObj) => {
|
||||
template.beforeObject = tmpInputDataObj;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (template.beforeObject.status) {
|
||||
case 'beforeCodeError':
|
||||
case 'info':
|
||||
case 'terminateRequest': {
|
||||
resolve({
|
||||
status: 'preCode error',
|
||||
content: template.beforeObject.content,
|
||||
reportList: template.beforeObject.reportList,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
template.options.headers = template.beforeObject.headers;
|
||||
if (tmpRequestType !== '4') {
|
||||
if (
|
||||
!template.label.muti &&
|
||||
/"content-type":"multipart\/form-data/i.test(JSON.stringify(template.options.headers))
|
||||
) {
|
||||
template.label.muti = true;
|
||||
}
|
||||
if (template.label.muti) {
|
||||
template.body = template.beforeObject.params;
|
||||
} else {
|
||||
template.body =
|
||||
typeof template.beforeObject.params == 'string'
|
||||
? template.beforeObject.params
|
||||
: querystring.stringify(template.beforeObject.params || {});
|
||||
}
|
||||
}
|
||||
template.uri = parse.uri(inputTestData.httpHeader, template.beforeObject.url);
|
||||
template.pathObject = url.parse(template.uri);
|
||||
template.options.path = template.pathObject.path;
|
||||
template.options.hostname = template.pathObject.hostname;
|
||||
template.options.port = template.pathObject.port;
|
||||
template.options.protocol = template.pathObject.protocol;
|
||||
template.options.auth = template.pathObject.auth;
|
||||
} catch (e) {
|
||||
console.error(new Date() + ':unit/common.js 227', e);
|
||||
}
|
||||
resolve({
|
||||
options: template.options,
|
||||
body: template.body,
|
||||
afterInject: inputTestData.afterInject,
|
||||
isMuti: template.label.muti,
|
||||
functionCode: inputTestData.functionCode,
|
||||
env: template.beforeObject.env,
|
||||
advancedSetting: Object.assign(
|
||||
{},
|
||||
{
|
||||
requestRedirect: 1,
|
||||
sendNocacheToken: 0,
|
||||
checkSSL: 0,
|
||||
sendEoToken: 1,
|
||||
},
|
||||
inputTestData.advancedSetting || {}
|
||||
),
|
||||
history: {
|
||||
body: template.beforeObject.params,
|
||||
headers: template.options.headers,
|
||||
uri: template.uri,
|
||||
},
|
||||
requestBody: {
|
||||
body: template.beforeObject.params,
|
||||
},
|
||||
requestType: tmpRequestType,
|
||||
queryParams: template.beforeObject.queryParams,
|
||||
reportList: template.beforeObject.reportList,
|
||||
binaryFileName: tmpBinaryFileName,
|
||||
});
|
||||
});
|
||||
};
|
||||
class unitCommon {
|
||||
constructor() {
|
||||
this.xhr = null;
|
||||
this.areadyAbortXhr = false;
|
||||
}
|
||||
ajax(inputTestData, inputOptions, callback) {
|
||||
this.areadyAbortXhr = false;
|
||||
return new Promise(function (resolve, reject) {
|
||||
let tmpReportData = {
|
||||
response: {
|
||||
headers: [],
|
||||
body: '',
|
||||
httpCode: 0,
|
||||
testDeny: '',
|
||||
responseLength: 0,
|
||||
responseType: 'text',
|
||||
},
|
||||
request: {
|
||||
headers: [],
|
||||
},
|
||||
reportList: inputTestData.reportList,
|
||||
general: {
|
||||
redirectTimes: 0,
|
||||
downloadSize: 0,
|
||||
downloadRate: 0,
|
||||
},
|
||||
},
|
||||
tmpMultiForm = {},
|
||||
tmpAjaxXhr;
|
||||
for (let key in inputTestData.options.headers) {
|
||||
tmpReportData.request.headers.push({
|
||||
key: key,
|
||||
value: inputTestData.options.headers[key],
|
||||
});
|
||||
}
|
||||
try {
|
||||
let tmpFunCheckIsIllegalUrl = (inputHostName, tmpInputTotalTime) => {
|
||||
if (!inputHostName || new RegExp(_LibsCommon.LOCAL_REGEXP_CONST).test(inputHostName)) {
|
||||
tmpReportData.response.body = inputHostName
|
||||
? global.eoLang['63be68fa-31fc-498c-b49c-d3b6db10a95b']
|
||||
: global.eoLang['d6fa1d73-6a43-477f-a6df-6752661c9df3'];
|
||||
tmpReportData.response.testDeny = tmpInputTotalTime.toFixed(2);
|
||||
tmpReportData.general.time = tmpInputTotalTime.toFixed(2) + 'ms';
|
||||
if (callback) callback(tmpReportData);
|
||||
reject('illegal');
|
||||
return true;
|
||||
}
|
||||
};
|
||||
if (tmpFunCheckIsIllegalUrl(inputTestData.options.hostname, 0)) return;
|
||||
let tmpFunOprAjaxErr = (tmpInputErr, tmpInputTotalTime) => {
|
||||
tmpReportData.response.testDeny = tmpInputTotalTime;
|
||||
tmpReportData.response.body = tmpInputErr.name + ':' + tmpInputErr.message;
|
||||
tmpReportData.general.time = tmpInputTotalTime.toFixed(2) + 'ms';
|
||||
if (callback) callback(tmpReportData);
|
||||
reject('request error');
|
||||
},
|
||||
tmpFunReduceAjaxResEnd = (inputRes, tmpInputResponseObj) => {
|
||||
tmpReportData.general.time = tmpInputResponseObj.totalTime.toFixed(2) + 'ms';
|
||||
tmpReportData.general.downloadSize = tmpInputResponseObj.chunk.length;
|
||||
tmpReportData.general.downloadRate = (
|
||||
(tmpInputResponseObj.chunk.length / tmpInputResponseObj.contentDeliveryTiming / 1024) *
|
||||
1000
|
||||
).toFixed(2);
|
||||
tmpReportData.response.body = tmpInputResponseObj.str;
|
||||
tmpReportData.response.httpCode = inputRes.statusCode;
|
||||
tmpReportData.response.responseLength = tmpInputResponseObj.chunk.length;
|
||||
let tmpDetected = {},
|
||||
tmpSuffix = _LibsMineType.getSuffix(inputRes.headers['content-type']),
|
||||
tmpFileBinary;
|
||||
if (!inputRes.headers['content-type']) {
|
||||
tmpDetected =
|
||||
_GetFileClass.byContent(
|
||||
Buffer.concat(tmpInputResponseObj.chunk.array, tmpInputResponseObj.chunk.length) ||
|
||||
tmpReportData.response.body
|
||||
) || {};
|
||||
}
|
||||
if (
|
||||
/^(text\/(.*))|(application(.*)((\/)|(\+))json)|(application(.*)((\/)|(\+))xml)/gi.test(
|
||||
inputRes.headers['content-type']
|
||||
) ||
|
||||
(!(inputRes.headers['content-type'] && tmpSuffix) && !(tmpDetected && tmpDetected.mime))
|
||||
) {
|
||||
tmpReportData.response.contentType = inputRes.headers['content-type'];
|
||||
if (tmpReportData.response.responseLength >= 300 * 1024) {
|
||||
tmpFileBinary = Buffer.concat(
|
||||
tmpInputResponseObj.chunk.array,
|
||||
tmpInputResponseObj.chunk.length
|
||||
).toString('base64');
|
||||
tmpReportData.response.responseType = 'longText';
|
||||
let tmpPathUrl = inputTestData.options.path;
|
||||
tmpReportData.blobFileName = tmpPathUrl.substring(
|
||||
tmpPathUrl.lastIndexOf('/') + 1,
|
||||
tmpPathUrl.lastIndexOf('?') === -1 ? tmpPathUrl.length : tmpPathUrl.lastIndexOf('?')
|
||||
);
|
||||
}
|
||||
} else {
|
||||
tmpFileBinary = Buffer.concat(
|
||||
tmpInputResponseObj.chunk.array,
|
||||
tmpInputResponseObj.chunk.length
|
||||
).toString('base64');
|
||||
tmpReportData.response.responseType = 'stream';
|
||||
tmpReportData.response.contentType = inputRes.headers['content-type'] || tmpDetected.mime;
|
||||
let tmpPathUrl = inputTestData.options.path;
|
||||
try {
|
||||
tmpReportData.blobFileName = _ContentDisposition.parse(
|
||||
inputRes.headers['content-disposition'] || 'undefined'
|
||||
).parameters.filename;
|
||||
} catch (PARSE_CONTENT_DISPOSITION_ERR) {
|
||||
try {
|
||||
tmpReportData.blobFileName = _ContentDisposition.parse(
|
||||
encodeURI(inputRes.headers['content-disposition'] || 'undefined').replace(/\?/g, '')
|
||||
).parameters.filename;
|
||||
} catch (URL_ENCODE_PARSE_CONTENT_DISPOSITION_ERR) {}
|
||||
}
|
||||
if (!tmpReportData.blobFileName && tmpDetected && tmpDetected.ext) {
|
||||
tmpReportData.blobFileName = `response.${tmpDetected.ext}`;
|
||||
} else if (!tmpReportData.blobFileName) {
|
||||
tmpReportData.blobFileName = tmpPathUrl.substring(
|
||||
tmpPathUrl.lastIndexOf('/') + 1,
|
||||
tmpPathUrl.lastIndexOf('?') === -1 ? tmpPathUrl.length : tmpPathUrl.lastIndexOf('?')
|
||||
);
|
||||
}
|
||||
}
|
||||
_LibsApiUtil
|
||||
.responsePreReduceByPromise(
|
||||
tmpReportData.response.body,
|
||||
inputTestData.afterInject,
|
||||
inputTestData.env || {},
|
||||
{
|
||||
globalHeader: inputOptions.globalHeader,
|
||||
functionCode: inputTestData.functionCode,
|
||||
responseHeaders: inputRes.headers,
|
||||
params: inputOptions.requestData.requestBody,
|
||||
headers: tmpAjaxXhr.getHeaders(),
|
||||
query: inputOptions.requestData.queryParams,
|
||||
raw: inputOptions.requestData.raw,
|
||||
}
|
||||
)
|
||||
.then((tmpInputDataObj) => {
|
||||
let tmpAfterCodeObj = tmpInputDataObj;
|
||||
tmpReportData.reportList = tmpReportData.reportList.concat(tmpAfterCodeObj.reportList);
|
||||
if (tmpAfterCodeObj.status === 'finish') {
|
||||
if (tmpFileBinary) {
|
||||
tmpReportData.response.body = tmpFileBinary;
|
||||
} else {
|
||||
tmpReportData.response.body = tmpAfterCodeObj.content;
|
||||
tmpReportData.response.body =
|
||||
typeof tmpReportData.response.body == 'string'
|
||||
? tmpReportData.response.body
|
||||
: JSON.stringify(tmpReportData.response.body);
|
||||
}
|
||||
} else {
|
||||
tmpReportData.response.body = tmpAfterCodeObj.errorReason;
|
||||
delete tmpReportData.response.responseType;
|
||||
delete tmpReportData.blobFileName;
|
||||
delete tmpReportData.response.contentType;
|
||||
}
|
||||
for (let key in inputRes.headers) {
|
||||
tmpReportData.response.headers.push({
|
||||
key: key,
|
||||
value: inputRes.headers[key],
|
||||
});
|
||||
}
|
||||
|
||||
tmpReportData.response.testDeny = tmpInputResponseObj.totalTime.toFixed(2);
|
||||
if (callback) callback(tmpReportData);
|
||||
resolve('success');
|
||||
});
|
||||
};
|
||||
inputOptions.timeoutLimit = CONFIG.MAX_TIME_LIMIT;
|
||||
inputOptions.timeoutLimitType = 'totalTime';
|
||||
if (inputTestData.isMuti) {
|
||||
tmpMultiForm = _Formdata();
|
||||
for (let key in inputTestData.body) {
|
||||
let val = inputTestData.body[key];
|
||||
switch (typeof val) {
|
||||
case 'string': {
|
||||
switch (inputOptions.messageEncoding) {
|
||||
case 'gbk': {
|
||||
val = iconv.encode(Buffer.from(val), 'gbk');
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmpMultiForm.append(key, val);
|
||||
break;
|
||||
}
|
||||
case 'object': {
|
||||
if (val.length > 0) {
|
||||
for (let childKey in val) {
|
||||
let childVal = val[childKey];
|
||||
switch (typeof childVal) {
|
||||
case 'object': {
|
||||
tmpMultiForm.append(
|
||||
key,
|
||||
Buffer.from((childVal.dataUrl || '').replace(/^data:(.*);base64,/gi, ''), 'base64'),
|
||||
{
|
||||
filename: childVal.name,
|
||||
}
|
||||
);
|
||||
val[childKey] = '[file] ' + childVal.name;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpMultiForm.append(key, childVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tmpMultiForm.append(key, '');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputTestData.options.headers = Object.assign({}, inputTestData.options.headers, tmpMultiForm.getHeaders());
|
||||
} else {
|
||||
if (!/"content-length":/i.test(JSON.stringify(inputTestData.options.headers))) {
|
||||
inputTestData.options.headers['Content-Length'] = Buffer.byteLength(inputTestData.body);
|
||||
}
|
||||
}
|
||||
inputTestData.options.headers = _HttpPackageClass.setCookieToHeaders(
|
||||
inputTestData.options.headers,
|
||||
inputTestData.options.hostname,
|
||||
inputOptions.globalHeader || {}
|
||||
);
|
||||
_HttpPackageClass.socketReduce(
|
||||
{
|
||||
postData: inputTestData.isMuti ? tmpMultiForm : inputTestData.body,
|
||||
isMuti: inputTestData.isMuti,
|
||||
options: inputTestData.options,
|
||||
timeoutLimit: inputOptions.timeoutLimit,
|
||||
timeoutLimitType: inputOptions.timeoutLimitType,
|
||||
advancedSetting: inputTestData.advancedSetting,
|
||||
globalHeader: inputOptions.globalHeader,
|
||||
pckSplitByHeader: inputOptions.pckSplitByHeader,
|
||||
messageEncoding: inputOptions.messageEncoding,
|
||||
},
|
||||
(tmpInputAjaxStatus, tmpInputDataObj, tmpInputXhr) => {
|
||||
tmpAjaxXhr = tmpInputXhr;
|
||||
tmpReportData.request.headers = [];
|
||||
tmpReportData.general.timingSummary = [_LibsApiUtil.getHttpTiming(tmpInputDataObj.summaryObj)];
|
||||
let headers = {};
|
||||
if (tmpAjaxXhr.getHeaders) {
|
||||
headers = tmpAjaxXhr.getHeaders();
|
||||
for (let key in headers) {
|
||||
tmpReportData.request.headers.push({
|
||||
key: key,
|
||||
value: headers[key],
|
||||
});
|
||||
}
|
||||
}
|
||||
let tmpHttpTotalTime = _LibsApiUtil.getMicrosToMs(
|
||||
tmpInputDataObj.summaryObj.startAt,
|
||||
tmpInputDataObj.summaryObj.endAt
|
||||
);
|
||||
switch (tmpInputAjaxStatus) {
|
||||
case 'ajax_end': {
|
||||
if (inputTestData.advancedSetting.requestRedirect == 1) {
|
||||
tmpReportData.general.redirectTimes++;
|
||||
let tmpRedirectClass = new _RedirectClass.core();
|
||||
let tmpRedirectObject = tmpRedirectClass.structureAjaxFun(
|
||||
inputTestData.options,
|
||||
inputTestData.isMuti ? tmpMultiForm : inputTestData.body,
|
||||
tmpInputDataObj.res
|
||||
);
|
||||
if (tmpRedirectObject) {
|
||||
if (tmpFunCheckIsIllegalUrl(tmpRedirectObject.options.hostname, tmpHttpTotalTime)) return;
|
||||
_HttpPackageClass.socketReduce(
|
||||
{
|
||||
postData: tmpRedirectObject.postData,
|
||||
isMuti: inputTestData.isMuti,
|
||||
options: tmpRedirectObject.options,
|
||||
timeoutLimit: inputOptions.timeoutLimit - tmpHttpTotalTime,
|
||||
timeoutLimitType: inputOptions.timeoutLimitType,
|
||||
advancedSetting: inputOptions.advancedSetting,
|
||||
pckSplitByHeader: inputOptions.pckSplitByHeader,
|
||||
messageEncoding: inputOptions.messageEncoding,
|
||||
},
|
||||
(tmpInputRedirectAjaxStatus, tmpInputRedirectDataObj) => {
|
||||
tmpReportData.general.timingSummary.push(
|
||||
_LibsApiUtil.getHttpTiming(tmpInputRedirectDataObj.summaryObj)
|
||||
);
|
||||
let tmpRedirectHttpTotalTime = _LibsApiUtil.getMicrosToMs(
|
||||
tmpInputRedirectDataObj.summaryObj.startAt,
|
||||
tmpInputRedirectDataObj.summaryObj.endAt
|
||||
);
|
||||
switch (tmpInputRedirectAjaxStatus) {
|
||||
case 'ajax_end': {
|
||||
tmpFunReduceAjaxResEnd(tmpInputRedirectDataObj.res, {
|
||||
chunk: tmpInputRedirectDataObj.chunk,
|
||||
str: tmpInputRedirectDataObj.responseStr,
|
||||
totalTime: tmpHttpTotalTime + tmpRedirectHttpTotalTime,
|
||||
contentDeliveryTiming: _LibsApiUtil.getMicrosToMs(
|
||||
tmpInputRedirectDataObj.summaryObj.firstByteTiming,
|
||||
tmpInputRedirectDataObj.summaryObj.endAt
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ajaxErr': {
|
||||
tmpFunOprAjaxErr(
|
||||
tmpInputRedirectDataObj.errObj,
|
||||
tmpHttpTotalTime + tmpRedirectHttpTotalTime
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmpFunReduceAjaxResEnd(tmpInputDataObj.res, {
|
||||
chunk: tmpInputDataObj.chunk,
|
||||
str: tmpInputDataObj.responseStr,
|
||||
totalTime: tmpHttpTotalTime,
|
||||
contentDeliveryTiming: _LibsApiUtil.getMicrosToMs(
|
||||
tmpInputDataObj.summaryObj.firstByteTiming,
|
||||
tmpInputDataObj.summaryObj.endAt
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ajaxErr': {
|
||||
tmpFunOprAjaxErr(tmpInputDataObj.errObj, tmpHttpTotalTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
tmpReportData.response.testDeny = 0;
|
||||
tmpReportData.general.time = tmpReportData.general.time || '0ms';
|
||||
tmpReportData.response.body = e.name + ':' + e.message;
|
||||
if (callback) callback(tmpReportData);
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
main(inputTestData, callback) {
|
||||
let unitCommonClass = this;
|
||||
async function main() {
|
||||
let template = {
|
||||
ajax: {},
|
||||
status: 'finish',
|
||||
},
|
||||
tmpDecorateObj,
|
||||
tmpReportData = {
|
||||
afterInject: inputTestData.afterInject,
|
||||
beforeInject: inputTestData.beforeInject,
|
||||
};
|
||||
try {
|
||||
inputTestData.globalHeader = inputTestData.globalHeader || {};
|
||||
await privateFun.parseTestData(inputTestData, inputTestData.env || {}).then((tmpInputData) => {
|
||||
tmpDecorateObj = tmpInputData;
|
||||
});
|
||||
switch (tmpDecorateObj.status) {
|
||||
case 'preCode error': {
|
||||
template.ajax = {
|
||||
status: 'error',
|
||||
errorReason: tmpDecorateObj.content,
|
||||
reportList: tmpDecorateObj.reportList,
|
||||
general: {
|
||||
time: '0.00ms',
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpReportData.requestInfo = {
|
||||
messageSeparatorSetting: inputTestData.messageSeparatorSetting,
|
||||
params: [],
|
||||
apiProtocol: '0',
|
||||
URL: tmpDecorateObj.history.uri,
|
||||
headers: [],
|
||||
methodType: inputTestData.methodType,
|
||||
method: inputTestData.method,
|
||||
};
|
||||
if (tmpDecorateObj.requestType === '4') {
|
||||
tmpReportData.requestInfo.requestType = '2';
|
||||
delete tmpReportData.requestInfo.params;
|
||||
} else {
|
||||
switch (typeof tmpDecorateObj.history.body) {
|
||||
case 'object': {
|
||||
tmpReportData.requestInfo.requestType = '0';
|
||||
for (let key in tmpDecorateObj.history.body) {
|
||||
switch (typeof tmpDecorateObj.history.body[key]) {
|
||||
case 'object': {
|
||||
for (let childKey in tmpDecorateObj.history.body[key]) {
|
||||
tmpReportData.requestInfo.params.push({
|
||||
key: key,
|
||||
value:
|
||||
typeof tmpDecorateObj.history.body[key][childKey] == 'string'
|
||||
? tmpDecorateObj.history.body[key][childKey]
|
||||
: '[file]',
|
||||
});
|
||||
if (typeof tmpDecorateObj.history.body[key][childKey] != 'string') break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpReportData.requestInfo.params.push({
|
||||
key: key,
|
||||
value: tmpDecorateObj.history.body[key],
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
tmpReportData.requestInfo.requestType = '1';
|
||||
tmpReportData.requestInfo.params = tmpDecorateObj.history.body;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let key in tmpDecorateObj.history.headers) {
|
||||
tmpReportData.requestInfo.headers.push({
|
||||
name: key,
|
||||
value: tmpDecorateObj.history.headers[key],
|
||||
});
|
||||
}
|
||||
let tmpIsOversized,
|
||||
tmpRequestBodyStr =
|
||||
typeof tmpReportData.requestInfo.params === 'object'
|
||||
? JSON.stringify(tmpReportData.requestInfo.params)
|
||||
: tmpReportData.requestInfo.params;
|
||||
if ((tmpRequestBodyStr || '').length > CONFIG.REQUEST_BODY_LIMIT_STORAGE_LENGTH) {
|
||||
tmpReportData.requestInfo.requestType = 'oversized';
|
||||
tmpReportData.requestInfo.params = '';
|
||||
tmpIsOversized = true;
|
||||
}
|
||||
tmpReportData.requestInfo = JSON.stringify(tmpReportData.requestInfo);
|
||||
await unitCommonClass.ajax(
|
||||
tmpDecorateObj,
|
||||
{
|
||||
requestData: _LibsCommon.parseRequestDataToObj(tmpDecorateObj),
|
||||
globalHeader: inputTestData.globalHeader,
|
||||
pckSplitByHeader: inputTestData.messageSeparatorSetting === 'spliceLength',
|
||||
messageEncoding: inputTestData.messageEncoding,
|
||||
},
|
||||
function (res) {
|
||||
template.ajax = res;
|
||||
if (res.status != 'abort') {
|
||||
let tmpHistoryResponse = Object.assign({}, res.response);
|
||||
tmpHistoryResponse.reportList = res.reportList;
|
||||
if (tmpHistoryResponse.responseType !== 'text') delete tmpHistoryResponse.body;
|
||||
tmpReportData.general = JSON.stringify(res.general);
|
||||
tmpReportData.resultInfo = JSON.stringify(tmpHistoryResponse);
|
||||
template.ajax.request.body = tmpDecorateObj.binaryFileName || tmpDecorateObj.requestBody.body;
|
||||
if (tmpIsOversized) {
|
||||
template.ajax.request.requestType = 'oversized';
|
||||
} else {
|
||||
template.ajax.request.requestType =
|
||||
tmpDecorateObj.requestType === '4'
|
||||
? '1'
|
||||
: typeof tmpDecorateObj.requestBody.body == 'object'
|
||||
? '0'
|
||||
: '1';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(template.ajax, tmpReportData);
|
||||
}
|
||||
} catch (e) {
|
||||
if (callback) {
|
||||
callback(template.ajax, tmpReportData);
|
||||
}
|
||||
console.error(new Date() + ':unit/common.js 336:', e);
|
||||
}
|
||||
}
|
||||
main();
|
||||
}
|
||||
abort() {
|
||||
this.areadyAbortXhr = true;
|
||||
if (this.xhr) this.xhr.abort();
|
||||
}
|
||||
}
|
||||
exports.core = unitCommon;
|
||||
})();
|
@ -4,26 +4,26 @@
|
||||
"output": "release/"
|
||||
},
|
||||
"files": [
|
||||
"app/**/*.js*",
|
||||
"platform/**/*.js*",
|
||||
"shared/**/*.js*",
|
||||
"src/app/**/*.js*",
|
||||
"src/platform/**/*.js*",
|
||||
"src/shared/**/*.js*",
|
||||
"**/*/browser/dist/**/*",
|
||||
"**/*/node/dist/**/*",
|
||||
"core/api-manager/node/",
|
||||
"src/core/api-manager/node/",
|
||||
"core/**/package.json",
|
||||
"app/common/**/*",
|
||||
"app/browser/index.html",
|
||||
"src/app/common/**/*",
|
||||
"src/app/browser/index.html",
|
||||
"!**/*.ts"
|
||||
],
|
||||
"publish": ["github"],
|
||||
"generateUpdatesFilesForAllChannels":true,
|
||||
"generateUpdatesFilesForAllChannels": true,
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowElevation": true,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"win": {
|
||||
"icon": "app/common/images/256x256.png",
|
||||
"icon": "src/app/common/images/256x256.png",
|
||||
"target": [
|
||||
{
|
||||
"target": "nsis"
|
||||
@ -32,14 +32,14 @@
|
||||
]
|
||||
},
|
||||
"portable": {
|
||||
"splashImage": "app/common/images/eoapi.bmp"
|
||||
"splashImage": "src/app/common/images/eoapi.bmp"
|
||||
},
|
||||
"mac": {
|
||||
"icon": "app/common/images/512x512.png",
|
||||
"icon": "src/app/common/images/512x512.png",
|
||||
"target": ["dmg"]
|
||||
},
|
||||
"linux": {
|
||||
"icon": "app/common/images/",
|
||||
"icon": "src/app/common/images/",
|
||||
"target": ["AppImage"]
|
||||
}
|
||||
}
|
||||
|
24
package.json
@ -1,23 +1,23 @@
|
||||
{
|
||||
"name": "eoapi",
|
||||
"version": "0.0.1",
|
||||
"main": "app/electron-main/main.js",
|
||||
"main": "src/app/electron-main/main.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"postinstall": "npm-run-all --serial install:*",
|
||||
"start": "npm-run-all -p startall electron:serve",
|
||||
"startall": "npm-run-all -p start:*",
|
||||
"install:app": "cd app/browser&&npm install",
|
||||
"build:app": "cd app/browser&&npm run build",
|
||||
"install:api-manager": "cd core/api-manager/browser&&npm ci",
|
||||
"start:api-manager": "cd core/api-manager/browser&&npm start",
|
||||
"build:api-manager": "cd core/api-manager/browser&&npm run build:prod",
|
||||
"install:workbench": "cd workbench/browser&&npm install",
|
||||
"start:workbench": "cd workbench/browser&&npm start",
|
||||
"build:workbench": "cd workbench/browser&&npm run build",
|
||||
"install:market": "cd core/market/browser && npm install",
|
||||
"start:market": "cd core/market/browser && npm run serve",
|
||||
"build:market": "cd core/market/browser && npm run build",
|
||||
"install:app": "cd src/app/browser&&npm install",
|
||||
"build:app": "cd src/app/browser&&npm run build",
|
||||
"install:api-manager": "cd src/core/api-manager/browser&&npm ci",
|
||||
"start:api-manager": "cd src/core/api-manager/browser&&npm start",
|
||||
"build:api-manager": "cd src/core/api-manager/browser&&npm run build:prod",
|
||||
"install:workbench": "cd src/workbench/browser&&npm install",
|
||||
"start:workbench": "cd src/workbench/browser&&npm start",
|
||||
"build:workbench": "cd src/workbench/browser&&npm run build",
|
||||
"install:market": "cd src/core/market/browser && npm install",
|
||||
"start:market": "cd src/core/market/browser && npm run serve",
|
||||
"build:market": "cd src/core/market/browser && npm run build",
|
||||
"install:node-electron": "electron-builder install-app-deps",
|
||||
"electron:serve": "wait-on tcp:4200 && npm run electron:dev",
|
||||
"electron:dev:static": "npm run electron:tsc && electron .",
|
||||
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 726 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@ -1,6 +1,6 @@
|
||||
import { autoUpdater } from 'electron-updater';
|
||||
import log from 'electron-log';
|
||||
const appVersion = require('../../package.json').version;
|
||||
const appVersion = require('../../../package.json').version;
|
||||
|
||||
export class EoUpdater {
|
||||
constructor() {
|