feat(gateway): clean URLs — serve <path>.html + strip .html from hrefs
Two symmetric changes so a site published as flat .html files (sirius.x
has tld.html, portal.html, market.html, register.html, studio.html)
reads with clean URLs to the visitor.
1. S3 handler fallback order for extensionless requests:
/tld → tld.html (new — first)
/tld → tld/index.html (existing — second)
/... → index.html (existing — SPA last-resort)
Requests with a real file extension (.js, .svg, .json) are never
rescued — those must never be routed by a client-side router and
swallowing them would hide real bugs.
2. transformHtml() gains stripHtmlExt(): rewrites href="foo.html"
(relative) to href="foo", preserving anchor and query. Absolute
URLs (https://silentmode.st/tlds/) are left alone — external
references are none of our business.
Backwards-compatible: existing /bns/<name>/foo.html links still 200.
Verified end-to-end on sirius.x: /tld, /portal, /market, /register,
/studio all serve; assets under js/, assets/ unchanged; direct .html
requests still work.
This commit is contained in:
parent
6ebdb98936
commit
e130596584
1 changed files with 34 additions and 8 deletions
|
|
@ -317,11 +317,27 @@ function rewriteBnsLinks(html) {
|
|||
}
|
||||
);
|
||||
}
|
||||
// Apply both transforms (base first, then link rewrite) — order doesn't
|
||||
// matter because they touch disjoint constructs, but grouping them here
|
||||
// means every text/html response goes through the same path.
|
||||
// Strip `.html` from relative link targets in served HTML — so a link
|
||||
// written as href="tld.html" reads as href="tld" in the browser bar.
|
||||
// Only touches non-absolute URLs (leaves `https://…/x.html` alone —
|
||||
// those are external and often out of our control). Preserves anchor
|
||||
// and query, and skips the ".html" that's part of a filename like
|
||||
// "foo.htmlx" (regex requires end/? / #).
|
||||
function stripHtmlExt(html) {
|
||||
return html.replace(
|
||||
/\b(href\s*=\s*")([^"#?][^"#?]*)\.html(?=["#?])/gi,
|
||||
(m, prefix, path) => {
|
||||
if (/^\s*[a-z][a-z0-9+.-]*:/i.test(path)) return m; // absolute URL — leave alone
|
||||
return prefix + path;
|
||||
}
|
||||
);
|
||||
}
|
||||
// Apply the three transforms (base first, link rewrite, extension strip).
|
||||
// Order doesn't matter across them because they touch disjoint constructs,
|
||||
// but grouping them here means every text/html response goes through the
|
||||
// same path.
|
||||
function transformHtml(html, baseHref) {
|
||||
return rewriteBnsLinks(injectBase(html, baseHref));
|
||||
return stripHtmlExt(rewriteBnsLinks(injectBase(html, baseHref)));
|
||||
}
|
||||
const nx = (h) => `<div style="font:16px system-ui;padding:2rem;color:#333"><h2>NXDOMAIN</h2><p><code>${h}</code> is not registered on the Bitcoin Cash chain.</p></div>`;
|
||||
|
||||
|
|
@ -487,15 +503,25 @@ async function serve(res, name, reqPath, baseHref) {
|
|||
// NOT rescued — those should never be routed by a client-side
|
||||
// router and swallowing them would hide real bugs.
|
||||
if (up.status === 404 && !/\.[a-z0-9]+$/i.test(reqPath) && reqPath !== "/") {
|
||||
// Try directory-index first
|
||||
const cleanBase = base.endsWith("/") ? base : base + "/";
|
||||
const cleanPath = reqPath.slice(1).replace(/\/+$/, "");
|
||||
// 1) Extensionless-URL support: /tld -> tld.html. Lets sites
|
||||
// publish clean URLs without keeping mirror files around.
|
||||
if (!reqPath.endsWith("/")) {
|
||||
const dirKey = (base.endsWith("/") ? base : base + "/") + reqPath.slice(1).replace(/\/+$/, '') + "/index.html";
|
||||
const htmlKey = cleanBase + cleanPath + ".html";
|
||||
const htmlHit = await aws.fetch(`${S3_ENDPOINT}/${htmlKey}`);
|
||||
if (htmlHit.ok) { up = htmlHit; }
|
||||
}
|
||||
// 2) Directory-index: /docs -> docs/index.html
|
||||
if (up.status === 404 && !reqPath.endsWith("/")) {
|
||||
const dirKey = cleanBase + cleanPath + "/index.html";
|
||||
const dir = await aws.fetch(`${S3_ENDPOINT}/${dirKey}`);
|
||||
if (dir.ok) { up = dir; }
|
||||
}
|
||||
// Then SPA root fallback
|
||||
// 3) SPA root fallback — last resort so client-side routers
|
||||
// can pick up /katalogos, /anthemus, etc.
|
||||
if (up.status === 404) {
|
||||
const fallbackKey = (base.endsWith("/") ? base : base + "/") + "index.html";
|
||||
const fallbackKey = cleanBase + "index.html";
|
||||
const fb = await aws.fetch(`${S3_ENDPOINT}/${fallbackKey}`);
|
||||
if (fb.ok) { up = fb; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue