fix(gateway): baseHref per current directory, not per site root

The path-form handler injected `<base href="/bns/<name>/">` on every
page regardless of the sub-path being viewed. That meant a subdirectory
page's relative-parent links resolved wrong: from /bns/theseus.x/extensions/
the page's `<a href="../plug-ins/">` was resolved against the base as
/bns/plug-ins/ — dropping the name, giving a 404.

Compute baseHref from the directory of the current sub-path instead
(everything before the last "/" in rest, defaulting to "/"). Now:

  /bns/theseus.x/                → <base href="/bns/theseus.x/">
  /bns/theseus.x/plug-ins/       → <base href="/bns/theseus.x/plug-ins/">
  /bns/theseus.x/plug-ins/x.html → <base href="/bns/theseus.x/plug-ins/">
  /bns/theseus.x/extensions/     → <base href="/bns/theseus.x/extensions/">

`../plug-ins/` from the extensions page now resolves correctly to
/bns/theseus.x/plug-ins/, and `./` on a subdirectory page resolves to
the subdirectory itself instead of the site root.

Verified end-to-end: clicking Plug-ins from Extensions preserves the
name in the URL. Assets loaded via `../assets/...` from any subdirectory
still resolve correctly (they now go up exactly one level, to the site
root).
This commit is contained in:
Local Dev 2026-09-20 17:31:49 +02:00
parent f49c7c244a
commit 0396988124

View file

@ -1749,7 +1749,15 @@ const server = http.createServer(async (req, res) => {
if (!m) { res.writeHead(400, { "content-type": "text/html" }); return res.end(`usage: ${MOUNT}/<name>.<tld>/`); }
const name = m[1].toLowerCase();
const rest = m[2] || "/";
return serve(res, name, rest, `${MOUNT}/${name}/`);
// baseHref must point at the CURRENT DIRECTORY, not the site root.
// If we injected `<base href="/bns/<name>/">` on every page, then a
// relative link like `../plug-ins/` on a subdirectory page (e.g.
// /bns/theseus.x/extensions/) resolves against the base — landing on
// /bns/plug-ins/, dropping the name. Using the directory of `rest`
// makes `.`, `..`, `foo/`, `../bar/` all resolve as the browser would
// if the site were served from its own origin.
const restDir = rest.replace(/[^/]*$/, "") || "/";
return serve(res, name, rest, `${MOUNT}/${name}${restDir}`);
} catch (e) { res.writeHead(500); res.end("gateway error: " + e.message); }
});
server.listen(PORT, "127.0.0.1", () => console.log(`bns public gateway on 127.0.0.1:${PORT} (path ${MOUNT}, subdomain *.${SUB_BASE})`));