fix(routing): enforce slashless public URLs
This commit is contained in:
5 files changed
+87
-5
No files matched your search
@@ -24,6 +24,18 @@ function formActions(html) {
|
||||
match[1].match(/\baction=["']([^"']*)["']/i)?.[1] ?? null);
|
||||
}
|
||||
|
||||
function rootRelativeUrls(html) {
|
||||
const urls = [];
|
||||
for (const match of html.matchAll(/\b(?:href|action)=["']([^"']+)["']/gi)) urls.push(match[1]);
|
||||
return urls;
|
||||
}
|
||||
|
||||
function hasTerminalSlash(url) {
|
||||
if (!url.startsWith('/') || url.startsWith('//')) return false;
|
||||
const pathname = url.split(/[?#]/, 1)[0];
|
||||
return pathname !== '/' && pathname.endsWith('/');
|
||||
}
|
||||
|
||||
function unsafeSignals(html) {
|
||||
const signals = [];
|
||||
if (/<iframe\b[^>]*\bsrc=["'][^"']*jotform/i.test(html)) signals.push('active Jotform iframe');
|
||||
@@ -52,10 +64,12 @@ export async function verifyArtifact(root, mode = 'staging') {
|
||||
const title = html.match(/<title>([^<]*)<\/title>/i)?.[1]?.trim() ?? '';
|
||||
const actions = formActions(html);
|
||||
const nonSearchActions = actions.filter((action) => action && action !== '/search');
|
||||
const trailingSlashUrls = rootRelativeUrls(html).filter(hasTerminalSlash);
|
||||
const signals = unsafeSignals(html);
|
||||
if (!title) errors.push(`${route}: missing title`);
|
||||
if (!canonical) errors.push(`${route}: missing canonical`);
|
||||
if (!robots) errors.push(`${route}: missing robots directive`);
|
||||
if (trailingSlashUrls.length) errors.push(`${route}: root-relative URL(s) end in a slash: ${trailingSlashUrls.join(', ')}`);
|
||||
if (mode === 'staging' && robots !== 'noindex,nofollow') errors.push(`${route}: staging robots is ${robots ?? 'missing'}`);
|
||||
if (canonical) {
|
||||
const prior = canonicalMap.get(canonical);
|
||||
|
||||
Reference in new issue
Block a user