theseus/serveBns: translate the gateway's <base> instead of stripping it

Before: Theseus stripped the gateway's `<base href="/bns/<name>/…">` tag
entirely. The browser fell back to the request URL's directory as the
implicit base, so bns://pithos.sia/HouseMusic/house-music loaded the
SPA-fallback root HTML with assets resolved against
bns://pithos.sia/HouseMusic/ — one folder too deep. The Pithos logo
and every other assets/* link 404d. The symptom was a correctly
served root page with a broken image where the logo belongs.

After: rewrite the tag to bns://<name>/… so the browser honours the
base the gateway chose. On an SPA fallback the gateway already serves
the root's `<base href="/bns/<name>/">` (public-gateway.mjs Oct-25 fix),
and now Theseus propagates that intent — assets resolve from the site
root under the bns:// origin. On the common case the base matches the
request path and the behaviour is unchanged.
This commit is contained in:
Hermes Dev 2026-11-04 13:35:12 +02:00
parent f54f711463
commit 0cff98872a

15
main.js
View file

@ -2746,8 +2746,17 @@ async function serveBns(request) {
? up.contentType : guessType(reqPath === "/" ? "index.html" : reqPath);
let body = up.buffer;
if (ct.includes("text/html")) {
// Strip the gateway's path-form <base href="/bns/<name>/"> so assets
// resolve against the bns:// origin, not back through the relay.
// Translate the gateway's path-form <base href="/bns/<name>/…"> to
// a bns://<name>/… base so assets resolve against the bns:// origin.
// Previously we stripped the tag entirely, which worked when the
// gateway's base matched the request path, but broke on any SPA
// fallback: hitting bns://pithos.sia/HouseMusic/house-music served
// the site's root index with <base href="/bns/pithos.sia/">, and
// stripping that let the browser use bns://pithos.sia/HouseMusic/
// as the implicit base — so `assets/logo.svg` on the root page
// resolved one folder too deep and 404d. Keeping the gateway's
// base (translated to bns://) honours the gateway's SPA fix for
// Theseus too.
// Also strip the gateway's relay chrome (banner + chip + their boot
// script) in case an older gateway, a misconfigured deployment, or
// a cached edge missed the x-bns-policy signal and injected it
@ -2757,7 +2766,7 @@ async function serveBns(request) {
// for exactly this kind of surgical removal.
body = Buffer.from(
body.toString("utf8")
.replace(/<base\s+href="\/bns\/[^"]*">/i, "")
.replace(/<base\s+href="\/bns\/([^"]*)">/i, (_, tail) => `<base href="bns://${tail}">`)
.replace(/<!--nav-relay-banner-start-->[\s\S]*?<!--nav-relay-banner-end-->/gi, "")
.replace(/<!--nav-relay-chip-start-->[\s\S]*?<!--nav-relay-chip-end-->/gi, "")
.replace(/<!--nav-relay-script-start-->[\s\S]*?<!--nav-relay-script-end-->/gi, ""),