From fc9e336e6bef897e848898d94ebb86dbb715d6b1 Mon Sep 17 00:00:00 2001 From: Agent Date: Mon, 25 May 2026 00:04:35 +0800 Subject: [PATCH] fix: auto-follow redirects in DynamicProxy to avoid HTTP downgrade warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub download links (codeload.github.com) return 302 redirects to objects.githubusercontent.com. When ReverseProxy passes the 302 through to the browser, Chrome sees a HTTPS→HTTP redirect chain and shows "redirected through an insecure connection" + ERR_CACHE_WRITE_FAILURE. Add followRedirectTransport that uses http.Client to automatically follow 3xx redirects before ReverseProxy sees the response. The browser now receives the final ZIP content directly with a 200 status. via [HAPI](https://hapi.run) Co-Authored-By: HAPI --- internal/proxy/dynamic.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/internal/proxy/dynamic.go b/internal/proxy/dynamic.go index 785bb79..86c66c1 100644 --- a/internal/proxy/dynamic.go +++ b/internal/proxy/dynamic.go @@ -13,6 +13,20 @@ import ( "mirror-proxy/internal/auth" ) +// followRedirectTransport 包装 http.RoundTripper,自动跟随 3xx 重定向。 +// 用于 DynamicProxy,避免浏览器在 HTTP 代理上看到 HTTPS→HTTP 的 302 降级警告。 +type followRedirectTransport struct { + base http.RoundTripper +} + +func (t *followRedirectTransport) RoundTrip(req *http.Request) (*http.Response, error) { + client := &http.Client{ + Transport: t.base, + CheckRedirect: func(req *http.Request, via []*http.Request) error { return nil }, + } + return client.Do(req) +} + // DynamicProxy 创建指向任意目标 URL 的反向代理 func DynamicProxy(targetURL string) http.Handler { target, err := url.Parse(targetURL) @@ -92,11 +106,13 @@ func DynamicProxy(targetURL string) http.Handler { w.WriteHeader(http.StatusBadGateway) fmt.Fprintf(w, "Proxy error: %s", err.Error()) }, - Transport: &http.Transport{ - MaxIdleConns: 100, - MaxIdleConnsPerHost: 20, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, + Transport: &followRedirectTransport{ + base: &http.Transport{ + MaxIdleConns: 100, + MaxIdleConnsPerHost: 20, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + }, }, }