From 44e8e47cbc1f41d126bdf08966c2a13aad4f677b Mon Sep 17 00:00:00 2001 From: benya Date: Thu, 4 Jun 2026 19:42:34 +0300 Subject: [PATCH] Rewrite LuCI bootstrap paths under proxy prefix --- server/internal/httpapi/server.go | 6 +++++- server/internal/httpapi/server_test.go | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/server/internal/httpapi/server.go b/server/internal/httpapi/server.go index 5efa1c8..5a7a712 100644 --- a/server/internal/httpapi/server.go +++ b/server/internal/httpapi/server.go @@ -1135,7 +1135,7 @@ func (a *App) proxyLuCI(w http.ResponseWriter, r *http.Request, deviceID, sessio removeCookie(req, luciRouteCookie) } proxy.ModifyResponse = func(resp *http.Response) error { - if resp.StatusCode >= 400 { + if resp.StatusCode >= 400 && resp.Header.Get("X-LuCI-Login-Required") == "" { logStructured(map[string]any{ "event": "luci.upstream_error", "request_id": requestID(r.Context()), @@ -1205,6 +1205,10 @@ func rewriteLuCIBody(body []byte, prefix string) []byte { replacement := marker[:len(marker)-1] + prefix + "/" body = bytes.ReplaceAll(body, []byte(marker), []byte(replacement)) } + escapedPrefix := strings.ReplaceAll(prefix, "/", `\/`) + for _, root := range []string{`\/cgi-bin\/luci`, `\/luci-static`, `\/ubus\/`} { + body = bytes.ReplaceAll(body, []byte(root), []byte(escapedPrefix+root)) + } return body } diff --git a/server/internal/httpapi/server_test.go b/server/internal/httpapi/server_test.go index 326469e..8464cbc 100644 --- a/server/internal/httpapi/server_test.go +++ b/server/internal/httpapi/server_test.go @@ -426,7 +426,7 @@ func TestLuCIProxyRequiresActiveSessionAndRewritesPaths(t *testing.T) { } upstreamPath = r.URL.Path w.Header().Set("Content-Type", "text/html") - _, _ = io.WriteString(w, `LuCI`) + _, _ = io.WriteString(w, `LuCI`) })) defer upstream.Close() upstreamURL, err := url.Parse(upstream.URL) @@ -472,6 +472,12 @@ func TestLuCIProxyRequiresActiveSessionAndRewritesPaths(t *testing.T) { if !strings.Contains(body, `href="`+prefix+`/cgi-bin/luci/admin"`) || !strings.Contains(body, `href="`+prefix+`/luci-static/test.css"`) { t.Fatalf("LuCI paths were not rewritten: %s", body) } + escapedPrefix := strings.ReplaceAll(prefix, "/", `\/`) + for _, path := range []string{`\/luci-static\/resources`, `\/cgi-bin\/luci`, `\/ubus\/`} { + if !strings.Contains(body, escapedPrefix+path) { + t.Fatalf("escaped LuCI path %s was not rewritten: %s", path, body) + } + } jar, err := cookiejar.New(nil) if err != nil {