kuefr commited on
Commit
80a9533
·
verified ·
1 Parent(s): c58b8ed

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +119 -50
index.js CHANGED
@@ -1378,10 +1378,7 @@ class ApiProxyService {
1378
 
1379
  if (params.stream) {
1380
  // 假流式处理:使用非流式请求,然后模拟流式响应
1381
- const result = await this.handleFakeStreamRequest(requestBody, params, requestId, res, req.authKey, logData, startTime);
1382
- if (!result.success) {
1383
- res.status(result.status || 500).json({ error: result.error });
1384
- }
1385
  } else {
1386
  // 非流式请求和原来一样
1387
  const result = await this.executeNormalRequest(requestBody, params, requestId);
@@ -1408,44 +1405,30 @@ class ApiProxyService {
1408
  logData.duration = Date.now() - startTime;
1409
  this.logRequest(req.authKey, logData);
1410
 
1411
- res.status(500).json({
1412
- error: {
1413
- message: '内部服务器错误: ' + error.message,
1414
- type: 'internal_server_error',
1415
- code: 'server_error'
1416
- }
1417
- });
 
 
 
1418
  }
1419
  }
1420
 
1421
  /**
1422
- * 处理假流式请求
1423
  */
1424
  async handleFakeStreamRequest(requestBody, params, requestId, res, authKey, logData, startTime) {
1425
- try {
1426
- // 设置流式响应头
1427
- res.writeHead(200, {
1428
- 'Content-Type': 'text/event-stream',
1429
- 'Cache-Control': 'no-cache',
1430
- 'Connection': 'keep-alive',
1431
- 'Access-Control-Allow-Origin': '*'
1432
- });
1433
-
1434
- // 开始发送ping消息保持连接活跃
1435
- const pingInterval = setInterval(() => {
1436
- try {
1437
- res.write(': ping\n\n');
1438
- } catch (error) {
1439
- clearInterval(pingInterval);
1440
- }
1441
- }, 1000); // 每秒发送一次ping
1442
 
 
1443
  // 执行非流式请求
1444
  const result = await this.executeNormalRequest(requestBody, params, requestId);
1445
 
1446
- // 停止ping
1447
- clearInterval(pingInterval);
1448
-
1449
  logData.responseTime = new Date().toISOString();
1450
  logData.duration = Date.now() - startTime;
1451
 
@@ -1454,10 +1437,34 @@ class ApiProxyService {
1454
  logData.error = result.error;
1455
  this.logRequest(authKey, logData);
1456
 
1457
- res.write(`data: ${JSON.stringify({ error: result.error })}\n\n`);
1458
- res.write('data: [DONE]\n\n');
1459
- res.end();
1460
- return { success: false };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1461
  }
1462
 
1463
  // 获取响应文本
@@ -1465,22 +1472,50 @@ class ApiProxyService {
1465
  logData.responseContent = responseText;
1466
  this.logRequest(authKey, logData);
1467
 
1468
- if (responseText) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1469
  // 将文本拆分为假流式块
1470
  const chunks = ResponseConverter.splitTextToFakeStream(responseText, requestId, params.model);
1471
 
1472
  // 逐步发送块,模拟流式响应
1473
  for (const chunk of chunks) {
 
1474
  res.write(chunk);
1475
  // 添加小延迟以模拟真实的流式响应
1476
- await new Promise(resolve => setTimeout(resolve, 10));
1477
  }
1478
  }
1479
 
1480
- res.write('data: [DONE]\n\n');
1481
- res.end();
1482
-
1483
- return { success: true };
 
 
 
 
 
1484
 
1485
  } catch (error) {
1486
  console.error('处理假流式请求错误:', error);
@@ -1491,14 +1526,48 @@ class ApiProxyService {
1491
  logData.duration = Date.now() - startTime;
1492
  this.logRequest(authKey, logData);
1493
 
1494
- try {
1495
- res.write(`data: ${JSON.stringify({ error: '内部服务器错误: ' + error.message })}\n\n`);
1496
- res.write('data: [DONE]\n\n');
1497
- res.end();
1498
- } catch (writeError) {
1499
- console.error('写入错误响应失败:', writeError);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1500
  }
1501
- return { success: false, error: error.message };
1502
  }
1503
  }
1504
 
@@ -2027,7 +2096,7 @@ class Server {
2027
  invalidKeys: this.apiProxy.config.invalidApiKeys.length,
2028
  authKeys: this.apiProxy.authKeyManager.getAllKeys().length,
2029
  fileLoggingEnabled: this.apiProxy.logManager.getFileLoggingStatus(),
2030
- version: '2.3.0',
2031
  features: ['text', 'vision', 'stream', 'fake_stream', 'load_balancing', 'auto_retry', 'logging', 'multi_auth', 'file_export']
2032
  });
2033
  });
 
