上传文件至「/」

This commit is contained in:
lyc
2026-08-21 01:19:45 +00:00
commit 85b0672a60
+213
View File
@@ -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{