commit 85b0672a608581924c1329102c2d151d6a0944a7 Author: lyc Date: Fri Aug 21 01:19:45 2026 +0000 上传文件至「/」 diff --git a/insecure.diff b/insecure.diff new file mode 100644 index 0000000..f98cd51 --- /dev/null +++ b/insecure.diff @@ -0,0 +1,213 @@ +diff --git a/internal/config/config_types.go b/internal/config/config_types.go +index 783f666..df24892 100644 +--- a/internal/config/config_types.go ++++ b/internal/config/config_types.go +@@ -655,6 +655,9 @@ type OpenAICompatibility struct { + // BaseURL is the base URL for the external OpenAI-compatible API endpoint. + BaseURL string `yaml:"base-url" json:"base-url"` + ++ // Insecure disables TLS certificate verification for this provider. ++ Insecure bool `yaml:"insecure,omitempty" json:"insecure,omitempty"` ++ + // APIKeyEntries defines API keys with optional per-key proxy configuration. + APIKeyEntries []OpenAICompatibilityAPIKey `yaml:"api-key-entries,omitempty" json:"api-key-entries,omitempty"` + +diff --git a/internal/runtime/executor/helps/proxy_helpers.go b/internal/runtime/executor/helps/proxy_helpers.go +index 572f87c..dcf3700 100644 +--- a/internal/runtime/executor/helps/proxy_helpers.go ++++ b/internal/runtime/executor/helps/proxy_helpers.go +@@ -2,6 +2,7 @@ package helps + + import ( + "context" ++ "crypto/tls" + "net/http" + "strings" + "time" +@@ -33,8 +34,10 @@ func NewProxyAwareHTTPClient(ctx context.Context, cfg *config.Config, auth *clip + + // Priority 1: Use auth.ProxyURL if configured + var proxyURL string ++ insecure := false + if auth != nil { + proxyURL = strings.TrimSpace(auth.ProxyURL) ++ insecure = strings.EqualFold(strings.TrimSpace(auth.Attributes["insecure"]), "true") + } + + // Priority 2: Use cfg.ProxyURL if auth proxy is not configured +@@ -46,7 +49,7 @@ func NewProxyAwareHTTPClient(ctx context.Context, cfg *config.Config, auth *clip + if proxyURL != "" { + transport := buildProxyTransport(proxyURL) + if transport != nil { +- httpClient.Transport = transport ++ httpClient.Transport = configureInsecureTLS(transport, insecure) + return httpClient + } + // If proxy setup failed, log and fall through to context RoundTripper +@@ -55,12 +58,32 @@ func NewProxyAwareHTTPClient(ctx context.Context, cfg *config.Config, auth *clip + + // Priority 3: Use RoundTripper from context (typically from RoundTripperFor) + if rt, ok := ctx.Value("cliproxy.roundtripper").(http.RoundTripper); ok && rt != nil { +- httpClient.Transport = rt ++ httpClient.Transport = configureInsecureTLS(rt, insecure) ++ } else if insecure { ++ httpClient.Transport = configureInsecureTLS(http.DefaultTransport, true) + } + + return httpClient + } + ++func configureInsecureTLS(rt http.RoundTripper, insecure bool) http.RoundTripper { ++ if !insecure { ++ return rt ++ } ++ transport, ok := rt.(*http.Transport) ++ if !ok || transport == nil { ++ return rt ++ } ++ transport = transport.Clone() ++ if transport.TLSClientConfig == nil { ++ transport.TLSClientConfig = &tls.Config{} ++ } else { ++ transport.TLSClientConfig = transport.TLSClientConfig.Clone() ++ } ++ transport.TLSClientConfig.InsecureSkipVerify = true ++ return transport ++} ++ + // buildProxyTransport creates an HTTP transport configured for the given proxy URL. + // It supports SOCKS5, HTTP, and HTTPS proxy protocols. + // +diff --git a/internal/runtime/executor/helps/proxy_helpers_test.go b/internal/runtime/executor/helps/proxy_helpers_test.go +index fb57b6b..9586cee 100644 +--- a/internal/runtime/executor/helps/proxy_helpers_test.go ++++ b/internal/runtime/executor/helps/proxy_helpers_test.go +@@ -2,6 +2,7 @@ package helps + + import ( + "context" ++ "crypto/tls" + "net/http" + "testing" + +@@ -28,3 +29,49 @@ func TestNewProxyAwareHTTPClientDirectBypassesGlobalProxy(t *testing.T) { + t.Fatal("expected direct transport to disable proxy function") + } + } ++ ++func TestNewProxyAwareHTTPClientInsecureTLS(t *testing.T) { ++ t.Parallel() ++ ++ insecureClient := NewProxyAwareHTTPClient(context.Background(), nil, &cliproxyauth.Auth{ ++ Attributes: map[string]string{"insecure": "true"}, ++ }, 0) ++ transport, ok := insecureClient.Transport.(*http.Transport) ++ if !ok { ++ t.Fatalf("transport type = %T, want *http.Transport", insecureClient.Transport) ++ } ++ if transport.TLSClientConfig == nil || !transport.TLSClientConfig.InsecureSkipVerify { ++ t.Fatal("InsecureSkipVerify = false, want true") ++ } ++} ++ ++func TestNewProxyAwareHTTPClientClonesTransportForInsecureTLS(t *testing.T) { ++ t.Parallel() ++ ++ original := http.DefaultTransport.(*http.Transport).Clone() ++ original.TLSClientConfig = &tls.Config{MinVersion: tls.VersionTLS12} ++ ctx := context.WithValue(context.Background(), "cliproxy.roundtripper", http.RoundTripper(original)) ++ ++ client := NewProxyAwareHTTPClient(ctx, nil, &cliproxyauth.Auth{ ++ Attributes: map[string]string{"insecure": "true"}, ++ }, 0) ++ configured, ok := client.Transport.(*http.Transport) ++ if !ok { ++ t.Fatalf("transport type = %T, want *http.Transport", client.Transport) ++ } ++ if configured == original { ++ t.Fatal("insecure TLS mutated the original transport") ++ } ++ if original.TLSClientConfig.InsecureSkipVerify { ++ t.Fatal("insecure TLS mutated the original TLS config") ++ } ++ if configured.TLSClientConfig == original.TLSClientConfig { ++ t.Fatal("insecure TLS reused the original TLS config") ++ } ++ if !configured.TLSClientConfig.InsecureSkipVerify { ++ t.Fatal("InsecureSkipVerify = false, want true") ++ } ++ if configured.TLSClientConfig.MinVersion != tls.VersionTLS12 { ++ t.Fatalf("MinVersion = %d, want %d", configured.TLSClientConfig.MinVersion, tls.VersionTLS12) ++ } ++} +diff --git a/internal/watcher/synthesizer/config.go b/internal/watcher/synthesizer/config.go +index c5f5722..447fdfd 100644 +--- a/internal/watcher/synthesizer/config.go ++++ b/internal/watcher/synthesizer/config.go +@@ -305,6 +305,9 @@ func (s *ConfigSynthesizer) synthesizeOpenAICompat(ctx *SynthesisContext) []*cor + "provider_key": internalProviderKey, + "config_index": strconv.Itoa(i), + } ++ if compat.Insecure { ++ attrs["insecure"] = "true" ++ } + metadata := map[string]any{} + if disableCooling != nil { + metadata["disable_cooling"] = *disableCooling +@@ -351,6 +354,9 @@ func (s *ConfigSynthesizer) synthesizeOpenAICompat(ctx *SynthesisContext) []*cor + "provider_key": internalProviderKey, + "config_index": strconv.Itoa(i), + } ++ if compat.Insecure { ++ attrs["insecure"] = "true" ++ } + metadata := map[string]any{} + if disableCooling != nil { + metadata["disable_cooling"] = *disableCooling +diff --git a/internal/watcher/synthesizer/config_test.go b/internal/watcher/synthesizer/config_test.go +index e4a9abc..f79babe 100644 +--- a/internal/watcher/synthesizer/config_test.go ++++ b/internal/watcher/synthesizer/config_test.go +@@ -524,6 +524,42 @@ func TestConfigSynthesizer_OpenAICompat(t *testing.T) { + } + } + ++func TestConfigSynthesizer_OpenAICompat_Insecure(t *testing.T) { ++ synth := NewConfigSynthesizer() ++ ctx := &SynthesisContext{ ++ Config: &config.Config{ ++ OpenAICompatibility: []config.OpenAICompatibility{ ++ { ++ Name: "with-key", ++ BaseURL: "https://with-key.example.com", ++ Insecure: true, ++ APIKeyEntries: []config.OpenAICompatibilityAPIKey{{APIKey: "key"}}, ++ }, ++ { ++ Name: "without-key", ++ BaseURL: "https://without-key.example.com", ++ Insecure: true, ++ }, ++ }, ++ }, ++ Now: time.Now(), ++ IDGenerator: NewStableIDGenerator(), ++ } ++ ++ auths, errSynthesize := synth.Synthesize(ctx) ++ if errSynthesize != nil { ++ t.Fatalf("Synthesize() error = %v", errSynthesize) ++ } ++ if len(auths) != 2 { ++ t.Fatalf("auth count = %d, want 2", len(auths)) ++ } ++ for i := range auths { ++ if got := auths[i].Attributes["insecure"]; got != "true" { ++ t.Fatalf("auth[%d] insecure = %q, want true", i, got) ++ } ++ } ++} ++ + func TestConfigSynthesizer_OpenAICompat_UsesNamespacedProviderKey(t *testing.T) { + synth := NewConfigSynthesizer() + ctx := &SynthesisContext{