1378
 
1379
  if (params.stream) {
1380
  // 假流式处理:使用非流式请求,然后模拟流式响应
1381
+ await this.handleFakeStreamRequest(requestBody, params, requestId, res, req.authKey, logData, startTime);
 
 
 
1382
  } else {
1383
  // 非流式请求和原来一样
1384
  const result = await this.executeNormalRequest(requestBody, params, requestId);
 
1405
  logData.duration = Date.now() - startTime;
1406
  this.logRequest(req.authKey, logData);
1407
 
1408
+ // 修复:确保在错误情况下正确响应
1409
+ if (!res.headersSent) {
1410
+ res.status(500).json({
1411
+ error: {
1412
+ message: '内部服务器错误: ' + error.message,
1413
+ type: 'internal_server_error',
1414
+ code: 'server_error'
1415
+ }
1416
+ });
1417
+ }
1418
  }
1419
  }
1420
 
1421
  /**
1422
+ * 处理假流式请求(修复版)
1423
  */
1424
  async handleFakeStreamRequest(requestBody, params, requestId, res, authKey, logData, startTime) {
1425
+ let responseStarted = false;
1426
+ let pingInterval = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1427
 
1428
+ try {
1429
  // 执行非流式请求
1430
  const result = await this.executeNormalRequest(requestBody, params, requestId);
1431
 
 
 
 
1432
  logData.responseTime = new Date().toISOString();
1433
  logData.duration = Date.now() - startTime;
1434
 
 
1437
  logData.error = result.error;
1438
  this.logRequest(authKey, logData);
1439
 
1440
+ // 发送错误响应为流式格式
1441
+ if (!res.headersSent) {
1442
+ res.writeHead(200, {
1443
+ 'Content-Type': 'text/event-stream',
1444
+ 'Cache-Control': 'no-cache',
1445
+ 'Connection': 'keep-alive',
1446
+ 'Access-Control-Allow-Origin': '*'
1447
+ });
1448
+ responseStarted = true;
1449
+ }
1450
+
1451
+ if (responseStarted) {
1452
+ const errorChunk = {
1453
+ id: requestId,
1454
+ object: 'chat.completion.chunk',
1455
+ created: Math.floor(Date.now() / 1000),
1456
+ model: params.model,
1457
+ choices: [{
1458
+ index: 0,
1459
+ delta: { content: `错误: ${result.error}` },
1460
+ finish_reason: 'stop'
1461
+ }]
1462
+ };
1463
+ res.write(`data: ${JSON.stringify(errorChunk)}\n\n`);
1464
+ res.write('data: [DONE]\n\n');
1465
+ res.end();
1466
+ }
1467
+ return;
1468
  }
1469
 
1470
  // 获取响应文本
 
1472
  logData.responseContent = responseText;
1473
  this.logRequest(authKey, logData);
1474
 
1475
+ // 设置流式响应头
1476
+ if (!res.headersSent) {
1477
+ res.writeHead(200, {
1478
+ 'Content-Type': 'text/event-stream',
1479
+ 'Cache-Control': 'no-cache',
1480
+ 'Connection': 'keep-alive',
1481
+ 'Access-Control-Allow-Origin': '*'
1482
+ });
1483
+ responseStarted = true;
1484
+
1485
+ // 开始发送ping消息保持连接活跃
1486
+ pingInterval = setInterval(() => {
1487
+ try {
1488
+ if (!res.destroyed) {
1489
+ res.write(': ping\n\n');
1490
+ }
1491
+ } catch (error) {
1492
+ clearInterval(pingInterval);
1493
+ }
1494
+ }, 1000);
1495
+ }
1496
+
1497
+ if (responseText && responseStarted) {
1498
  // 将文本拆分为假流式块
1499
  const chunks = ResponseConverter.splitTextToFakeStream(responseText, requestId, params.model);
1500
 
1501
  // 逐步发送块,模拟流式响应
1502
  for (const chunk of chunks) {
1503
+ if (res.destroyed) break;
1504
  res.write(chunk);
1505
  // 添加小延迟以模拟真实的流式响应
1506
+ await new Promise(resolve => setTimeout(resolve, 50));
1507
  }
1508
  }
1509
 
1510
+ // 停止ping并结束响应
1511
+ if (pingInterval) {
1512
+ clearInterval(pingInterval);
1513
+ }
1514
+
1515
+ if (responseStarted && !res.destroyed) {
1516
+ res.write('data: [DONE]\n\n');
1517
+ res.end();
1518
+ }
1519
 
1520
  } catch (error) {
1521
  console.error('处理假流式请求错误:', error);
 
1526
  logData.duration = Date.now() - startTime;
1527
  this.logRequest(authKey, logData);
1528
 
1529
+ // 停止ping
1530
+ if (pingInterval) {
1531
+ clearInterval(pingInterval);
1532
+ }
1533
+
1534
+ // 如果还没有开始响应,设置流式响应头
1535
+ if (!res.headersSent && !responseStarted) {
1536
+ try {
1537
+ res.writeHead(200, {
1538
+ 'Content-Type': 'text/event-stream',
1539
+ 'Cache-Control': 'no-cache',
1540
+ 'Connection': 'keep-alive',
1541
+ 'Access-Control-Allow-Origin': '*'
1542
+ });
1543
+ responseStarted = true;
1544
+ } catch (headerError) {
1545
+ console.error('设置响应头失败:', headerError);
1546
+ return;
1547
+ }
1548
+ }
1549
+
1550
+ // 发送错误信息
1551
+ if (responseStarted && !res.destroyed) {
1552
+ try {
1553
+ const errorChunk = {
1554
+ id: requestId,
1555
+ object: 'chat.completion.chunk',
1556
+ created: Math.floor(Date.now() / 1000),
1557
+ model: params.model,
1558
+ choices: [{
1559
+ index: 0,
1560
+ delta: { content: `错误: ${error.message}` },
1561
+ finish_reason: 'stop'
1562
+ }]
1563
+ };
1564
+ res.write(`data: ${JSON.stringify(errorChunk)}\n\n`);
1565
+ res.write('data: [DONE]\n\n');
1566
+ res.end();
1567
+ } catch (writeError) {
1568
+ console.error('写入错误响应失败:', writeError);
1569
+ }
1570
  }
 
1571
  }
1572
  }
1573
 
 
2096
  invalidKeys: this.apiProxy.config.invalidApiKeys.length,
2097
  authKeys: this.apiProxy.authKeyManager.getAllKeys().length,
2098
  fileLoggingEnabled: this.apiProxy.logManager.getFileLoggingStatus(),
2099
+ version: '2.3.1',
2100
  features: ['text', 'vision', 'stream', 'fake_stream', 'load_balancing', 'auto_retry', 'logging', 'multi_auth', 'file_export']
2101
  });
2102
  });