/**
|
* 变量提取器
|
* 参考JMeter的变量提取实现,从响应中提取变量
|
*/
|
|
/**
|
* 正则表达式提取器
|
*/
|
export const extractByRegex = (source, regex, template = '$1$', matchNumber = 1) => {
|
if (!source || !regex) {
|
return null;
|
}
|
|
try {
|
const regexObj = new RegExp(regex, 'g');
|
const matches = [];
|
let match;
|
|
while ((match = regexObj.exec(source)) !== null) {
|
matches.push(match);
|
}
|
|
if (matches.length === 0) {
|
return null;
|
}
|
|
// matchNumber: 0=随机, -1=所有, 1-N=第N个
|
let selectedMatch;
|
if (matchNumber === 0) {
|
// 随机选择一个
|
selectedMatch = matches[Math.floor(Math.random() * matches.length)];
|
} else if (matchNumber === -1) {
|
// 返回所有匹配(用逗号分隔)
|
return matches.map(m => applyTemplate(m, template)).join(',');
|
} else {
|
// 选择第N个(从1开始)
|
selectedMatch = matches[matchNumber - 1] || matches[0];
|
}
|
|
if (!selectedMatch) {
|
return null;
|
}
|
|
return applyTemplate(selectedMatch, template);
|
} catch (error) {
|
console.error('正则表达式提取失败:', error);
|
return null;
|
}
|
};
|
|
/**
|
* 应用模板
|
*/
|
const applyTemplate = (match, template) => {
|
if (!template || template === '$1$') {
|
return match[1] || match[0];
|
}
|
|
let result = template;
|
// 替换 $1$, $2$, ... 为匹配组
|
for (let i = 0; i < match.length; i++) {
|
result = result.replace(new RegExp(`\\$${i}\\$`, 'g'), match[i] || '');
|
}
|
return result;
|
};
|
|
/**
|
* JSON提取器
|
*/
|
export const extractByJsonPath = (data, jsonPath, defaultValue = '') => {
|
if (!jsonPath || !data) {
|
return defaultValue;
|
}
|
|
try {
|
// 简化版JSONPath实现
|
if (jsonPath.startsWith('$.')) {
|
const path = jsonPath.substring(2);
|
const keys = path.split('.');
|
let value = data;
|
|
for (const key of keys) {
|
if (value === null || value === undefined) {
|
return defaultValue;
|
}
|
// 支持数组索引 [0]
|
if (key.includes('[') && key.includes(']')) {
|
const arrayKey = key.substring(0, key.indexOf('['));
|
const index = parseInt(key.substring(key.indexOf('[') + 1, key.indexOf(']')));
|
if (arrayKey) {
|
value = value[arrayKey];
|
}
|
if (Array.isArray(value)) {
|
value = value[index];
|
} else {
|
return defaultValue;
|
}
|
} else {
|
value = value[key];
|
}
|
}
|
return value !== null && value !== undefined ? String(value) : defaultValue;
|
}
|
|
if (jsonPath === '$') {
|
return typeof data === 'string' ? data : JSON.stringify(data);
|
}
|
|
return defaultValue;
|
} catch (error) {
|
console.error('JSONPath提取失败:', error);
|
return defaultValue;
|
}
|
};
|
|
/**
|
* 从响应中提取变量
|
*/
|
export const extractVariables = (extractorConfig, response, request) => {
|
const { extractType, variableName, extractPath, template, matchNumber, defaultValue } = extractorConfig;
|
|
if (!variableName) {
|
return {};
|
}
|
|
let extractedValue = null;
|
|
switch (extractType) {
|
case 'regex':
|
const source = typeof response?.data === 'string'
|
? response.data
|
: JSON.stringify(response?.data || {});
|
extractedValue = extractByRegex(source, extractPath, template || '$1$', matchNumber || 1);
|
break;
|
case 'json_path':
|
extractedValue = extractByJsonPath(response?.data || response, extractPath, defaultValue || '');
|
break;
|
default:
|
extractedValue = null;
|
}
|
|
if (extractedValue === null || extractedValue === undefined) {
|
return {};
|
}
|
|
return {
|
[variableName]: String(extractedValue),
|
};
|
};
|