yapi/common/postmanLib.js

435 lines
12 KiB
JavaScript
Raw Normal View History

const { isJson5, json_parse, handleJson, joinPath, safeArray } = require('./utils');
const constants = require('../client/constants/variable.js');
const _ = require('underscore');
const URL = require('url');
2018-02-08 16:03:14 +08:00
const utils = require('./power-string.js').utils;
const HTTP_METHOD = constants.HTTP_METHOD;
2018-02-08 21:29:10 +08:00
const axios = require('axios');
const qs = require('qs');
2018-02-08 21:29:10 +08:00
const isNode = typeof global == 'object' && global.global === global;
const ContentTypeMap = {
'application/json': 'json',
'application/xml': 'xml',
other: 'text',
'application/html': 'html'
};
2018-02-08 21:29:10 +08:00
async function httpRequestByNode(options) {
function handleRes(response) {
if (!response || typeof response !== 'object') {
2018-02-12 18:13:12 +08:00
return {
res: {
2018-04-11 20:13:29 +08:00
status: 500,
body: isNode
? '请求出错, 内网服务器自动化测试无法访问到,请检查是否为内网服务器!'
: '请求出错'
2018-02-12 18:13:12 +08:00
}
};
2018-04-11 20:13:29 +08:00
}
return {
res: {
header: response.headers,
status: response.status,
body: response.data
}
};
2018-02-08 21:29:10 +08:00
}
function handleData() {
2018-02-08 21:29:10 +08:00
let contentTypeItem;
if (!options) return;
if (typeof options.headers === 'object' && options.headers) {
2018-02-08 21:29:10 +08:00
Object.keys(options.headers).forEach(key => {
if (/content-type/i.test(key)) {
if (options.headers[key]) {
contentTypeItem = options.headers[key]
.split(';')[0]
.trim()
.toLowerCase();
}
2018-02-08 21:29:10 +08:00
}
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);
2018-02-08 21:29:10 +08:00
}
}
}
try {
2018-02-08 21:29:10 +08:00
handleData(options);
let response = await axios({
2018-02-08 21:29:10 +08:00
method: options.method,
url: options.url,
headers: options.headers,
timeout: 5000,
data: options.data
});
return handleRes(response);
} catch (err) {
if (err.response === undefined) {
2018-02-12 18:13:12 +08:00
handleRes({
headers: {},
status: null,
data: err.message
});
2018-02-12 18:13:12 +08:00
}
return handleRes(err.response);
2018-02-08 21:29:10 +08:00
}
}
2017-12-04 21:32:09 +08:00
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) {
2018-02-09 15:09:43 +08:00
const vm = require('vm');
script = new vm.Script(script);
const context = new vm.createContext(sandbox);
script.runInContext(context, {
timeout: 3000
});
return sandbox;
}
async function sandbox(context = {}, script) {
if (isNode) {
try {
2018-02-09 15:09:43 +08:00
context.context = context;
context.console = console;
2018-04-28 17:02:14 +08:00
context.Promise = Promise;
context.setTimeout = setTimeout;
context = sandboxByNode(context, script);
} catch (err) {
2018-02-09 15:09:43 +08:00
err.message = `Script: ${script}
message: ${err.message}`;
2018-02-09 15:09:43 +08:00
throw err;
}
} else {
context = sandboxByBrowser(context, script);
2018-02-09 15:09:43 +08:00
}
if (context.promise && typeof context.promise === 'object' && context.promise.then) {
try {
await context.promise;
} catch (err) {
2018-04-28 17:02:14 +08:00
err.message = `Script: ${script}
message: ${err.message}`;
2018-04-28 17:02:14 +08:00
throw err;
}
}
2018-02-09 15:09:43 +08:00
return context;
}
function sandboxByBrowser(context = {}, script) {
if (!script || typeof script !== 'string') {
2017-12-04 22:40:05 +08:00
return context;
}
let beginScript = '';
for (var i in context) {
2017-12-04 22:40:05 +08:00
beginScript += `var ${i} = context.${i};`;
}
try {
2017-12-04 22:40:05 +08:00
eval(beginScript + script);
} catch (err) {
let message = `Script:
----CodeBegin----:
${beginScript}
${script}
----CodeEnd----
`;
err.message = `Script: ${message}
message: ${err.message}`;
throw err;
2017-12-04 22:40:05 +08:00
}
return context;
2017-12-04 21:32:09 +08:00
}
2018-02-08 21:29:10 +08:00
async function crossRequest(defaultOptions, preScript, afterScript) {
let options = Object.assign({}, defaultOptions);
let urlObj = URL.parse(options.url, true),
query = {};
2017-12-04 22:40:05 +08:00
query = Object.assign(query, urlObj.query);
let context = {
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 不能被赋值')
},
2018-03-14 11:26:40 +08:00
method: options.method,
2017-12-04 22:40:05 +08:00
pathname: urlObj.pathname,
query: query,
requestHeader: options.headers || {},
requestBody: options.data,
promise: false
2017-12-04 22:40:05 +08:00
};
2017-12-04 21:32:09 +08:00
context.utils = Object.freeze({
_: _,
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) {
2018-04-28 17:02:14 +08:00
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;
2017-12-04 21:32:09 +08:00
}
2018-02-08 21:29:10 +08:00
let data;
if (isNode) {
data = await httpRequestByNode(options);
2018-02-08 21:29:10 +08:00
data.req = options;
} else {
data = await new Promise((resolve, reject) => {
options.error = options.success = function(res, header, data) {
2018-02-08 21:29:10 +08:00
let message = '';
if (res && typeof res === 'string') {
2018-02-09 15:09:43 +08:00
res = json_parse(data.res.body);
2018-02-08 21:29:10 +08:00
data.res.body = res;
}
if (!isNode) message = '请求异常,请检查 chrome network 错误信息...';
if (isNaN(data.res.status)) {
reject({
body: res || message,
header,
message
});
2018-02-08 21:29:10 +08:00
}
resolve(data);
};
2018-02-08 21:29:10 +08:00
window.crossRequest(options);
});
2018-02-08 21:29:10 +08:00
}
2018-02-08 21:29:10 +08:00
if (afterScript) {
context.responseData = data.res.body;
context.responseHeader = data.res.header;
context.responseStatus = data.res.status;
context.runTime = data.runTime;
2018-04-28 17:02:14 +08:00
context = await sandbox(context, afterScript);
2018-02-08 21:29:10 +08:00
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) {
2018-06-13 13:59:36 +08:00
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);
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);
if (requestParams) {
requestParams[item.name] = obj[item.name];
}
}
});
return obj;
}
2018-06-13 13:59:36 +08:00
let { case_env, path, env, _id } = interfaceRunData;
let currDomain,
requestBody,
requestOptions = {};
2018-06-13 13:59:36 +08:00
interfaceRunData.req_params = interfaceRunData.req_params || [];
interfaceRunData.req_params.forEach(item => {
let val = handleValue(item.value);
if (requestParams) {
requestParams[item.name] = val;
}
path = path.replace(`:${item.name}`, val || `:${item.name}`);
2017-12-07 10:38:41 +08:00
path = path.replace(`{${item.name}}`, val || `{${item.name}}`);
});
currDomain = handleCurrDomain(env, case_env);
2017-12-04 21:32:09 +08:00
const urlObj = URL.parse(joinPath(currDomain.domain, path), true);
const url = URL.format({
protocol: urlObj.protocol || 'http',
host: urlObj.host,
pathname: urlObj.pathname,
2018-06-13 13:59:36 +08:00
query: Object.assign(urlObj.query, paramsToObjectWithEnable(interfaceRunData.req_query))
});
2018-06-13 13:59:36 +08:00
let headers = paramsToObjectUnWithEnable(interfaceRunData.req_headers);
2017-12-04 21:32:09 +08:00
requestOptions = {
url,
caseId: _id,
2018-06-13 13:59:36 +08:00
method: interfaceRunData.method,
headers,
2017-12-04 21:32:09 +08:00
timeout: 82400000
};
2017-12-04 21:32:09 +08:00
2018-06-13 13:59:36 +08:00
// 对 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.log('err',e);
}
if (HTTP_METHOD[interfaceRunData.method].request_body) {
if (interfaceRunData.req_body_type === 'form') {
requestBody = paramsToObjectWithEnable(
2018-06-13 13:59:36 +08:00
safeArray(interfaceRunData.req_body_form).filter(item => {
return item.type == 'text';
})
);
2018-06-13 13:59:36 +08:00
} else if (interfaceRunData.req_body_type === 'json') {
let reqBody = isJson5(interfaceRunData.req_body_other);
if (reqBody === false) {
2018-06-13 13:59:36 +08:00
requestBody = interfaceRunData.req_body_other;
} else {
if (requestParams) {
requestParams = Object.assign(requestParams, reqBody);
}
requestBody = handleJson(reqBody, handleValue);
}
} else {
2018-06-13 13:59:36 +08:00
requestBody = interfaceRunData.req_body_other;
}
2017-12-04 21:32:09 +08:00
requestOptions.data = requestBody;
2018-06-13 13:59:36 +08:00
if (interfaceRunData.req_body_type === 'form') {
requestOptions.files = paramsToObjectWithEnable(
2018-06-13 13:59:36 +08:00
safeArray(interfaceRunData.req_body_form).filter(item => {
return item.type == 'file';
})
);
2018-06-13 13:59:36 +08:00
} else if (interfaceRunData.req_body_type === 'file') {
requestOptions.file = 'single-file';
2017-12-04 21:32:09 +08:00
}
}
return requestOptions;
2018-02-08 16:03:14 +08:00
}
exports.checkRequestBodyIsRaw = checkRequestBodyIsRaw;
exports.handleParams = handleParams;
exports.handleContentType = handleContentType;
exports.crossRequest = crossRequest;
exports.handleCurrDomain = handleCurrDomain;
exports.checkNameIsExistInArray = checkNameIsExistInArray;