chen.lin
21 小时以前 9f724c61dfa4dc4c0eea66253ea0780b023622ae
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * 变量提取器
 * 参考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),
    };
};