Skip to content

fix(webui): use relative asset base so fonts and lazy chunks honor X-Forwarded-Prefix (#10889)#10904

Open
localai-org-maint-bot wants to merge 1 commit into
masterfrom
fix/10889-forwarded-prefix-assets
Open

fix(webui): use relative asset base so fonts and lazy chunks honor X-Forwarded-Prefix (#10889)#10904
localai-org-maint-bot wants to merge 1 commit into
masterfrom
fix/10889-forwarded-prefix-assets

Conversation

@localai-org-maint-bot

Copy link
Copy Markdown
Collaborator

What

Fixes #10889.

When LocalAI is served under a reverse-proxy subpath (X-Forwarded-Prefix: /llm/), Web UI fonts render as missing-glyph "tofu" and some lazy-loaded route chunks 404, because they are fetched from the origin root instead of under the prefix.

Root cause

The Vite build used base: '/', emitting path-absolute asset URLs. serveIndex (core/http/app.go) rewrites the entry <script>/<link> and favicon in index.html to include the prefix, and injects a <base href>. But two reference kinds live outside index.html and bypass that rewrite:

  • CSS url() font references (Font Awesome .woff2) — the browser resolves these relative to the stylesheet, and <base href> never affects CSS url().
  • Lazily-imported route chunks — their preload base came from the absolute Vite base.

Both resolved to /assets/... (origin root), skipping the /llm/ prefix → 404.

Fix

Switch Vite to a relative base (base: './'). Every generated URL now resolves against the file that references it:

  • CSS fonts → /llm/assets/*.woff2
  • lazy route chunks → /llm/assets/*.js
  • index.html's now-relative entry refs resolve via the <base href> serveIndex already injects on every response (middleware.BaseURL is never empty), so this works for both proxied and root deployments.

The public /favicon.svg (referenced absolutely in the source index.html) is still covered by the existing path-absolute rewrite in app.go.

Verification

npm run build output confirms the emitted paths are now relative:

  • index.html: src="./assets/index-*.js", href="./assets/index-*.css"
  • built CSS: url(./fa-solid-900-*.woff2) (was /assets/...)
  • no "/assets/" absolute references remain in the built JS

The existing reverse-proxy assertions in core/http/app_test.go (<base href> injection; body must not contain ="/assets/ or ="/favicon.svg" under a prefix) continue to hold.


Assisted-by: Claude:opus-4.8 [Claude Code]

…Forwarded-Prefix (#10889)

The Vite build emitted path-absolute asset URLs (base: '/'). index.html
entry scripts and the favicon were rewritten to include the reverse-proxy
prefix in serveIndex, but two reference kinds are not in index.html and so
bypassed that rewrite:

  - CSS `url()` font references (e.g. Font Awesome .woff2), which the browser
    resolves relative to the stylesheet and which `<base href>` never affects
  - lazily-imported route chunks, whose preload base came from the absolute
    Vite base

Under a subpath mount (X-Forwarded-Prefix: /llm/) both were fetched from the
origin root, 404ing — missing-glyph "tofu" icons and broken lazy-loaded pages.

Switch Vite to a relative base ('./') so every generated URL resolves against
the file that references it: CSS fonts and route chunks now load from
`/llm/assets/...`, and index.html's now-relative entry refs resolve via the
`<base href>` serveIndex already injects on every response. Root deployments
are unaffected. The existing path-absolute rewrite in app.go still covers the
public `/favicon.svg`.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude:opus-4.8 [Claude Code]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web UI fonts and lazy-loaded scripts ignore X-Forwarded-Prefix

2 participants