-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathtest-unified-proxy.js
More file actions
342 lines (300 loc) · 10.6 KB
/
test-unified-proxy.js
File metadata and controls
342 lines (300 loc) · 10.6 KB
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/**
* 全能代理测试脚本
* 测试 unified-proxy 的智能路由、错误处理和回退机制
*/
import fetch from 'node-fetch';
// 测试配置
const TEST_CONFIG = {
baseUrl: 'http://localhost:3001',
authCode: 'drpy',
timeout: 10000
};
// 测试用例
const TEST_CASES = [
// M3U8 文件测试
{
name: 'M3U8 播放列表 - 应该使用 M3U8 代理',
url: 'https://example.com/playlist.m3u8',
expectedType: 'm3u8',
shouldSucceed: false, // 示例URL,预期会失败但能测试路由逻辑
description: '测试 M3U8 文件的智能识别和路由'
},
// TS 文件测试
{
name: 'TS 视频片段 - 应该使用 M3U8 代理',
url: 'https://example.com/segment001.ts',
expectedType: 'm3u8',
shouldSucceed: false,
description: '测试 TS 文件的智能识别和路由'
},
// 普通文件测试
{
name: '普通视频文件 - 应该使用文件代理',
url: 'https://example.com/video.mp4',
expectedType: 'file',
shouldSucceed: false,
description: '测试普通文件的智能识别和路由'
},
// 图片文件测试
{
name: '图片文件 - 应该使用文件代理',
url: 'https://example.com/image.jpg',
expectedType: 'file',
shouldSucceed: false,
description: '测试图片文件的智能识别和路由'
},
// 强制类型测试
{
name: '强制使用文件代理',
url: 'https://example.com/test.m3u8',
forceType: 'file',
expectedType: 'file',
shouldSucceed: false,
description: '测试强制指定代理类型功能'
},
// 自定义请求头测试
{
name: '带自定义请求头的测试',
url: 'https://example.com/test.mp4',
headers: {
'User-Agent': 'UnifiedProxyTest/1.0',
'X-Custom-Header': 'test-value'
},
expectedType: 'file',
shouldSucceed: false,
description: '测试自定义请求头的传递'
},
// 错误处理测试
{
name: '无效URL测试',
url: 'invalid-url',
shouldSucceed: false,
expectError: true,
description: '测试无效URL的错误处理'
},
// 内网地址阻止测试
{
name: '内网地址阻止测试',
url: 'http://192.168.1.1/test.mp4',
shouldSucceed: false,
expectError: true,
expectedErrorCode: 403,
description: '测试内网地址访问阻止功能'
}
];
/**
* 发起代理请求
* @param {Object} testCase - 测试用例
* @returns {Promise<Object>} 测试结果
*/
async function makeProxyRequest(testCase) {
try {
// 构建请求URL
const encodedUrl = encodeURIComponent(testCase.url);
let proxyUrl = `${TEST_CONFIG.baseUrl}/unified-proxy/proxy?url=${encodedUrl}&auth=${TEST_CONFIG.authCode}`;
// 添加强制类型参数
if (testCase.forceType) {
proxyUrl += `&type=${testCase.forceType}`;
}
// 添加自定义请求头
if (testCase.headers) {
const encodedHeaders = encodeURIComponent(JSON.stringify(testCase.headers));
proxyUrl += `&headers=${encodedHeaders}`;
}
console.log(`\n🔗 请求URL: ${proxyUrl}`);
// 发起请求
const startTime = Date.now();
const response = await fetch(proxyUrl, {
method: 'GET',
timeout: TEST_CONFIG.timeout
});
const endTime = Date.now();
// 获取响应内容(限制大小)
let responseText = '';
try {
const text = await response.text();
responseText = text.length > 500 ? text.substring(0, 500) + '...' : text;
} catch (textError) {
responseText = `Failed to read response: ${textError.message}`;
}
return {
success: response.ok,
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries()),
responseTime: endTime - startTime,
responseText: responseText,
contentType: response.headers.get('content-type'),
contentLength: response.headers.get('content-length')
};
} catch (error) {
return {
success: false,
error: error.message,
errorType: error.name
};
}
}
/**
* 测试代理状态接口
*/
async function testProxyStatus() {
console.log('\n📊 测试代理状态接口...');
try {
const response = await fetch(`${TEST_CONFIG.baseUrl}/unified-proxy/status`);
const statusData = await response.json();
console.log('✅ 状态接口响应:', JSON.stringify(statusData, null, 2));
return true;
} catch (error) {
console.log('❌ 状态接口测试失败:', error.message);
return false;
}
}
/**
* 分析测试结果
* @param {Object} testCase - 测试用例
* @param {Object} result - 测试结果
* @returns {Object} 分析结果
*/
function analyzeResult(testCase, result) {
const analysis = {
testName: testCase.name,
passed: false,
issues: [],
details: {}
};
// 检查是否符合预期
if (testCase.expectError) {
// 预期错误的测试
if (!result.success) {
analysis.passed = true;
if (testCase.expectedErrorCode && result.status !== testCase.expectedErrorCode) {
analysis.issues.push(`Expected error code ${testCase.expectedErrorCode}, got ${result.status}`);
analysis.passed = false;
}
} else {
analysis.issues.push('Expected error but request succeeded');
}
} else if (testCase.shouldSucceed) {
// 预期成功的测试
if (result.success) {
analysis.passed = true;
} else {
analysis.issues.push(`Expected success but got error: ${result.error || result.status}`);
}
} else {
// 预期失败但要测试路由逻辑的测试
analysis.passed = true; // 主要测试路由逻辑,不关心最终成功与否
// 分析响应头以判断使用的代理类型
if (result.headers) {
const contentType = result.contentType || '';
if (testCase.expectedType === 'm3u8' && contentType.includes('mpegurl')) {
analysis.details.detectedType = 'm3u8';
} else if (testCase.expectedType === 'file') {
analysis.details.detectedType = 'file';
}
}
}
// 记录响应时间
if (result.responseTime) {
analysis.details.responseTime = result.responseTime;
if (result.responseTime > 5000) {
analysis.issues.push('Response time too slow (>5s)');
}
}
return analysis;
}
/**
* 运行所有测试
*/
async function runAllTests() {
console.log('🚀 开始全能代理测试...\n');
console.log(`📍 测试服务器: ${TEST_CONFIG.baseUrl}`);
console.log(`🔑 认证码: ${TEST_CONFIG.authCode}`);
console.log(`⏱️ 超时时间: ${TEST_CONFIG.timeout}ms\n`);
// 测试状态接口
const statusOk = await testProxyStatus();
if (!statusOk) {
console.log('❌ 代理服务器状态检查失败,请确保服务器正在运行');
return;
}
const results = [];
let passedTests = 0;
let totalTests = TEST_CASES.length;
// 运行每个测试用例
for (let i = 0; i < TEST_CASES.length; i++) {
const testCase = TEST_CASES[i];
console.log(`\n📋 测试 ${i + 1}/${totalTests}: ${testCase.name}`);
console.log(`📝 描述: ${testCase.description}`);
console.log(`🎯 目标URL: ${testCase.url}`);
const result = await makeProxyRequest(testCase);
const analysis = analyzeResult(testCase, result);
results.push({
testCase,
result,
analysis
});
// 显示测试结果
if (analysis.passed) {
console.log('✅ 测试通过');
passedTests++;
} else {
console.log('❌ 测试失败');
analysis.issues.forEach(issue => {
console.log(` ⚠️ ${issue}`);
});
}
// 显示详细信息
if (result.success !== undefined) {
console.log(`📊 状态: ${result.status} ${result.statusText || ''}`);
}
if (result.error) {
console.log(`❗ 错误: ${result.error}`);
}
if (result.responseTime) {
console.log(`⏱️ 响应时间: ${result.responseTime}ms`);
}
if (result.contentType) {
console.log(`📄 内容类型: ${result.contentType}`);
}
// 等待一下避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
}
// 显示测试总结
console.log('\n' + '='.repeat(60));
console.log('📊 测试总结');
console.log('='.repeat(60));
console.log(`✅ 通过: ${passedTests}/${totalTests}`);
console.log(`❌ 失败: ${totalTests - passedTests}/${totalTests}`);
console.log(`📈 成功率: ${((passedTests / totalTests) * 100).toFixed(1)}%`);
// 显示失败的测试
const failedTests = results.filter(r => !r.analysis.passed);
if (failedTests.length > 0) {
console.log('\n❌ 失败的测试:');
failedTests.forEach((test, index) => {
console.log(`${index + 1}. ${test.testCase.name}`);
test.analysis.issues.forEach(issue => {
console.log(` - ${issue}`);
});
});
}
// 性能统计
const responseTimes = results
.map(r => r.result.responseTime)
.filter(time => time !== undefined);
if (responseTimes.length > 0) {
const avgTime = responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length;
const maxTime = Math.max(...responseTimes);
const minTime = Math.min(...responseTimes);
console.log('\n⏱️ 性能统计:');
console.log(` 平均响应时间: ${avgTime.toFixed(0)}ms`);
console.log(` 最快响应时间: ${minTime}ms`);
console.log(` 最慢响应时间: ${maxTime}ms`);
}
console.log('\n🎉 测试完成!');
}
// 运行测试
runAllTests().catch(error => {
console.error('💥 测试运行失败:', error);
process.exit(1);
});