package repository // ============================================================== // antigravity — Node.js TLS 代理扩展 // // 此文件包含 Antigravity fork 新增的 Node.js TLS 代理功能, // 与 upstream 代码完全隔离,便于 upstream 更新时的合并维护。 // // 上游文件 http_upstream.go 中的钩子调用点: // Do() L128-137 — 直接路由到 doViaNodeTLSProxy // DoWithTLS() L188-193 — 优先走 Node.js 代理 // ============================================================== import ( "fmt" "log/slog" "net/http" ) // isNodeTLSProxyEnabled 检查 Node.js TLS 代理是否启用 func (s *httpUpstreamService) isNodeTLSProxyEnabled() bool { if s.cfg == nil { return false } return s.cfg.Gateway.NodeTLSProxy.Enabled } // shouldRouteViaNodeProxy 判断请求是否应该走 Node.js TLS 代理 // 仅拦截目标主机在 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 } reqHost := req.URL.Hostname() 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 代理发送请求 // 将 HTTPS 请求改为 HTTP 明文发送到本地 Node.js 代理, // 由 Node.js 进程使用原生 TLS 栈完成到上游的 HTTPS 连接。 // 原始目标主机通过 X-Forwarded-Host 传递给 Node.js 代理, // 代理据此动态连接到正确的上游主机。 func (s *httpUpstreamService) doViaNodeTLSProxy(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) { proxyCfg := s.cfg.Gateway.NodeTLSProxy listenHost := proxyCfg.ListenHost if listenHost == "" { listenHost = "127.0.0.1" } listenPort := proxyCfg.ListenPort if listenPort == 0 { listenPort = 3456 } // 克隆请求,避免修改原始 req(重试时需要原始 URL) proxyReq := req.Clone(req.Context()) // 安全复制 Body:优先用 GetBody 工厂方法 if req.GetBody != nil { proxyReq.Body, _ = req.GetBody() } else { proxyReq.Body = req.Body } // 保存原始目标主机,通过自定义头传给 Node.js 代理 originalHost := req.URL.Host proxyReq.Header.Set("X-Forwarded-Host", originalHost) // 如果账号绑定了代理(落地机 GOST),通过 header 传递给 node-tls-proxy // node-tls-proxy 会用此代理作为上游出口,实现动态路由 if proxyURL != "" { proxyReq.Header.Set("X-Upstream-Proxy", proxyURL) } // 重写请求 URL:https://api.anthropic.com/v1/... → http://127.0.0.1:3456/v1/... proxyReq.URL.Scheme = "http" proxyReq.URL.Host = fmt.Sprintf("%s:%d", listenHost, listenPort) slog.Debug("node_tls_proxy_rewrite", "account_id", accountID, "original_host", originalHost, "rewritten_to", proxyReq.URL.Host, ) // 通过标准 HTTP 客户端发送(不需要 TLS,代理是本地 HTTP) return s.Do(proxyReq, "", accountID, accountConcurrency) }