From d4dd867478bd73fa8782507ede0a81d829098c0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 09:25:26 +0000 Subject: [PATCH 1/3] Initial plan From 0ec5e0369588a6f09702785ed1ecc5676d6428ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 09:29:35 +0000 Subject: [PATCH 2/3] fix: correct dialer context usage Co-authored-by: lwaay2025 <218015601+lwaay2025@users.noreply.github.com> --- main.go | 2 +- services/httpclient.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 411001a..1fb2c9a 100644 --- a/main.go +++ b/main.go @@ -401,7 +401,7 @@ func main() { }() // Run the application. This blocks until the application has been exited. - err := app.Run() + err = app.Run() // If an error occurred while running the application, log it and exit. if err != nil { diff --git a/services/httpclient.go b/services/httpclient.go index 84a34ff..f22a0b0 100644 --- a/services/httpclient.go +++ b/services/httpclient.go @@ -1,6 +1,7 @@ package services import ( + "context" "crypto/tls" "fmt" "net" @@ -202,7 +203,7 @@ func createSOCKS5ProxyTransport(proxyAddr string) (*http.Transport, error) { // 创建使用 SOCKS5 代理的传输层 transport := &http.Transport{ Dial: dialer.Dial, - DialContext: func(ctx interface{}, network, addr string) (net.Conn, error) { + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return dialer.Dial(network, addr) }, ForceAttemptHTTP2: false, // SOCKS5 通常不支持 HTTP/2 From c515bee0c5ed456d59e0e903e66dc5c7ed2a7980 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 09:36:30 +0000 Subject: [PATCH 3/3] refine: improve SOCKS5 dial context handling Co-authored-by: lwaay2025 <218015601+lwaay2025@users.noreply.github.com> --- services/httpclient.go | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/services/httpclient.go b/services/httpclient.go index f22a0b0..5f494eb 100644 --- a/services/httpclient.go +++ b/services/httpclient.go @@ -194,8 +194,12 @@ func createSOCKS5ProxyTransport(proxyAddr string) (*http.Transport, error) { socksAddr = proxyAddr } - // 创建 SOCKS5 拨号器 - dialer, err := proxy.SOCKS5("tcp", socksAddr, nil, proxy.Direct) + // 创建 SOCKS5 拨号器,使用带超时的底层拨号器避免长时间阻塞 + baseDialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + } + dialer, err := proxy.SOCKS5("tcp", socksAddr, nil, baseDialer) if err != nil { return nil, fmt.Errorf("创建 SOCKS5 拨号器失败: %w", err) } @@ -204,7 +208,33 @@ func createSOCKS5ProxyTransport(proxyAddr string) (*http.Transport, error) { transport := &http.Transport{ Dial: dialer.Dial, DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { - return dialer.Dial(network, addr) + if ctxDialer, ok := dialer.(proxy.ContextDialer); ok { + return ctxDialer.DialContext(ctx, network, addr) + } + type result struct { + conn net.Conn + err error + } + resultCh := make(chan result, 1) + go func() { + if ctxErr := ctx.Err(); ctxErr != nil { + resultCh <- result{conn: nil, err: ctxErr} + return + } + conn, err := dialer.Dial(network, addr) + if ctx.Err() != nil && conn != nil { + _ = conn.Close() + err = ctx.Err() + conn = nil + } + resultCh <- result{conn: conn, err: err} + }() + select { + case res := <-resultCh: + return res.conn, res.err + case <-ctx.Done(): + return nil, ctx.Err() + } }, ForceAttemptHTTP2: false, // SOCKS5 通常不支持 HTTP/2 MaxIdleConns: 100,