Refactor GrampsWeb subpath handling: move all patching to nginx sub_filter (STI-98)
Some checks are pending
CI/CD Pipeline / test (push) Waiting to run
CI/CD Pipeline / deploy (push) Blocked by required conditions
Code Quality / quality (push) Waiting to run

Replace fragile container-side sed/JS patching with comprehensive nginx sub_filter
rules. The container now only handles admin user creation on startup. All SPA route
prefixing is done in nginx via a History API interceptor injected into HTML responses.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
SysAdmin Agent
2026-04-03 21:19:11 +00:00
parent 2a3577baff
commit b79de1d9dd
4 changed files with 65 additions and 50 deletions

View File

@@ -83,8 +83,10 @@ server {
}
# GrampsWeb Ahnenforschung
# GrampsWeb SPA has <base href="/"> hardcoded — sub_filter rewrites it
# so asset URLs resolve under /ahnenforschung/ instead of /
# All path rewriting happens here via sub_filter — no container-side patching needed.
# GrampsWeb SPA uses Vaadin Router with absolute paths; the injected History API
# interceptor ensures pushState/replaceState calls get the /ahnenforschung/ prefix,
# while <base href> lets the router strip it back for route matching.
location /ahnenforschung/ {
proxy_pass http://127.0.0.1:8090/;
proxy_set_header Host $host;
@@ -93,12 +95,39 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Script-Name /ahnenforschung;
# Rewrite <base href="/"> to <base href="/ahnenforschung/">
# so the SPA loads JS/CSS from the correct subpath
# Disable upstream compression so sub_filter can operate on response bodies
proxy_set_header Accept-Encoding "";
# Apply sub_filter to HTML, JS, and CSS responses
sub_filter_types text/html application/javascript text/css;
sub_filter_once off;
# HTML: set <base href> so the SPA router knows its prefix
sub_filter '<base href="/">' '<base href="/ahnenforschung/">';
sub_filter_once on;
sub_filter_types text/html;
# HTML: inject History API interceptor — ensures pushState/replaceState
# always include the /ahnenforschung/ prefix for correct SPA routing on reload
sub_filter '</head>' '<script>!function(){var p="/ahnenforschung",o=history.pushState,r=history.replaceState;function w(u){return"string"==typeof u&&"/"===u[0]&&0!==u.indexOf(p)?p+u:u}history.pushState=function(s,t,u){return o.call(this,s,t,w(u))},history.replaceState=function(s,t,u){return r.call(this,s,t,w(u))}}();</script></head>';
# JS: rewrite hardcoded absolute API/resource paths
sub_filter '"/api/' '"/ahnenforschung/api/';
sub_filter '`/api/' '`/ahnenforschung/api/';
sub_filter '"/lang/' '"/ahnenforschung/lang/';
sub_filter '`/lang/' '`/ahnenforschung/lang/';
sub_filter '"/fonts/' '"/ahnenforschung/fonts/';
sub_filter '`/fonts/' '`/ahnenforschung/fonts/';
sub_filter '"/assets/' '"/ahnenforschung/assets/';
sub_filter '`/assets/' '`/ahnenforschung/assets/';
# JS: rewrite root redirects
sub_filter 'location.href="/"' 'location.href="/ahnenforschung/"';
sub_filter 'document.location.href="/"' 'document.location.href="/ahnenforschung/"';
# JS: service worker route handling
sub_filter 'createHandlerBoundToURL("/index.html")' 'createHandlerBoundToURL("/ahnenforschung/index.html")';
# CSS: fix relative font paths (served from subpath, ../fonts/ won't resolve)
sub_filter '../fonts/' 'fonts/';
# WebSocket support
proxy_http_version 1.1;