From c5e63feaa38ffcc07404e1edb9c8a3b572c26d3c Mon Sep 17 00:00:00 2001 From: D8D Developer Date: Fri, 20 Mar 2026 15:21:48 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Claude=20=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E5=AF=B9=E6=99=BA=E8=B0=B1=20AI=20=E7=9A=84=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 x-api-key 头自动转换为 Authorization: Bearer 格式 - 检测上游是否为智谱 AI,自动适配认证方式 - 保持标准 Claude API 认证头的直接透传 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- src/proxy.ts | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index 955ca45..32b731c 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -16,15 +16,42 @@ function getBaseUrl(): string { return process.env.ANTHROPIC_BASE_URL || 'https://api.anthropic.com'; } -// 提取需要透传的 headers +// 提取需要透传的 headers,并处理认证头转换 function extractProxyHeaders(req: Request): Record { const headers: Record = {}; - for (const header of PROXY_HEADERS) { - const value = req.headers[header]; - if (value) { - headers[header] = Array.isArray(value) ? value[0] : value; + const baseUrl = getBaseUrl(); + + // 如果上游是智谱 AI 等,需要将 x-api-key 转换为 Authorization: Bearer + if (baseUrl.includes('bigmodel.cn') || baseUrl.includes('open.bigmodel')) { + // 优先使用 x-api-key,其次使用 Authorization + const rawHeaders = req.headers as Record; + const xApiKey = rawHeaders['x-api-key']; + const authHeader = rawHeaders['authorization']; + + const apiKey = (Array.isArray(xApiKey) ? xApiKey[0] : xApiKey) || + (Array.isArray(authHeader) ? authHeader[0] : authHeader)?.replace?.(/^Bearer\s+/i, ''); + + if (apiKey) { + headers['authorization'] = `Bearer ${apiKey}`; + } + // 复制其他 headers + for (const header of PROXY_HEADERS) { + if (header === 'x-api-key' || header === 'authorization') continue; + const value = req.headers[header]; + if (value) { + headers[header] = Array.isArray(value) ? value[0] : value; + } + } + } else { + // 标准 Claude API,直接透传 + for (const header of PROXY_HEADERS) { + const value = req.headers[header]; + if (value) { + headers[header] = Array.isArray(value) ? value[0] : value; + } } } + return headers; }