fix(gateway/services): admin node/render pages 500 — redirect loop + is_admin claim
Build backend images / build content-svc (push) Failing after 56s
Build backend images / build file-svc (push) Failing after 54s
Build backend images / build gateway (push) Failing after 55s
Build backend images / build identity-svc (push) Failing after 48s
Build backend images / build notification-svc (push) Failing after 55s
Build backend images / build render-svc (push) Failing after 57s
Build backend images / build studio-svc (push) Failing after 44s

- gateway proxy: trim trailing slash before forwarding upstream. gin's
  RedirectTrailingSlash adds /nodes → /nodes/ while render-svc redirects
  /nodes/ → /nodes, forming an infinite redirect loop (admin pages 500'd)
- accept is_admin as bool OR string "true" in render/file/notification/gateway
  auth middleware (identity emits it as a string) — admin endpoints were 403'ing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-02 11:26:44 +03:30
parent 1aacf8bd5d
commit cd95ca2c6f
5 changed files with 44 additions and 5 deletions
+7
View File
@@ -38,6 +38,13 @@ func New(name, target string) *Upstream {
orig := rp.Director
rp.Director = func(req *http.Request) {
orig(req)
// Normalise away a trailing slash (gin's RedirectTrailingSlash adds one when a
// route is registered as catch-all, e.g. /v1/nodes/*path, but upstream services
// register the canonical no-slash form and redirect /nodes/ → /nodes — without
// this the two redirects form an infinite loop).
if len(req.URL.Path) > 1 && strings.HasSuffix(req.URL.Path, "/") {
req.URL.Path = strings.TrimRight(req.URL.Path, "/")
}
req.Header.Set("X-Forwarded-Host", req.Host)
req.Header.Del("X-Forwarded-For") // let httputil re-add it properly
req.Host = u.Host