From e31661dba765ac4c72a4ae08305accea130c46cc Mon Sep 17 00:00:00 2001 From: jcj46548-ux Date: Sat, 6 Jun 2026 21:49:41 +0800 Subject: [PATCH 1/2] fix: support lowercase proxy environment variables --- .../local_runtime/setup_python_environment.go | 10 +--- internal/core/local_runtime/subprocess.go | 10 +--- internal/types/app/config_test.go | 53 +++++++++++++++++++ internal/types/app/default.go | 1 + internal/types/app/proxy.go | 41 ++++++++++++++ 5 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 internal/types/app/proxy.go diff --git a/internal/core/local_runtime/setup_python_environment.go b/internal/core/local_runtime/setup_python_environment.go index 50324c491..05164f0c4 100644 --- a/internal/core/local_runtime/setup_python_environment.go +++ b/internal/core/local_runtime/setup_python_environment.go @@ -197,15 +197,7 @@ func (p *LocalPluginRuntime) installDependencies( parent.SetAttributes(attribute.String("uv.path", uvPath), attribute.StringSlice("uv.args", args)) cmd.Env = append(cmd.Env, "VIRTUAL_ENV="+virtualEnvPath, "PATH="+os.Getenv("PATH")) cmd.Env = append(cmd.Env, "UV_CACHE_DIR="+uvCacheDir) - if p.appConfig.HttpProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("HTTP_PROXY=%s", p.appConfig.HttpProxy)) - } - if p.appConfig.HttpsProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("HTTPS_PROXY=%s", p.appConfig.HttpsProxy)) - } - if p.appConfig.NoProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("NO_PROXY=%s", p.appConfig.NoProxy)) - } + cmd.Env = append(cmd.Env, p.appConfig.ProxyEnv()...) cmd.Dir = p.State.WorkingPath // get stdout and stderr diff --git a/internal/core/local_runtime/subprocess.go b/internal/core/local_runtime/subprocess.go index 37d9855ab..3f5e0d40b 100644 --- a/internal/core/local_runtime/subprocess.go +++ b/internal/core/local_runtime/subprocess.go @@ -33,15 +33,7 @@ func (r *LocalPluginRuntime) getInstanceCmd() (*exec.Cmd, error) { } cmd.Env = cmd.Environ() - if r.appConfig.HttpsProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("HTTPS_PROXY=%s", r.appConfig.HttpsProxy)) - } - if r.appConfig.HttpProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("HTTP_PROXY=%s", r.appConfig.HttpProxy)) - } - if r.appConfig.NoProxy != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("NO_PROXY=%s", r.appConfig.NoProxy)) - } + cmd.Env = append(cmd.Env, r.appConfig.ProxyEnv()...) cmd.Env = append(cmd.Env, "INSTALL_METHOD=local", "PATH="+os.Getenv("PATH")) cmd.Dir = r.State.WorkingPath return cmd, nil diff --git a/internal/types/app/config_test.go b/internal/types/app/config_test.go index b2592ffe8..bdba7bbed 100644 --- a/internal/types/app/config_test.go +++ b/internal/types/app/config_test.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "os" "path/filepath" + "runtime" "testing" "github.com/kelseyhightower/envconfig" @@ -86,6 +87,58 @@ func TestConfigRedisKeyPrefixField(t *testing.T) { assert.Equal(t, "enterprise-a", cfg.RedisKeyPrefix) } +func TestConfigProxyLowercaseFallbacks(t *testing.T) { + t.Setenv("http_proxy", "http://lowercase-http:8080") + t.Setenv("https_proxy", "http://lowercase-https:8443") + t.Setenv("no_proxy", "localhost,127.0.0.1") + + cfg := Config{} + require.NoError(t, envconfig.Process("", &cfg)) + cfg.SetDefault() + + assert.Equal(t, "http://lowercase-http:8080", cfg.HttpProxy) + assert.Equal(t, "http://lowercase-https:8443", cfg.HttpsProxy) + assert.Equal(t, "localhost,127.0.0.1", cfg.NoProxy) +} + +func TestConfigProxyUppercaseTakesPrecedence(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Windows environment variables are case-insensitive") + } + + t.Setenv("HTTP_PROXY", "http://uppercase-http:8080") + t.Setenv("http_proxy", "http://lowercase-http:8080") + t.Setenv("HTTPS_PROXY", "http://uppercase-https:8443") + t.Setenv("https_proxy", "http://lowercase-https:8443") + t.Setenv("NO_PROXY", "internal") + t.Setenv("no_proxy", "localhost") + + cfg := Config{} + require.NoError(t, envconfig.Process("", &cfg)) + cfg.SetDefault() + + assert.Equal(t, "http://uppercase-http:8080", cfg.HttpProxy) + assert.Equal(t, "http://uppercase-https:8443", cfg.HttpsProxy) + assert.Equal(t, "internal", cfg.NoProxy) +} + +func TestConfigProxyEnvIncludesUppercaseAndLowercase(t *testing.T) { + cfg := Config{ + HttpProxy: "http://proxy-http:8080", + HttpsProxy: "http://proxy-https:8443", + NoProxy: "localhost", + } + + assert.ElementsMatch(t, []string{ + "HTTP_PROXY=http://proxy-http:8080", + "http_proxy=http://proxy-http:8080", + "HTTPS_PROXY=http://proxy-https:8443", + "https_proxy=http://proxy-https:8443", + "NO_PROXY=localhost", + "no_proxy=localhost", + }, cfg.ProxyEnv()) +} + func TestRedisTLSConfig(t *testing.T) { tests := []struct { name string diff --git a/internal/types/app/default.go b/internal/types/app/default.go index eedaaa0c3..53d63618c 100644 --- a/internal/types/app/default.go +++ b/internal/types/app/default.go @@ -6,6 +6,7 @@ import ( ) func (config *Config) SetDefault() { + config.SetProxyEnvFallbacks() switch config.DBType { case DB_TYPE_OCEANBASE, DB_TYPE_SEEKDB: config.DBType = DB_TYPE_MYSQL diff --git a/internal/types/app/proxy.go b/internal/types/app/proxy.go new file mode 100644 index 000000000..3753bd636 --- /dev/null +++ b/internal/types/app/proxy.go @@ -0,0 +1,41 @@ +package app + +import ( + "fmt" + "os" +) + +func (config *Config) SetProxyEnvFallbacks() { + if config.HttpProxy == "" { + config.HttpProxy = os.Getenv("http_proxy") + } + if config.HttpsProxy == "" { + config.HttpsProxy = os.Getenv("https_proxy") + } + if config.NoProxy == "" { + config.NoProxy = os.Getenv("no_proxy") + } +} + +func (config *Config) ProxyEnv() []string { + env := []string{} + if config.HttpProxy != "" { + env = append(env, + fmt.Sprintf("HTTP_PROXY=%s", config.HttpProxy), + fmt.Sprintf("http_proxy=%s", config.HttpProxy), + ) + } + if config.HttpsProxy != "" { + env = append(env, + fmt.Sprintf("HTTPS_PROXY=%s", config.HttpsProxy), + fmt.Sprintf("https_proxy=%s", config.HttpsProxy), + ) + } + if config.NoProxy != "" { + env = append(env, + fmt.Sprintf("NO_PROXY=%s", config.NoProxy), + fmt.Sprintf("no_proxy=%s", config.NoProxy), + ) + } + return env +} From 52a51d00c32afbaf9c9426a1133eb016f0c776c3 Mon Sep 17 00:00:00 2001 From: jcj46548-ux Date: Sat, 6 Jun 2026 21:57:41 +0800 Subject: [PATCH 2/2] test: isolate proxy environment fallback --- internal/types/app/config_test.go | 3 +++ internal/types/app/proxy.go | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/internal/types/app/config_test.go b/internal/types/app/config_test.go index bdba7bbed..d7790927b 100644 --- a/internal/types/app/config_test.go +++ b/internal/types/app/config_test.go @@ -88,6 +88,9 @@ func TestConfigRedisKeyPrefixField(t *testing.T) { } func TestConfigProxyLowercaseFallbacks(t *testing.T) { + t.Setenv("HTTP_PROXY", "") + t.Setenv("HTTPS_PROXY", "") + t.Setenv("NO_PROXY", "") t.Setenv("http_proxy", "http://lowercase-http:8080") t.Setenv("https_proxy", "http://lowercase-https:8443") t.Setenv("no_proxy", "localhost,127.0.0.1") diff --git a/internal/types/app/proxy.go b/internal/types/app/proxy.go index 3753bd636..5d707dc31 100644 --- a/internal/types/app/proxy.go +++ b/internal/types/app/proxy.go @@ -6,6 +6,10 @@ import ( ) func (config *Config) SetProxyEnvFallbacks() { + if config == nil { + return + } + if config.HttpProxy == "" { config.HttpProxy = os.Getenv("http_proxy") } @@ -18,6 +22,10 @@ func (config *Config) SetProxyEnvFallbacks() { } func (config *Config) ProxyEnv() []string { + if config == nil { + return nil + } + env := []string{} if config.HttpProxy != "" { env = append(env,