支持统一代理配置
Browse files- README.md +1 -0
- internal/tls_http.go +41 -25
README.md
CHANGED
|
@@ -25,6 +25,7 @@ Required runtime secrets:
|
|
| 25 |
|
| 26 |
The container sets `CAPTCHA_PROVIDER_URL=http://127.0.0.1:9876` so the proxy can fetch captcha tokens from the internal provider.
|
| 27 |
If the internal provider cannot get an Aliyun token from the current Space egress IP, set `FALLBACK_CAPTCHA_PROVIDER_URL` to another compatible captcha token service.
|
|
|
|
| 28 |
|
| 29 |
> 将 [Z.AI](https://chat.z.ai) 转换为 OpenAI 兼容 API 的代理服务。
|
| 30 |
>
|
|
|
|
| 25 |
|
| 26 |
The container sets `CAPTCHA_PROVIDER_URL=http://127.0.0.1:9876` so the proxy can fetch captcha tokens from the internal provider.
|
| 27 |
If the internal provider cannot get an Aliyun token from the current Space egress IP, set `FALLBACK_CAPTCHA_PROVIDER_URL` to another compatible captcha token service.
|
| 28 |
+
If Z.AI rejects the Space egress IP, set `PROXY_SERVER` to an HTTP(S)/SOCKS proxy URL; both the captcha provider and Go proxy use it.
|
| 29 |
|
| 30 |
> 将 [Z.AI](https://chat.z.ai) 转换为 OpenAI 兼容 API 的代理服务。
|
| 31 |
>
|
internal/tls_http.go
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
package internal
|
| 2 |
|
| 3 |
-
import (
|
| 4 |
-
"fmt"
|
| 5 |
-
"
|
| 6 |
-
"
|
|
|
|
|
|
|
| 7 |
|
| 8 |
fhttp "github.com/bogdanfinn/fhttp"
|
| 9 |
tls_client "github.com/bogdanfinn/tls-client"
|
|
@@ -22,27 +24,41 @@ var (
|
|
| 22 |
)
|
| 23 |
|
| 24 |
// TLSHTTPClient 返回按超时(秒)复用的 tls-client 实例;所有出站 HTTPS 应通过此处以统一指纹。
|
| 25 |
-
func TLSHTTPClient(timeout time.Duration) (tls_client.HttpClient, error) {
|
| 26 |
-
sec := int(timeout.Round(time.Second) / time.Second)
|
| 27 |
-
if sec < 1 {
|
| 28 |
-
sec = 1
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
tls_client.
|
| 38 |
-
tls_client.
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
// ApplyBrowserFingerprintHeaders 设置与 Chrome 133 一致的 User-Agent 与 Sec-CH-UA(配合 TLSHTTPClient 的 TLS/H2 指纹)。
|
| 48 |
func ApplyBrowserFingerprintHeaders(h fhttp.Header) {
|
|
|
|
| 1 |
package internal
|
| 2 |
|
| 3 |
+
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"os"
|
| 6 |
+
"strings"
|
| 7 |
+
"sync"
|
| 8 |
+
"time"
|
| 9 |
|
| 10 |
fhttp "github.com/bogdanfinn/fhttp"
|
| 11 |
tls_client "github.com/bogdanfinn/tls-client"
|
|
|
|
| 24 |
)
|
| 25 |
|
| 26 |
// TLSHTTPClient 返回按超时(秒)复用的 tls-client 实例;所有出站 HTTPS 应通过此处以统一指纹。
|
| 27 |
+
func TLSHTTPClient(timeout time.Duration) (tls_client.HttpClient, error) {
|
| 28 |
+
sec := int(timeout.Round(time.Second) / time.Second)
|
| 29 |
+
if sec < 1 {
|
| 30 |
+
sec = 1
|
| 31 |
+
}
|
| 32 |
+
proxyURL := resolveProxyURL()
|
| 33 |
+
tlsClientMu.Lock()
|
| 34 |
+
defer tlsClientMu.Unlock()
|
| 35 |
+
if c, ok := tlsBySec[sec]; ok {
|
| 36 |
+
return c, nil
|
| 37 |
+
}
|
| 38 |
+
options := []tls_client.HttpClientOption{
|
| 39 |
+
tls_client.WithTimeoutSeconds(sec),
|
| 40 |
+
tls_client.WithClientProfile(DefaultBrowserProfile),
|
| 41 |
+
tls_client.WithRandomTLSExtensionOrder(),
|
| 42 |
+
}
|
| 43 |
+
if proxyURL != "" {
|
| 44 |
+
options = append(options, tls_client.WithProxyUrl(proxyURL))
|
| 45 |
+
}
|
| 46 |
+
c, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
|
| 47 |
+
if err != nil {
|
| 48 |
+
return nil, fmt.Errorf("tls-client: %w", err)
|
| 49 |
+
}
|
| 50 |
+
tlsBySec[sec] = c
|
| 51 |
+
return c, nil
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
func resolveProxyURL() string {
|
| 55 |
+
for _, name := range []string{"PROXY_SERVER", "ZAI_PROXY", "HTTPS_PROXY", "HTTP_PROXY"} {
|
| 56 |
+
if value := strings.TrimSpace(os.Getenv(name)); value != "" {
|
| 57 |
+
return value
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
return ""
|
| 61 |
+
}
|
| 62 |
|
| 63 |
// ApplyBrowserFingerprintHeaders 设置与 Chrome 133 一致的 User-Agent 与 Sec-CH-UA(配合 TLSHTTPClient 的 TLS/H2 指纹)。
|
| 64 |
func ApplyBrowserFingerprintHeaders(h fhttp.Header) {
|