From 2b0192e7040c4263852e6401d509af2576cc3f6e Mon Sep 17 00:00:00 2001 From: win Date: Sun, 22 Mar 2026 11:39:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9E=B6=E6=9E=84=E5=AE=A1=E6=9F=A5?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=203=20=E4=B8=AA=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. instanceSalt 空值兼容:salt 为空时保持原始 hash 格式不变 避免升级后所有 user_id hash 突变触发 Anthropic 检测 2. doViaNodeTLSProxy 克隆请求:不修改原始 req 对象 修复重试时 URL 已被改写导致请求失败 3. Sora doSoraBackendJSON 漏改:补上 sidecar 路由 --- backend/internal/repository/http_upstream.go | 19 +++++++++---------- backend/internal/service/identity_service.go | 7 ++++++- backend/internal/service/sora_sdk_client.go | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/backend/internal/repository/http_upstream.go b/backend/internal/repository/http_upstream.go index d72d4006..8d73dc9c 100644 --- a/backend/internal/repository/http_upstream.go +++ b/backend/internal/repository/http_upstream.go @@ -284,27 +284,26 @@ func (s *httpUpstreamService) doViaNodeTLSProxy(req *http.Request, proxyURL stri listenPort = 3456 } + // 克隆请求,避免修改原始 req(重试时需要原始 URL) + proxyReq := req.Clone(req.Context()) + proxyReq.Body = req.Body // Clone 不复制 Body + // 保存原始目标主机,通过自定义头传给 Node.js 代理 originalHost := req.URL.Host - req.Header.Set("X-Forwarded-Host", originalHost) + proxyReq.Header.Set("X-Forwarded-Host", originalHost) // 重写请求 URL:https://api.anthropic.com/v1/... → http://127.0.0.1:3456/v1/... - originalURL := req.URL.String() - req.URL.Scheme = "http" - req.URL.Host = fmt.Sprintf("%s:%d", listenHost, listenPort) + proxyReq.URL.Scheme = "http" + proxyReq.URL.Host = fmt.Sprintf("%s:%d", listenHost, listenPort) slog.Debug("node_tls_proxy_rewrite", "account_id", accountID, - "original_url", originalURL, "original_host", originalHost, - "rewritten_to", req.URL.String(), + "rewritten_to", proxyReq.URL.Host, ) - // 递归保护:标记已经过代理重写,避免 Do() 再次进入本方法 - req.URL.Scheme = "http" // Do() 只拦截 scheme=="https",http 会走正常路径 - // 通过标准 HTTP 客户端发送(不需要 TLS,代理是本地 HTTP) - return s.Do(req, "", accountID, accountConcurrency) + return s.Do(proxyReq, "", accountID, accountConcurrency) } // acquireClientWithTLS 获取或创建带 TLS 指纹的客户端 diff --git a/backend/internal/service/identity_service.go b/backend/internal/service/identity_service.go index 7fc7beb3..db4935f9 100644 --- a/backend/internal/service/identity_service.go +++ b/backend/internal/service/identity_service.go @@ -268,7 +268,12 @@ func (s *IdentityService) RewriteUserID(body []byte, accountID int64, accountUUI // 生成新的session hash: SHA256(salt::accountID::sessionTail) -> UUID格式 // instanceSalt 使不同 sub2api 实例对相同输入产生不同的 hash - seed := fmt.Sprintf("%s::%d::%s", s.instanceSalt, accountID, sessionTail) + var seed string + if s.instanceSalt != "" { + seed = fmt.Sprintf("%s::%d::%s", s.instanceSalt, accountID, sessionTail) + } else { + seed = fmt.Sprintf("%d::%s", accountID, sessionTail) + } newSessionHash := generateUUIDFromSeed(seed) // 根据客户端版本选择输出格式 diff --git a/backend/internal/service/sora_sdk_client.go b/backend/internal/service/sora_sdk_client.go index a8812ff5..f59c257d 100644 --- a/backend/internal/service/sora_sdk_client.go +++ b/backend/internal/service/sora_sdk_client.go @@ -723,7 +723,7 @@ func (c *SoraSDKClient) doSoraBackendJSON( var resp *http.Response if c.httpUpstream != nil { - resp, err = c.httpUpstream.Do(req, proxyURL, accountID, accountConcurrency) + resp, err = c.doSoraHTTP(req, proxyURL, accountID, accountConcurrency) } else { resp, err = http.DefaultClient.Do(req) }