sub2api/backend/internal/repository/http_upstream_antigravity.go
win 21325afb33
Some checks failed
CI / test (push) Failing after 10s
CI / frontend (push) Failing after 8s
CI / golangci-lint (push) Failing after 5s
Security Scan / backend-security (push) Failing after 5s
Security Scan / frontend-security (push) Failing after 4s
feat(windsurf): 补全ops日志记录与endpoint派生,对齐其他平台
- windsurf_gateway_service: 添加上游延迟/TTFT/错误上下文记录
- endpoint: DeriveUpstreamEndpoint 添加 PlatformWindsurf 分支
- ops_error_logger: guessPlatformFromPath 添加 /windsurf/ 识别
2026-04-23 20:46:27 +08:00

92 lines
3.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
// ==============================================================
// antigravity — Go 原生 TLS 指纹扩展
//
// 此文件包含 Antigravity fork 新增的 TLS 指纹代理功能,
// 与 upstream 代码完全隔离,便于 upstream 更新时的合并维护。
//
// 上游文件 http_upstream.go 中的钩子调用点:
// Do() — 匹配主机时路由到 doWithTLSFingerprint
// DoWithTLS() — profile==nil 时回退到 Do(),触发同样的路由
//
// 替代原先的 Node.js TLS 代理node-tls-proxy
// 直接使用 Go utls 库模拟 Claude CLI 的 TLS 指纹。
// ==============================================================
import (
"log/slog"
"net/http"
"github.com/Wei-Shaw/sub2api/internal/pkg/tlsfingerprint"
"github.com/Wei-Shaw/sub2api/internal/util/logredact"
)
// isTLSFingerprintRoutingEnabled 检查 TLS 指纹路由是否启用
// 使用 TLSFingerprint.Enabled 配置项(而不是旧的 NodeTLSProxy.Enabled
func (s *httpUpstreamService) isTLSFingerprintRoutingEnabled() bool {
if s.cfg == nil {
return false
}
return s.cfg.Gateway.TLSFingerprint.Enabled
}
// shouldRouteWithTLSFingerprint 判断请求是否应该使用 TLS 指纹
// 拦截目标主机在 proxy_hosts 白名单中的 HTTPS 请求
// 白名单为空时默认代理 api.anthropic.com 和 Antigravity API 主机
func (s *httpUpstreamService) shouldRouteWithTLSFingerprint(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 {
// 默认白名单api.anthropic.com 和 Antigravity API 主机
defaultHosts := map[string]bool{
"api.anthropic.com": true,
"cloudcode-pa.googleapis.com": true,
"daily-cloudcode-pa.googleapis.com": true,
}
return defaultHosts[reqHost]
}
for _, h := range hosts {
if reqHost == h {
return true
}
}
return false
}
// defaultTLSProfile 返回模拟 Claude CLI (Node.js 24.x) 的默认 TLS 指纹配置
// 所有 slice 字段留空 → dialer.go 自动使用内置的 Node.js 24.x 默认值
// ALPN 仅声明 http/1.1,与真实 CLI 行为一致undici allowH2=false
func defaultTLSProfile() *tlsfingerprint.Profile {
return &tlsfingerprint.Profile{
Name: "claude_cli_builtin",
EnableGREASE: true,
}
}
// doWithTLSFingerprint 使用 Go 原生 utls TLS 指纹发送请求
// 直接通过 DoWithTLS 路径,利用已有的 utls dialer 基础设施:
// - 直连Dialer (TCP → utls handshake)
// - HTTP 代理HTTPProxyDialer (CONNECT 隧道 → utls handshake)
// - SOCKS5 代理SOCKS5ProxyDialer (SOCKS5 隧道 → utls handshake)
func (s *httpUpstreamService) doWithTLSFingerprint(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) {
proxyInfo := "direct"
if proxyURL != "" {
proxyInfo = logredact.RedactProxyURL(proxyURL)
}
slog.Debug("tls_fingerprint_routing",
"account_id", accountID,
"target", req.URL.Host,
"proxy", proxyInfo,
)
return s.DoWithTLS(req, proxyURL, accountID, accountConcurrency, defaultTLSProfile())
}