From c4448db6abde90c7851de11df997431defac501d Mon Sep 17 00:00:00 2001 From: Chapoly1305 Date: Tue, 30 Dec 2025 01:10:43 -0500 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E9=98=B2=E6=AD=A2=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E6=96=AD=E5=BC=80=E8=BF=9E=E6=8E=A5=E6=97=B6=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当客户端在流式响应过程中断开连接时,catch 块尝试发送 JSON 错误响应 会触发 ERR_HTTP_HEADERS_SENT 错误,导致 unhandledRejection 使服务崩溃。 修复文件: - src/routes/openaiClaudeRoutes.js - src/routes/openaiGeminiRoutes.js 修复内容: - 添加 res.headersSent 检查,避免在响应已发送后再次尝试发送 - 客户端断开连接使用 INFO 级别日志(不是 ERROR) - 客户端断开使用 499 状态码 (Client Closed Request) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/routes/openaiClaudeRoutes.js | 29 +++++++++++++++++++++-------- src/routes/openaiGeminiRoutes.js | 32 ++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/routes/openaiClaudeRoutes.js b/src/routes/openaiClaudeRoutes.js index 2bb7cc09..35314e4a 100644 --- a/src/routes/openaiClaudeRoutes.js +++ b/src/routes/openaiClaudeRoutes.js @@ -402,16 +402,29 @@ async function handleChatCompletion(req, res, apiKeyData) { const duration = Date.now() - startTime logger.info(`✅ OpenAI-Claude request completed in ${duration}ms`) } catch (error) { - logger.error('❌ OpenAI-Claude request error:', error) + // 客户端主动断开连接是正常情况,使用 INFO 级别 + if (error.message === 'Client disconnected') { + logger.info('🔌 OpenAI-Claude stream ended: Client disconnected') + } else { + logger.error('❌ OpenAI-Claude request error:', error) + } - const status = error.status || 500 - res.status(status).json({ - error: { - message: error.message || 'Internal server error', - type: 'server_error', - code: 'internal_error' + // 检查响应是否已发送(流式响应场景),避免 ERR_HTTP_HEADERS_SENT + if (!res.headersSent) { + // 客户端断开使用 499 状态码 (Client Closed Request) + if (error.message === 'Client disconnected') { + res.status(499).end() + } else { + const status = error.status || 500 + res.status(status).json({ + error: { + message: error.message || 'Internal server error', + type: 'server_error', + code: 'internal_error' + } + }) } - }) + } } finally { // 清理资源 if (abortController) { diff --git a/src/routes/openaiGeminiRoutes.js b/src/routes/openaiGeminiRoutes.js index fd74ad86..ef65acc1 100644 --- a/src/routes/openaiGeminiRoutes.js +++ b/src/routes/openaiGeminiRoutes.js @@ -604,7 +604,12 @@ router.post('/v1/chat/completions', authenticateApiKey, async (req, res) => { const duration = Date.now() - startTime logger.info(`OpenAI-Gemini request completed in ${duration}ms`) } catch (error) { - logger.error('OpenAI-Gemini request error:', error) + // 客户端主动断开连接是正常情况,使用 INFO 级别 + if (error.message === 'Client disconnected') { + logger.info('🔌 OpenAI-Gemini stream ended: Client disconnected') + } else { + logger.error('OpenAI-Gemini request error:', error) + } // 处理速率限制 if (error.status === 429) { @@ -613,17 +618,24 @@ router.post('/v1/chat/completions', authenticateApiKey, async (req, res) => { } } - // 返回 OpenAI 格式的错误响应 - const status = error.status || 500 - const errorResponse = { - error: error.error || { - message: error.message || 'Internal server error', - type: 'server_error', - code: 'internal_error' + // 检查响应是否已发送(流式响应场景),避免 ERR_HTTP_HEADERS_SENT + if (!res.headersSent) { + // 客户端断开使用 499 状态码 (Client Closed Request) + if (error.message === 'Client disconnected') { + res.status(499).end() + } else { + // 返回 OpenAI 格式的错误响应 + const status = error.status || 500 + const errorResponse = { + error: error.error || { + message: error.message || 'Internal server error', + type: 'server_error', + code: 'internal_error' + } + } + res.status(status).json(errorResponse) } } - - res.status(status).json(errorResponse) } finally { // 清理资源 if (abortController) { From 0a59a0f9d4e407cd5e093715179dbbe56a391021 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 1 Jan 2026 05:57:53 +0000 Subject: [PATCH 2/2] chore: sync VERSION file with release v1.1.251 [skip ci] --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7b7bb57d..548ae3b2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.250 +1.1.251