From 37daf1aa0d1131fadb9f75e7bc935c1df4cee520 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 14 Mar 2026 17:54:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20apiCallTransport=20fallback=20?= =?UTF-8?q?=E5=BA=94=E4=BF=9D=E7=95=99=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当凭证和全局配置均未设置代理时,apiCallTransport 的 fallback 分支显式将 Proxy 设为 nil,禁用了环境变量代理(HTTP_PROXY/ HTTPS_PROXY)。而 codex_websockets_executor 中的 newProxyAwareWebsocketDialer 在相同场景下保留了 http.ProxyFromEnvironment 作为默认行为。 这一不一致导致管理面板通过 /v0/management/api-call 代理的 请求(如获取 Codex 额度)在仅配置了环境变量代理的部署环境中 无法到达上游服务,触发 30 秒超时。 修复方式:当没有显式代理配置时,直接返回 http.DefaultTransport, 保留其默认的 ProxyFromEnvironment 行为,与 WebSocket 执行器 保持一致。 Co-Authored-By: Claude Opus 4.6 --- internal/api/handlers/management/api_tools.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/internal/api/handlers/management/api_tools.go b/internal/api/handlers/management/api_tools.go index de546ea820..a6e4eded71 100644 --- a/internal/api/handlers/management/api_tools.go +++ b/internal/api/handlers/management/api_tools.go @@ -649,13 +649,7 @@ func (h *Handler) apiCallTransport(auth *coreauth.Auth) http.RoundTripper { } } - transport, ok := http.DefaultTransport.(*http.Transport) - if !ok || transport == nil { - return &http.Transport{Proxy: nil} - } - clone := transport.Clone() - clone.Proxy = nil - return clone + return http.DefaultTransport } func buildProxyTransport(proxyStr string) *http.Transport { From 1bd04b2072c72deecaf31027d2ff60cb2eec732a Mon Sep 17 00:00:00 2001 From: zhoubeiqing Date: Tue, 17 Mar 2026 22:32:04 +0800 Subject: [PATCH 2/2] Update api_tools_test.go --- .../api/handlers/management/api_tools_test.go | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/internal/api/handlers/management/api_tools_test.go b/internal/api/handlers/management/api_tools_test.go index 5b0c63693a..91086c15db 100644 --- a/internal/api/handlers/management/api_tools_test.go +++ b/internal/api/handlers/management/api_tools_test.go @@ -56,3 +56,57 @@ func TestAPICallTransportInvalidAuthFallsBackToGlobalProxy(t *testing.T) { t.Fatalf("proxy URL = %v, want http://global-proxy.example.com:8080", proxyURL) } } +func TestAPICallTransport_InheritsEnvironmentProxyWhenNoExplicitProxyConfigured(t *testing.T) { + t.Setenv("HTTP_PROXY", "http://127.0.0.1:18080") + t.Setenv("HTTPS_PROXY", "http://127.0.0.1:18443") + t.Setenv("NO_PROXY", "") + + h := &Handler{ + cfg: &config.Config{ + SDKConfig: sdkconfig.SDKConfig{ProxyURL: ""}, + }, + } + + rt := h.apiCallTransport(&coreauth.Auth{ProxyURL: ""}) + transport, ok := rt.(*http.Transport) + if ok && transport.Proxy != nil { + tests := []struct { + name string + raw string + want string + }{ + {name: "http request uses HTTP_PROXY", raw: "http://example.com", want: "http://127.0.0.1:18080"}, + {name: "https request uses HTTPS_PROXY", raw: "https://example.com", want: "http://127.0.0.1:18443"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req, err := http.NewRequest("GET", tt.raw, nil) + if err != nil { + t.Fatalf("new request: %v", err) + } + proxyURL, err := transport.Proxy(req) + if err != nil { + t.Fatalf("proxy func returned error: %v", err) + } + if proxyURL == nil { + t.Fatal("expected environment proxy to be inherited, got nil") + } + if got := proxyURL.String(); got != tt.want { + t.Fatalf("expected proxy %q, got %q", tt.want, got) + } + }) + } + return + } + req, err := http.NewRequest("GET", "https://example.com", nil) + if err != nil { + t.Fatalf("new request: %v", err) + } + proxyURL, err := http.ProxyFromEnvironment(req) + if err != nil { + t.Fatalf("ProxyFromEnvironment error: %v", err) + } + if proxyURL == nil || proxyURL.String() != "http://127.0.0.1:18443" { + t.Fatalf("expected environment proxy http://127.0.0.1:18443, got %v", proxyURL) + } + }