| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- const { isJson5, json_parse, handleJson, joinPath, safeArray } = require('./utils');
- const constants = require('../client/constants/variable.js');
- const _ = require('underscore');
- const URL = require('url');
- const utils = require('./power-string.js').utils;
- const HTTP_METHOD = constants.HTTP_METHOD;
- const axios = require('axios');
- const qs = require('qs');
- const CryptoJS = require('crypto-js');
- const jsrsasign = require('jsrsasign');
- const https = require('https');
- const isNode = typeof global == 'object' && global.global === global;
- const ContentTypeMap = {
- 'application/json': 'json',
- 'application/xml': 'xml',
- 'text/xml': 'xml',
- 'application/html': 'html',
- 'text/html': 'html',
- other: 'text'
- };
- const getStorage = async (id)=>{
- try{
- if(isNode){
- let storage = global.storageCreator(id);
- let data = await storage.getItem();
- return {
- getItem: (name)=> data[name],
- setItem: (name, value)=>{
- data[name] = value;
- storage.setItem(name, value)
- }
- }
- }else{
- return {
- getItem: (name)=> window.localStorage.getItem(name),
- setItem: (name, value)=> window.localStorage.setItem(name, value)
- }
- }
- }catch(e){
- console.error(e)
- return {
- getItem: (name)=>{
- console.error(name, e)
- },
- setItem: (name, value)=>{
- console.error(name, value, e)
- }
- }
- }
- }
- async function httpRequestByNode(options) {
- function handleRes(response) {
- if (!response || typeof response !== 'object') {
- return {
- res: {
- status: 500,
- body: isNode
- ? '请求出错, 内网服务器自动化测试无法访问到,请检查是否为内网服务器!'
- : '请求出错'
- }
- };
- }
- return {
- res: {
- header: response.headers,
- status: response.status,
- body: response.data
- }
- };
- }
- function handleData() {
- let contentTypeItem;
- if (!options) return;
- if (typeof options.headers === 'object' && options.headers) {
- Object.keys(options.headers).forEach(key => {
- if (/content-type/i.test(key)) {
- if (options.headers[key]) {
- contentTypeItem = options.headers[key]
- .split(';')[0]
- .trim()
- .toLowerCase();
- }
- }
- if (!options.headers[key]) delete options.headers[key];
- });
- if (
- contentTypeItem === 'application/x-www-form-urlencoded' &&
- typeof options.data === 'object' &&
- options.data
- ) {
- options.data = qs.stringify(options.data);
- }
- }
- }
- try {
- handleData(options);
- let response = await axios({
- method: options.method,
- url: options.url,
- headers: options.headers,
- timeout: 10000,
- maxRedirects: 0,
- httpsAgent: new https.Agent({
- rejectUnauthorized: false
- }),
- data: options.data
- });
- return handleRes(response);
- } catch (err) {
- if (err.response === undefined) {
- return handleRes({
- headers: {},
- status: null,
- data: err.message
- });
- }
- return handleRes(err.response);
- }
- }
- function handleContentType(headers) {
- if (!headers || typeof headers !== 'object') return ContentTypeMap.other;
- let contentTypeItem = 'other';
- try {
- Object.keys(headers).forEach(key => {
- if (/content-type/i.test(key)) {
- contentTypeItem = headers[key]
- .split(';')[0]
- .trim()
- .toLowerCase();
- }
- });
- return ContentTypeMap[contentTypeItem] ? ContentTypeMap[contentTypeItem] : ContentTypeMap.other;
- } catch (err) {
- return ContentTypeMap.other;
- }
- }
- function checkRequestBodyIsRaw(method, reqBodyType) {
- if (
- reqBodyType &&
- reqBodyType !== 'file' &&
- reqBodyType !== 'form' &&
- HTTP_METHOD[method].request_body
- ) {
- return reqBodyType;
- }
- return false;
- }
- function checkNameIsExistInArray(name, arr) {
- let isRepeat = false;
- for (let i = 0; i < arr.length; i++) {
- let item = arr[i];
- if (item.name === name) {
- isRepeat = true;
- break;
- }
- }
- return isRepeat;
- }
- function handleCurrDomain(domains, case_env) {
- let currDomain = _.find(domains, item => item.name === case_env);
- if (!currDomain) {
- currDomain = domains[0];
- }
- return currDomain;
- }
- function sandboxByNode(sandbox = {}, script) {
- const vm = require('vm');
- script = new vm.Script(script);
- const context = new vm.createContext(sandbox);
- script.runInContext(context, {
- timeout: 10000
- });
- return sandbox;
- }
- async function sandbox(context = {}, script) {
- if (isNode) {
- try {
- context.context = context;
- context.console = console;
- context.Promise = Promise;
- context.setTimeout = setTimeout;
- context = sandboxByNode(context, script);
- } catch (err) {
- err.message = `Script: ${script}
- message: ${err.message}`;
- throw err;
- }
- } else {
- context = sandboxByBrowser(context, script);
- }
- if (context.promise && typeof context.promise === 'object' && context.promise.then) {
- try {
- await context.promise;
- } catch (err) {
- err.message = `Script: ${script}
- message: ${err.message}`;
- throw err;
- }
- }
- return context;
- }
- function sandboxByBrowser(context = {}, script) {
- if (!script || typeof script !== 'string') {
- return context;
- }
- let beginScript = '';
- for (var i in context) {
- beginScript += `var ${i} = context.${i};`;
- }
- try {
- eval(beginScript + script);
- } catch (err) {
- let message = `Script:
- ----CodeBegin----:
- ${beginScript}
- ${script}
- ----CodeEnd----
- `;
- err.message = `Script: ${message}
- message: ${err.message}`;
- throw err;
- }
- return context;
- }
- /**
- *
- * @param {*} defaultOptions
- * @param {*} preScript
- * @param {*} afterScript
- * @param {*} commonContext 负责传递一些业务信息,crossRequest 不关注具体传什么,只负责当中间人
- */
- async function crossRequest(defaultOptions, preScript, afterScript, commonContext = {}) {
- let options = Object.assign({}, defaultOptions);
- const taskId = options.taskId || Math.random() + '';
- let urlObj = URL.parse(options.url, true),
- query = {};
- query = Object.assign(query, urlObj.query);
- let context = {
- isNode,
- get href() {
- return urlObj.href;
- },
- set href(val) {
- throw new Error('context.href 不能被赋值');
- },
- get hostname() {
- return urlObj.hostname;
- },
- set hostname(val) {
- throw new Error('context.hostname 不能被赋值');
- },
- get caseId() {
- return options.caseId;
- },
- set caseId(val) {
- throw new Error('context.caseId 不能被赋值');
- },
- method: options.method,
- pathname: urlObj.pathname,
- query: query,
- requestHeader: options.headers || {},
- requestBody: options.data,
- promise: false,
- storage: await getStorage(taskId)
- };
- Object.assign(context, commonContext)
- context.utils = Object.freeze({
- _: _,
- CryptoJS: CryptoJS,
- jsrsasign: jsrsasign,
- base64: utils.base64,
- md5: utils.md5,
- sha1: utils.sha1,
- sha224: utils.sha224,
- sha256: utils.sha256,
- sha384: utils.sha384,
- sha512: utils.sha512,
- unbase64: utils.unbase64,
- axios: axios
- });
- if (preScript) {
- context = await sandbox(context, preScript);
- defaultOptions.url = options.url = URL.format({
- protocol: urlObj.protocol,
- host: urlObj.host,
- query: context.query,
- pathname: context.pathname
- });
- defaultOptions.headers = options.headers = context.requestHeader;
- defaultOptions.data = options.data = context.requestBody;
- }
- let data;
- if (isNode) {
- data = await httpRequestByNode(options);
- data.req = options;
- } else {
- data = await new Promise((resolve, reject) => {
- options.error = options.success = function(res, header, data) {
- let message = '';
- if (res && typeof res === 'string') {
- res = json_parse(data.res.body);
- data.res.body = res;
- }
- if (!isNode) message = '请求异常,请检查 chrome network 错误信息... https://juejin.im/post/5c888a3e5188257dee0322af 通过该链接查看教程")';
- if (isNaN(data.res.status)) {
- reject({
- body: res || message,
- header,
- message
- });
- }
- resolve(data);
- };
- window.crossRequest(options);
- });
- }
- if (afterScript) {
- context.responseData = data.res.body;
- context.responseHeader = data.res.header;
- context.responseStatus = data.res.status;
- context.runTime = data.runTime;
- context = await sandbox(context, afterScript);
- data.res.body = context.responseData;
- data.res.header = context.responseHeader;
- data.res.status = context.responseStatus;
- data.runTime = context.runTime;
- }
- return data;
- }
- function handleParams(interfaceData, handleValue, requestParams) {
- let interfaceRunData = Object.assign({}, interfaceData);
- function paramsToObjectWithEnable(arr) {
- const obj = {};
- safeArray(arr).forEach(item => {
- if (item && item.name && (item.enable || item.required === '1')) {
- obj[item.name] = handleValue(item.value, currDomain.global);
- if (requestParams) {
- requestParams[item.name] = obj[item.name];
- }
- }
- });
- return obj;
- }
- function paramsToObjectUnWithEnable(arr) {
- const obj = {};
- safeArray(arr).forEach(item => {
- if (item && item.name) {
- obj[item.name] = handleValue(item.value, currDomain.global);
- if (requestParams) {
- requestParams[item.name] = obj[item.name];
- }
- }
- });
- return obj;
- }
- let { case_env, path, env, _id } = interfaceRunData;
- let currDomain,
- requestBody,
- requestOptions = {};
- currDomain = handleCurrDomain(env, case_env);
- interfaceRunData.req_params = interfaceRunData.req_params || [];
- interfaceRunData.req_params.forEach(item => {
- let val = handleValue(item.value, currDomain.global);
- if (requestParams) {
- requestParams[item.name] = val;
- }
- path = path.replace(`:${item.name}`, val || `:${item.name}`);
- path = path.replace(`{${item.name}}`, val || `{${item.name}}`);
- });
- const urlObj = URL.parse(joinPath(currDomain.domain, path), true);
- const url = URL.format({
- protocol: urlObj.protocol || 'http',
- host: urlObj.host,
- pathname: urlObj.pathname,
- query: Object.assign(urlObj.query, paramsToObjectWithEnable(interfaceRunData.req_query))
- });
- let headers = paramsToObjectUnWithEnable(interfaceRunData.req_headers);
- requestOptions = {
- url,
- caseId: _id,
- method: interfaceRunData.method,
- headers,
- timeout: 82400000
- };
- // 对 raw 类型的 form 处理
- try {
- if (interfaceRunData.req_body_type === 'raw') {
- if (headers && headers['Content-Type']) {
- if (headers['Content-Type'].indexOf('application/x-www-form-urlencoded') >= 0) {
- interfaceRunData.req_body_type = 'form';
- let reqData = json_parse(interfaceRunData.req_body_other);
- if (reqData && typeof reqData === 'object') {
- interfaceRunData.req_body_form = [];
- Object.keys(reqData).forEach(key => {
- interfaceRunData.req_body_form.push({
- name: key,
- type: 'text',
- value: JSON.stringify(reqData[key]),
- enable: true
- });
- });
- }
- } else if (headers['Content-Type'].indexOf('application/json') >= 0) {
- interfaceRunData.req_body_type = 'json';
- }
- }
- }
- } catch (e) {
- console.error('err', e);
- }
- if (HTTP_METHOD[interfaceRunData.method].request_body) {
- if (interfaceRunData.req_body_type === 'form') {
- requestBody = paramsToObjectWithEnable(
- safeArray(interfaceRunData.req_body_form).filter(item => {
- return item.type == 'text';
- })
- );
- } else if (interfaceRunData.req_body_type === 'json') {
- let reqBody = isJson5(interfaceRunData.req_body_other);
- if (reqBody === false) {
- requestBody = interfaceRunData.req_body_other;
- } else {
- if (requestParams) {
- requestParams = Object.assign(requestParams, reqBody);
- }
- requestBody = handleJson(reqBody, val => handleValue(val, currDomain.global));
- }
- } else {
- requestBody = interfaceRunData.req_body_other;
- }
- requestOptions.data = requestBody;
- if (interfaceRunData.req_body_type === 'form') {
- requestOptions.files = paramsToObjectWithEnable(
- safeArray(interfaceRunData.req_body_form).filter(item => {
- return item.type == 'file';
- })
- );
- } else if (interfaceRunData.req_body_type === 'file') {
- requestOptions.file = 'single-file';
- }
- }
- return requestOptions;
- }
- exports.checkRequestBodyIsRaw = checkRequestBodyIsRaw;
- exports.handleParams = handleParams;
- exports.handleContentType = handleContentType;
- exports.crossRequest = crossRequest;
- exports.handleCurrDomain = handleCurrDomain;
- exports.checkNameIsExistInArray = checkNameIsExistInArray;
|