feat: add lost request lib

This commit is contained in:
everright 2022-04-19 15:50:08 +08:00
parent 9951c1485f
commit 190e588259
19 changed files with 7742 additions and 0 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ dist/
!src/core/market/browser/**/*.js
!src/core/market/browser/dist/icon.png
!src/core/api-manager/browser/dist/assets/images/icon.png
!src/core/api-manager/node/request/**/*.js
# dependencies
node_modules

View File

@ -0,0 +1,509 @@
/**
* @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;

View File

@ -0,0 +1,187 @@
/**
* @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);
};

View File

@ -0,0 +1,215 @@
(() => {
'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;
})()

View File

@ -0,0 +1,534 @@
(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.js122ES 签名错误):' + 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;
})();

View File

@ -0,0 +1,491 @@
(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;
})();

View File

@ -0,0 +1,458 @@
(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;
})();

View File

@ -0,0 +1,289 @@
(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;
})();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
(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;
})();

View File

@ -0,0 +1,3 @@
if (parseInt(process.versions.node.split('.')[0]) < 6) throw new Error('vm2 requires Node.js version 6 or newer.');
module.exports = require('./lib/main');

View File

@ -0,0 +1,35 @@
'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`);
}
}
}
}

View File

@ -0,0 +1,815 @@
/* 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;

View File

@ -0,0 +1,613 @@
/* 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;

View File

@ -0,0 +1,530 @@
/* 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);

View File

@ -0,0 +1,7 @@
const match = (wildcard, s) => {
const regexString = wildcard.replace(/\*/, '\\S*').replace(/\?/g, '.');
const regex = new RegExp(regexString);
return regex.test(s);
};
module.exports = {match};

View File

@ -0,0 +1,112 @@
(() => {
'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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')+tmpResult.substr(tmpPreIndex,tmpLastIndex)+tmpResult.substr(tmpLastIndex,tmpResult.length).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
return String(text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
};
return function (input,inputXmlAttrObj) {
var xotree = new XML.ObjTree();
return xotree.writeXML(input,inputXmlAttrObj||{});
}
}
}
exports.core = mainClass;
})();

View File

@ -0,0 +1,24 @@
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;
}
}
});

View File

@ -0,0 +1,830 @@
(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;
})();