fix: Node.js TLS 代理按主机白名单过滤,Gemini 走原路径
- 新增 proxy_hosts 配置:白名单内的主机走 Node.js 代理 - 默认仅代理 api.anthropic.com - Gemini/Sora 等非 Anthropic 请求自动走原有 uTLS 路径 - 解决 Gemini 请求经 Node.js 代理后 socket hang up 的问题
This commit is contained in:
parent
5c587c1095
commit
c6a282c2e7
@ -689,6 +689,11 @@ type NodeTLSProxyConfig struct {
|
|||||||
// UpstreamHost: 上游目标主机(默认 api.anthropic.com)
|
// UpstreamHost: 上游目标主机(默认 api.anthropic.com)
|
||||||
// 通常不需要修改,除非需要指向不同的 API 端点
|
// 通常不需要修改,除非需要指向不同的 API 端点
|
||||||
UpstreamHost string `mapstructure:"upstream_host"`
|
UpstreamHost string `mapstructure:"upstream_host"`
|
||||||
|
// ProxyHosts: 需要走 Node.js 代理的上游主机白名单
|
||||||
|
// 只有目标主机在此列表中的 HTTPS 请求才走 Node.js 代理
|
||||||
|
// 不在列表中的请求走原有路径(uTLS 或直连)
|
||||||
|
// 为空时默认只代理 api.anthropic.com
|
||||||
|
ProxyHosts []string `mapstructure:"proxy_hosts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GatewaySchedulingConfig accounts scheduling configuration.
|
// GatewaySchedulingConfig accounts scheduling configuration.
|
||||||
|
|||||||
@ -124,8 +124,8 @@ func NewHTTPUpstream(cfg *config.Config) service.HTTPUpstream {
|
|||||||
// - 调用方必须关闭 resp.Body,否则会导致 inFlight 计数泄漏
|
// - 调用方必须关闭 resp.Body,否则会导致 inFlight 计数泄漏
|
||||||
// - inFlight > 0 的客户端不会被淘汰,确保活跃请求不被中断
|
// - inFlight > 0 的客户端不会被淘汰,确保活跃请求不被中断
|
||||||
func (s *httpUpstreamService) Do(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) {
|
func (s *httpUpstreamService) Do(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) {
|
||||||
// 优先使用 Node.js TLS 代理模式:拦截所有 HTTPS 上游请求
|
// Node.js TLS 代理:仅拦截白名单内的上游主机
|
||||||
if s.isNodeTLSProxyEnabled() && req != nil && req.URL != nil && req.URL.Scheme == "https" {
|
if s.isNodeTLSProxyEnabled() && s.shouldRouteViaNodeProxy(req) {
|
||||||
return s.doViaNodeTLSProxy(req, accountID, accountConcurrency)
|
return s.doViaNodeTLSProxy(req, accountID, accountConcurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,19 +247,28 @@ func (s *httpUpstreamService) isNodeTLSProxyEnabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shouldRouteViaNodeProxy 判断请求是否应该走 Node.js TLS 代理
|
// shouldRouteViaNodeProxy 判断请求是否应该走 Node.js TLS 代理
|
||||||
// 仅拦截发往配置的上游主机(默认 api.anthropic.com)的 HTTPS 请求,
|
// 仅拦截目标主机在 proxy_hosts 白名单中的 HTTPS 请求,
|
||||||
// 其他请求(如 Gemini、Sora)走原有路径。
|
// 白名单为空时默认只代理 api.anthropic.com。
|
||||||
func (s *httpUpstreamService) shouldRouteViaNodeProxy(req *http.Request) bool {
|
func (s *httpUpstreamService) shouldRouteViaNodeProxy(req *http.Request) bool {
|
||||||
if req == nil || req.URL == nil || req.URL.Scheme != "https" {
|
if req == nil || req.URL == nil || req.URL.Scheme != "https" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
upstreamHost := s.cfg.Gateway.NodeTLSProxy.UpstreamHost
|
|
||||||
if upstreamHost == "" {
|
|
||||||
upstreamHost = "api.anthropic.com"
|
|
||||||
}
|
|
||||||
// 比较请求的目标主机(去掉端口)
|
|
||||||
reqHost := req.URL.Hostname()
|
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 代理发送请求
|
// doViaNodeTLSProxy 通过 Node.js TLS 代理发送请求
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user