diff --git a/internal/proxy/mihomo.go b/internal/proxy/mihomo.go index 78202cc..19c55a1 100644 --- a/internal/proxy/mihomo.go +++ b/internal/proxy/mihomo.go @@ -26,17 +26,21 @@ func NewMihomoForward( } rp := &httputil.ReverseProxy{ Rewrite: func(pr *httputil.ProxyRequest) { - NormalizeRequestURLPath(pr.In) - p := pr.In.URL.Path + // Нормализуем Out, не In (контракт httputil.ProxyRequest: In не трогать). + NormalizeRequestURLPath(pr.Out) + p := pr.Out.URL.Path if !strings.HasPrefix(p, stripPrefix) { return } rest := strings.TrimPrefix(strings.TrimPrefix(p, stripPrefix), "/") dest := JoinPathPrefix(target, "/", rest) du := *dest - du.RawQuery = pr.In.URL.RawQuery + du.RawQuery = pr.Out.URL.RawQuery out := pr.Out out.URL = &du + // Как в NewAliasForward: не оставлять Host клиента ни в поле, ни в Header — + // иначе строгий upstream (в т.ч. Mihomo) часто отвечает 400. + out.Header.Del("Host") out.Host = du.Host out.RequestURI = "" out.Proto = "HTTP/1.1" diff --git a/internal/proxy/mihomo_test.go b/internal/proxy/mihomo_test.go index 2d87d0d..a38a7fb 100644 --- a/internal/proxy/mihomo_test.go +++ b/internal/proxy/mihomo_test.go @@ -21,11 +21,15 @@ func TestMihomoForwardRewritesPathAndAuth(t *testing.T) { t.Fatal(err) } req.Header.Set("Authorization", "Bearer client-should-not-forward") + req.Header.Set("Host", "public-gateway.example:8888") h.ServeHTTP(httptest.NewRecorder(), req) if cap.got == nil { t.Fatal("no outgoing request captured") } + if got, want := cap.got.Host, "127.0.0.1:9090"; got != want { + t.Fatalf("Host: got %q want %q (upstream must not see client Host)", got, want) + } if got := cap.got.Header.Get("Authorization"); got != "Bearer testsecret" { t.Fatalf("Authorization: got %q want Bearer testsecret", got) }