/** * 变量提取器 * 参考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), }; };