diff --git a/src/gateway/public-gateway.mjs b/src/gateway/public-gateway.mjs index c83eacd..6d7b4b2 100644 --- a/src/gateway/public-gateway.mjs +++ b/src/gateway/public-gateway.mjs @@ -507,19 +507,30 @@ async function serve(res, name, reqPath, baseHref) { const cleanPath = reqPath.slice(1).replace(/\/+$/, ""); // 1) Extensionless-URL support: /tld -> tld.html. Lets sites // publish clean URLs without keeping mirror files around. + // Base injection stays anchored at the directory of reqPath, + // which is correct because tld.html is a flat file. if (!reqPath.endsWith("/")) { 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 + // 2) Directory-index: /docs -> docs/index.html. Redirect to add + // the trailing slash instead of serving in place — otherwise + // the injected stays at the parent directory and any + // relative asset/href inside the served page (e.g. + // ./assets/favicon.svg on /theseus/index.html) resolves to + // the WRONG directory. nginx behaves the same way. 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; } + if (dir.ok) { + res.writeHead(302, { location: `${MOUNT}/${name}${reqPath}/` }); + return res.end(); + } } // 3) SPA root fallback — last resort so client-side routers - // can pick up /katalogos, /anthemus, etc. + // can pick up /katalogos, /anthemus, etc. Base stays at the + // site root, which is what SPAs expect. if (up.status === 404) { const fallbackKey = cleanBase + "index.html"; const fb = await aws.fetch(`${S3_ENDPOINT}/${fallbackKey}`);