feat: Add automated ChatGPT account registration with backend API, TLS client, and fingerprinting, alongside new frontend pages for configuration, monitoring, and upload.

This commit is contained in:
2026-02-03 02:39:08 +08:00
parent 389b8eca28
commit 51ba54856d
18 changed files with 1382 additions and 674 deletions

View File

@@ -7,101 +7,150 @@ import (
)
// ============================================================
// 浏览器指纹配置文件
// 整合 tls-client 高成功率指纹
// 指纹配置文件 - Super Max Plus Ultra 版
// 整合 tls-client, spoofed-round-tripper, azuretls, surf 高成功率指纹
// ============================================================
// FingerprintType 指纹类型
type FingerprintType int
const (
FingerprintTLSClient FingerprintType = iota // bogdanfinn/tls-client
FingerprintSpoofedRT // juzeon/spoofed-round-tripper
FingerprintAzureTLS // Noooste/azuretls-client
)
// BrowserFingerprint 浏览器指纹完整配置
type BrowserFingerprint struct {
Browser string
Version string
Platform string
Mobile bool
TLSProfile profiles.ClientProfile
Browser string
Version string
Platform string
Mobile bool
Type FingerprintType
TLSProfile profiles.ClientProfile // tls-client / spoofed-round-tripper
AzureBrowser string // azuretls-client browser type
}
// ============================================================
// Firefox 指纹池 (100% 成功率)
// Firefox 指纹池 (100% 成功率) - tls-client
// ============================================================
var firefoxFingerprints = []BrowserFingerprint{
// 最新版本
{Browser: "firefox", Version: "135", Platform: "Windows", TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "135", Platform: "macOS", TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "135", Platform: "Linux", TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "133", Platform: "Windows", TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "133", Platform: "macOS", TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "133", Platform: "Linux", TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "132", Platform: "Windows", TLSProfile: profiles.Firefox_132},
{Browser: "firefox", Version: "132", Platform: "macOS", TLSProfile: profiles.Firefox_132},
{Browser: "firefox", Version: "123", Platform: "Windows", TLSProfile: profiles.Firefox_123},
{Browser: "firefox", Version: "120", Platform: "Windows", TLSProfile: profiles.Firefox_120},
{Browser: "firefox", Version: "120", Platform: "macOS", TLSProfile: profiles.Firefox_120},
{Browser: "firefox", Version: "117", Platform: "Windows", TLSProfile: profiles.Firefox_117},
{Browser: "firefox", Version: "110", Platform: "Windows", TLSProfile: profiles.Firefox_110},
{Browser: "firefox", Version: "108", Platform: "Windows", TLSProfile: profiles.Firefox_108},
{Browser: "firefox", Version: "106", Platform: "Windows", TLSProfile: profiles.Firefox_106},
{Browser: "firefox", Version: "105", Platform: "Windows", TLSProfile: profiles.Firefox_105},
{Browser: "firefox", Version: "104", Platform: "Windows", TLSProfile: profiles.Firefox_104},
{Browser: "firefox", Version: "102", Platform: "Windows", TLSProfile: profiles.Firefox_102},
{Browser: "firefox", Version: "135", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "135", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "135", Platform: "Linux", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_135},
{Browser: "firefox", Version: "133", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "133", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "133", Platform: "Linux", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_133},
{Browser: "firefox", Version: "132", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_132},
{Browser: "firefox", Version: "132", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_132},
{Browser: "firefox", Version: "123", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_123},
{Browser: "firefox", Version: "120", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_120},
{Browser: "firefox", Version: "120", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_120},
{Browser: "firefox", Version: "117", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_117},
{Browser: "firefox", Version: "110", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_110},
{Browser: "firefox", Version: "108", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_108},
{Browser: "firefox", Version: "106", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_106},
{Browser: "firefox", Version: "105", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_105},
{Browser: "firefox", Version: "104", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_104},
{Browser: "firefox", Version: "102", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Firefox_102},
}
// ============================================================
// Safari 指纹池 (100% 成功率)
// Safari 指纹池 (100% 成功率) - tls-client
// ============================================================
var safariFingerprints = []BrowserFingerprint{
// macOS Safari
{Browser: "safari", Version: "16.0", Platform: "macOS", TLSProfile: profiles.Safari_16_0},
{Browser: "safari", Version: "15.6.1", Platform: "macOS", TLSProfile: profiles.Safari_15_6_1},
{Browser: "safari", Version: "16.0", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Safari_16_0},
{Browser: "safari", Version: "15.6.1", Platform: "macOS", Type: FingerprintTLSClient, TLSProfile: profiles.Safari_15_6_1},
// iOS Safari
{Browser: "safari", Version: "18.5", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_18_5},
{Browser: "safari", Version: "18.0", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_18_0},
{Browser: "safari", Version: "17.0", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_17_0},
{Browser: "safari", Version: "16.0", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_16_0},
{Browser: "safari", Version: "15.6", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_15_6},
{Browser: "safari", Version: "15.5", Platform: "iOS", Mobile: true, TLSProfile: profiles.Safari_IOS_15_5},
{Browser: "safari", Version: "18.5", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_18_5},
{Browser: "safari", Version: "18.0", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_18_0},
{Browser: "safari", Version: "17.0", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_17_0},
{Browser: "safari", Version: "16.0", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_16_0},
{Browser: "safari", Version: "15.6", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_15_6},
{Browser: "safari", Version: "15.5", Platform: "iOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_IOS_15_5},
// iPadOS Safari
{Browser: "safari", Version: "15.6", Platform: "iPadOS", Mobile: true, TLSProfile: profiles.Safari_Ipad_15_6},
{Browser: "safari", Version: "15.6", Platform: "iPadOS", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Safari_Ipad_15_6},
}
// ============================================================
// Opera 指纹池 (高成功率)
// Opera 指纹池 (高成功率) - tls-client
// ============================================================
var operaFingerprints = []BrowserFingerprint{
{Browser: "opera", Version: "91", Platform: "Windows", TLSProfile: profiles.Opera_91},
{Browser: "opera", Version: "90", Platform: "Windows", TLSProfile: profiles.Opera_90},
{Browser: "opera", Version: "89", Platform: "Windows", TLSProfile: profiles.Opera_89},
{Browser: "opera", Version: "91", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Opera_91},
{Browser: "opera", Version: "90", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Opera_90},
{Browser: "opera", Version: "89", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Opera_89},
}
// ============================================================
// OkHttp 指纹池 (100% 成功率 - Android 原生)
// OkHttp 指纹池 (100% 成功率 - Android 原生) - tls-client
// ============================================================
var okhttpFingerprints = []BrowserFingerprint{
{Browser: "okhttp", Version: "13", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android13},
{Browser: "okhttp", Version: "12", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android12},
{Browser: "okhttp", Version: "11", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android11},
{Browser: "okhttp", Version: "10", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android10},
{Browser: "okhttp", Version: "9", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android9},
{Browser: "okhttp", Version: "8", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android8},
{Browser: "okhttp", Version: "7", Platform: "Android", Mobile: true, TLSProfile: profiles.Okhttp4Android7},
{Browser: "okhttp", Version: "13", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android13},
{Browser: "okhttp", Version: "12", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android12},
{Browser: "okhttp", Version: "11", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android11},
{Browser: "okhttp", Version: "10", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android10},
{Browser: "okhttp", Version: "9", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android9},
{Browser: "okhttp", Version: "8", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android8},
{Browser: "okhttp", Version: "7", Platform: "Android", Mobile: true, Type: FingerprintTLSClient, TLSProfile: profiles.Okhttp4Android7},
}
// ============================================================
// Chrome 指纹池 (测试通过的版本)
// Chrome 指纹池 (测试通过的版本) - tls-client
// 注意: 新版 Chrome (120+) 在 tls-client 中被检测,只保留旧版本
// ============================================================
var chromeFingerprints = []BrowserFingerprint{
// 只保留测试通过的旧版本
{Browser: "chrome", Version: "112", Platform: "Windows", TLSProfile: profiles.Chrome_112},
{Browser: "chrome", Version: "111", Platform: "Windows", TLSProfile: profiles.Chrome_111},
{Browser: "chrome", Version: "112", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Chrome_112},
{Browser: "chrome", Version: "111", Platform: "Windows", Type: FingerprintTLSClient, TLSProfile: profiles.Chrome_111},
}
// ============================================================
// 合并所有指纹
// juzeon/spoofed-round-tripper 指纹
// ============================================================
var spoofedRTFingerprints = []BrowserFingerprint{
{Browser: "firefox", Version: "135", Platform: "Windows", Type: FingerprintSpoofedRT, TLSProfile: profiles.Firefox_135},
{Browser: "safari", Version: "16.0", Platform: "macOS", Type: FingerprintSpoofedRT, TLSProfile: profiles.Safari_16_0},
}
// ============================================================
// Noooste/azuretls-client 指纹池 (HTTP/2 + HTTP/3 支持)
// 支持最新浏览器版本,自动更新指纹
// ============================================================
var azureTLSFingerprints = []BrowserFingerprint{
// Chrome - 最新版本 (自动获取)
{Browser: "chrome", Version: "latest", Platform: "Windows", Type: FingerprintAzureTLS, AzureBrowser: "chrome"},
{Browser: "chrome", Version: "latest", Platform: "macOS", Type: FingerprintAzureTLS, AzureBrowser: "chrome"},
{Browser: "chrome", Version: "latest", Platform: "Linux", Type: FingerprintAzureTLS, AzureBrowser: "chrome"},
// Firefox - 最新版本
{Browser: "firefox", Version: "latest", Platform: "Windows", Type: FingerprintAzureTLS, AzureBrowser: "firefox"},
{Browser: "firefox", Version: "latest", Platform: "macOS", Type: FingerprintAzureTLS, AzureBrowser: "firefox"},
{Browser: "firefox", Version: "latest", Platform: "Linux", Type: FingerprintAzureTLS, AzureBrowser: "firefox"},
// Safari - 最新版本
{Browser: "safari", Version: "latest", Platform: "macOS", Type: FingerprintAzureTLS, AzureBrowser: "safari"},
// Edge - 最新版本
{Browser: "edge", Version: "latest", Platform: "Windows", Type: FingerprintAzureTLS, AzureBrowser: "edge"},
// iOS Safari
{Browser: "safari", Version: "latest", Platform: "iOS", Mobile: true, Type: FingerprintAzureTLS, AzureBrowser: "ios"},
// Opera
{Browser: "opera", Version: "latest", Platform: "Windows", Type: FingerprintAzureTLS, AzureBrowser: "opera"},
}
// ============================================================
// 合并所有指纹 - 均衡权重分配
// ============================================================
var allFingerprints []BrowserFingerprint
@@ -109,21 +158,34 @@ var allFingerprints []BrowserFingerprint
func init() {
allFingerprints = make([]BrowserFingerprint, 0, 100)
// Firefox (高优先级,多份)
allFingerprints = append(allFingerprints, firefoxFingerprints...)
// ============================================================
// 权重策略: tls-client ~50%, azuretls ~30%, spoofed-rt ~20%
// ============================================================
// tls-client Firefox
allFingerprints = append(allFingerprints, firefoxFingerprints...)
// Safari (高成功率)
// tls-client Safari
allFingerprints = append(allFingerprints, safariFingerprints...)
// Opera
// tls-client Opera
allFingerprints = append(allFingerprints, operaFingerprints...)
// OkHttp (Android)
// tls-client OkHttp (Android)
allFingerprints = append(allFingerprints, okhttpFingerprints...)
// Chrome (低优先级)
// tls-client Chrome
allFingerprints = append(allFingerprints, chromeFingerprints...)
// spoofed-round-tripper (权重加倍)
allFingerprints = append(allFingerprints, spoofedRTFingerprints...)
allFingerprints = append(allFingerprints, spoofedRTFingerprints...)
allFingerprints = append(allFingerprints, spoofedRTFingerprints...)
// azuretls-client (权重加倍,最新浏览器指纹)
allFingerprints = append(allFingerprints, azureTLSFingerprints...)
allFingerprints = append(allFingerprints, azureTLSFingerprints...)
allFingerprints = append(allFingerprints, azureTLSFingerprints...)
}
// GetRandomFingerprint 获取随机指纹

View File

@@ -8,21 +8,36 @@ import (
"math/rand"
"net/http"
"net/url"
"strings"
"time"
"codex-pool/internal/proxyutil"
"github.com/Noooste/azuretls-client"
"github.com/andybalholm/brotli"
http2 "github.com/bogdanfinn/fhttp"
tls_client "github.com/bogdanfinn/tls-client"
)
// TLSClient 使用 tls-client 模拟浏览器指纹的 HTTP 客户端
// ClientType 客户端类型
type ClientType int
const (
ClientTypeTLS ClientType = iota // bogdanfinn/tls-client
ClientTypeAzureTLS // Noooste/azuretls-client
)
// TLSClient 统一的 HTTP 客户端接口,支持多种 TLS 指纹和浏览器模拟
type TLSClient struct {
client tls_client.HttpClient
// 内部客户端
tlsClient tls_client.HttpClient
azureSession *azuretls.Session
clientType ClientType
// 指纹信息
fingerprint BrowserFingerprint
userAgent string
acceptLang string
proxy string
}
// 语言偏好池
@@ -37,7 +52,7 @@ var languagePrefs = []string{
"es-ES,es;q=0.9,en-US;q=0.8,en;q=0.7",
}
// New 创建一个新的 TLS 客户端使用随机指纹
// New 创建一个新的 TLS 客户端 (使用随机指纹)
func New(proxyStr string) (*TLSClient, error) {
// 获取随机桌面端指纹
fp := GetRandomDesktopFingerprint()
@@ -45,7 +60,36 @@ func New(proxyStr string) (*TLSClient, error) {
}
// NewWithFingerprint 使用指定指纹创建客户端
func NewWithFingerprint(fp BrowserFingerprint, proxyStr string) (*TLSClient, error) {
func NewWithFingerprint(fp BrowserFingerprint, proxyStr string) (client *TLSClient, err error) {
// 添加 panic 恢复
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("创建客户端时发生 panic: %v", r)
client = nil
}
}()
acceptLang := languagePrefs[rand.Intn(len(languagePrefs))]
userAgent := generateUserAgent(fp)
client = &TLSClient{
fingerprint: fp,
userAgent: userAgent,
acceptLang: acceptLang,
proxy: proxyStr,
}
// 根据指纹类型创建对应的客户端
switch fp.Type {
case FingerprintAzureTLS:
return createAzureTLSClient(client, fp, proxyStr)
default:
return createTLSClient(client, fp, proxyStr)
}
}
// createTLSClient 创建 tls-client 客户端
func createTLSClient(c *TLSClient, fp BrowserFingerprint, proxyStr string) (*TLSClient, error) {
jar := tls_client.NewCookieJar()
options := []tls_client.HttpClientOption{
@@ -54,6 +98,7 @@ func NewWithFingerprint(fp BrowserFingerprint, proxyStr string) (*TLSClient, err
tls_client.WithRandomTLSExtensionOrder(),
tls_client.WithCookieJar(jar),
tls_client.WithInsecureSkipVerify(),
tls_client.WithNotFollowRedirects(),
}
if proxyStr != "" {
@@ -64,20 +109,45 @@ func NewWithFingerprint(fp BrowserFingerprint, proxyStr string) (*TLSClient, err
options = append(options, tls_client.WithProxyUrl(normalized))
}
client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
tlsClient, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
if err != nil {
return nil, err
}
acceptLang := languagePrefs[rand.Intn(len(languagePrefs))]
userAgent := generateUserAgent(fp)
c.tlsClient = tlsClient
c.clientType = ClientTypeTLS
return c, nil
}
return &TLSClient{
client: client,
fingerprint: fp,
userAgent: userAgent,
acceptLang: acceptLang,
}, nil
// createAzureTLSClient 创建 azuretls-client 客户端
func createAzureTLSClient(c *TLSClient, fp BrowserFingerprint, proxyStr string) (*TLSClient, error) {
session := azuretls.NewSession()
browser := fp.AzureBrowser
if browser == "" {
browser = azuretls.Chrome
}
session.Browser = browser
session.GetClientHelloSpec = azuretls.GetBrowserClientHelloFunc(browser)
session.SetTimeout(90 * time.Second)
if proxyStr != "" {
normalized, err := proxyutil.Normalize(proxyStr)
if err != nil {
return nil, err
}
if err := session.SetProxy(normalized); err != nil {
return nil, fmt.Errorf("azuretls set proxy failed: %w", err)
}
}
session.MaxRedirects = 0
session.InsecureSkipVerify = true
c.azureSession = session
c.clientType = ClientTypeAzureTLS
return c, nil
}
// generateUserAgent 根据指纹生成 User-Agent
@@ -87,6 +157,22 @@ func generateUserAgent(fp BrowserFingerprint) string {
linuxVersions := []string{"X11; Linux x86_64", "X11; Ubuntu; Linux x86_64", "X11; Fedora; Linux x86_64"}
version := fp.Version
if version == "latest" {
switch fp.Browser {
case "chrome":
version = "133"
case "firefox":
version = "135"
case "safari":
version = "18.3"
case "edge":
version = "133"
case "opera":
version = "117"
default:
version = "133"
}
}
switch fp.Browser {
case "chrome":
@@ -144,11 +230,10 @@ func generateUserAgent(fp BrowserFingerprint) string {
return "okhttp/4.12.0"
}
// 默认 Chrome
return fmt.Sprintf("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0.0.0 Safari/537.36", version)
}
// getDefaultHeaders 获取默认请求头(根据浏览器类型返回不同的头)
// getDefaultHeaders 获取默认请求头
func (c *TLSClient) getDefaultHeaders() map[string]string {
headers := map[string]string{
"User-Agent": c.userAgent,
@@ -222,14 +307,18 @@ func (c *TLSClient) getPlatformHeader() string {
}
}
// GetFingerprintInfo 获取指纹信息字符串(用于日志输出)
func (c *TLSClient) GetFingerprintInfo() string {
fp := c.fingerprint
return fmt.Sprintf("%s/%s (%s)", fp.Browser, fp.Version, fp.Platform)
}
// Do 执行 HTTP 请求
func (c *TLSClient) Do(req *http.Request) (*http.Response, error) {
switch c.clientType {
case ClientTypeAzureTLS:
return c.doAzureTLS(req)
default:
return c.doTLS(req)
}
}
// doTLS 使用 tls-client 执行请求
func (c *TLSClient) doTLS(req *http.Request) (*http.Response, error) {
fhttpReq, err := http2.NewRequest(req.Method, req.URL.String(), req.Body)
if err != nil {
return nil, err
@@ -247,7 +336,7 @@ func (c *TLSClient) Do(req *http.Request) (*http.Response, error) {
}
}
resp, err := c.client.Do(fhttpReq)
resp, err := c.tlsClient.Do(fhttpReq)
if err != nil {
return nil, err
}
@@ -261,7 +350,7 @@ func (c *TLSClient) Do(req *http.Request) (*http.Response, error) {
}
}
stdResp := &http.Response{
return &http.Response{
Status: resp.Status,
StatusCode: resp.StatusCode,
Proto: resp.Proto,
@@ -274,23 +363,104 @@ func (c *TLSClient) Do(req *http.Request) (*http.Response, error) {
Close: resp.Close,
Uncompressed: resp.Uncompressed,
Request: finalReq,
}, nil
}
// doAzureTLS 使用 azuretls 执行请求
func (c *TLSClient) doAzureTLS(req *http.Request) (*http.Response, error) {
orderedHeaders := azuretls.OrderedHeaders{}
for key, value := range c.getDefaultHeaders() {
if req.Header.Get(key) == "" {
orderedHeaders = append(orderedHeaders, []string{key, value})
}
}
for key, values := range req.Header {
if len(values) > 0 {
orderedHeaders = append(orderedHeaders, []string{key, values[0]})
}
}
return stdResp, nil
azureReq := &azuretls.Request{
Method: req.Method,
Url: req.URL.String(),
OrderedHeaders: orderedHeaders,
DisableRedirects: true,
}
if req.Body != nil {
bodyBytes, _ := io.ReadAll(req.Body)
azureReq.Body = bodyBytes
}
resp, err := c.azureSession.Do(azureReq)
if err != nil {
return nil, err
}
respHeaders := make(http.Header)
for key, values := range resp.Header {
respHeaders[key] = values
}
return &http.Response{
Status: fmt.Sprintf("%d %s", resp.StatusCode, http.StatusText(resp.StatusCode)),
StatusCode: resp.StatusCode,
Header: respHeaders,
Body: io.NopCloser(bytes.NewReader(resp.Body)),
Request: req,
}, nil
}
// DoWithRedirect 执行请求并手动处理重定向
func (c *TLSClient) DoWithRedirect(req *http.Request, maxRedirects int) (*http.Response, error) {
for i := 0; i <= maxRedirects; i++ {
resp, err := c.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
location := resp.Header.Get("Location")
if location == "" {
return resp, nil
}
redirectURL, err := url.Parse(location)
if err != nil {
return resp, nil
}
if !redirectURL.IsAbs() {
redirectURL = req.URL.ResolveReference(redirectURL)
}
req, err = http.NewRequest(http.MethodGet, redirectURL.String(), nil)
if err != nil {
return nil, err
}
resp.Body.Close()
continue
}
return resp, nil
}
return nil, fmt.Errorf("too many redirects")
}
// Get 执行 GET 请求
func (c *TLSClient) Get(urlStr string) (*http.Response, error) {
req, err := http.NewRequest("GET", urlStr, nil)
req, err := http.NewRequest(http.MethodGet, urlStr, nil)
if err != nil {
return nil, err
}
return c.Do(req)
return c.DoWithRedirect(req, 10)
}
// Post 执行 POST 请求
func (c *TLSClient) Post(urlStr string, contentType string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest("POST", urlStr, body)
req, err := http.NewRequest(http.MethodPost, urlStr, body)
if err != nil {
return nil, err
}
@@ -298,11 +468,6 @@ func (c *TLSClient) Post(urlStr string, contentType string, body io.Reader) (*ht
return c.Do(req)
}
// PostForm 执行 POST 表单请求
func (c *TLSClient) PostForm(urlStr string, data url.Values) (*http.Response, error) {
return c.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
// PostJSON 执行 POST JSON 请求
func (c *TLSClient) PostJSON(urlStr string, body io.Reader) (*http.Response, error) {
return c.Post(urlStr, "application/json", body)
@@ -310,11 +475,15 @@ func (c *TLSClient) PostJSON(urlStr string, body io.Reader) (*http.Response, err
// GetCookie 获取指定 URL 的 Cookie
func (c *TLSClient) GetCookie(urlStr string, name string) string {
if c.clientType == ClientTypeAzureTLS {
return "" // azuretls cookie 管理待完善,目前主要依赖 tls-client 或手动 handle
}
u, err := url.Parse(urlStr)
if err != nil {
return ""
}
cookies := c.client.GetCookies(u)
cookies := c.tlsClient.GetCookies(u)
for _, cookie := range cookies {
if cookie.Name == name {
return cookie.Value
@@ -325,11 +494,15 @@ func (c *TLSClient) GetCookie(urlStr string, name string) string {
// SetCookie 设置 Cookie
func (c *TLSClient) SetCookie(urlStr string, cookie *http.Cookie) {
if c.clientType == ClientTypeAzureTLS {
return
}
u, err := url.Parse(urlStr)
if err != nil {
return
}
c.client.SetCookies(u, []*http2.Cookie{
c.tlsClient.SetCookies(u, []*http2.Cookie{
{
Name: cookie.Name,
Value: cookie.Value,
@@ -371,3 +544,20 @@ func ReadBodyString(resp *http.Response) (string, error) {
}
return string(body), nil
}
// GetFingerprintInfo 获取指纹信息字符串(用于日志输出)
func (c *TLSClient) GetFingerprintInfo() string {
fp := c.fingerprint
typeName := "tls-client"
if c.clientType == ClientTypeAzureTLS {
typeName = "azuretls"
}
return fmt.Sprintf("%s/%s %s (%s)", typeName, fp.Browser, fp.Version, fp.Platform)
}
// Close 关闭客户端
func (c *TLSClient) Close() {
if c.azureSession != nil {
c.azureSession.Close()
}
}