diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index c1fe02bc..ef9c81f7 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -689,6 +689,11 @@ type NodeTLSProxyConfig struct { // UpstreamHost: 上游目标主机(默认 api.anthropic.com) // 通常不需要修改,除非需要指向不同的 API 端点 UpstreamHost string `mapstructure:"upstream_host"` + // ProxyHosts: 需要走 Node.js 代理的上游主机白名单 + // 只有目标主机在此列表中的 HTTPS 请求才走 Node.js 代理 + // 不在列表中的请求走原有路径(uTLS 或直连) + // 为空时默认只代理 api.anthropic.com + ProxyHosts []string `mapstructure:"proxy_hosts"` } // GatewaySchedulingConfig accounts scheduling configuration. diff --git a/backend/internal/repository/http_upstream.go b/backend/internal/repository/http_upstream.go index e7127788..b5a82352 100644 --- a/backend/internal/repository/http_upstream.go +++ b/backend/internal/repository/http_upstream.go @@ -124,8 +124,8 @@ func NewHTTPUpstream(cfg *config.Config) service.HTTPUpstream { // - 调用方必须关闭 resp.Body,否则会导致 inFlight 计数泄漏 // - inFlight > 0 的客户端不会被淘汰,确保活跃请求不被中断 func (s *httpUpstreamService) Do(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) { - // 优先使用 Node.js TLS 代理模式:拦截所有 HTTPS 上游请求 - if s.isNodeTLSProxyEnabled() && req != nil && req.URL != nil && req.URL.Scheme == "https" { + // Node.js TLS 代理:仅拦截白名单内的上游主机 + if s.isNodeTLSProxyEnabled() && s.shouldRouteViaNodeProxy(req) { return s.doViaNodeTLSProxy(req, accountID, accountConcurrency) } @@ -247,19 +247,28 @@ func (s *httpUpstreamService) isNodeTLSProxyEnabled() bool { } // shouldRouteViaNodeProxy 判断请求是否应该走 Node.js TLS 代理 -// 仅拦截发往配置的上游主机(默认 api.anthropic.com)的 HTTPS 请求, -// 其他请求(如 Gemini、Sora)走原有路径。 +// 仅拦截目标主机在 proxy_hosts 白名单中的 HTTPS 请求, +// 白名单为空时默认只代理 api.anthropic.com。 func (s *httpUpstreamService) shouldRouteViaNodeProxy(req *http.Request) bool { if req == nil || req.URL == nil || req.URL.Scheme != "https" { return false } - upstreamHost := s.cfg.Gateway.NodeTLSProxy.UpstreamHost - if upstreamHost == "" { - upstreamHost = "api.anthropic.com" - } - // 比较请求的目标主机(去掉端口) reqHost := req.URL.Hostname() - return reqHost == upstreamHost + if reqHost == "" { + return false + } + + hosts := s.cfg.Gateway.NodeTLSProxy.ProxyHosts + if len(hosts) == 0 { + // 默认只代理 Anthropic + return reqHost == "api.anthropic.com" + } + for _, h := range hosts { + if reqHost == h { + return true + } + } + return false } // doViaNodeTLSProxy 通过 Node.js TLS 代理发送请求