上传文件至「/」
This commit is contained in:
+213
@@ -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{
|
||||
Reference in New Issue
Block a user