Skip to content

Commit

Permalink
feat(404): apply smart redirects, but don't send 404 checkpoint if a …
Browse files Browse the repository at this point in the history
…redirect has been found
  • Loading branch information
trieloff committed Oct 14, 2024
1 parent 6fe592c commit a2eacf2
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
</script>
<script type="module">
import { sampleRUM } from '/scripts/lib-franklin.js';
import { applyRedirects } from '/scripts/redirects.js';
await applyRedirects();
sampleRUM('404', { source: document.referrer });
</script>
<link rel="stylesheet" href="/styles/styles.css">
Expand Down
62 changes: 62 additions & 0 deletions scripts/redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function globToRegex(glob) {
return new RegExp(`^${glob.replace(/\*/g, '(.*)').replace(/\?/g, '(.)').replace(/\//g, '\\/')}$`);
}

export function activateRedirects(data) {
return data.map((o) => Object.entries(o)
.reduce((acc, [k, v]) => {
if (k.toLowerCase() === 'from') {
acc.from = globToRegex(v);
} else if (k.toLowerCase() === 'to') {
acc.to = (...replacements) => {
replacements.shift();
const result = v.replace(/(\$\d+|\*)/g, (matched) => {
if (matched.startsWith('$')) {
return replacements[matched.slice(1)];
}
if (matched === '*') {
return replacements.shift();
}
return matched;
});
return result;
};
} else if (k.toLowerCase() === 'start') {
acc.start = new Date(
Date.UTC(1899, 11, 30, 0, 0, 0)
+ (v - Math.floor(v)) * 86400000 + Math.floor(v) * 86400000,
);
}
return acc;
}, {}));
}
export async function fetchRedirects(path = '/smart-redirects.json') {
const response = await fetch(path);
const redirects = await response.json();
if (redirects.data) {
return activateRedirects(redirects.data);
}
return [];
}

export async function applyRedirects(
redirects = fetchRedirects(),
path = window.location.pathname,
) {
const redirect = (await redirects)
.filter((r) => typeof r.start === 'undefined' || r.start.getTime() <= Date.now())
.find((r) => r.from.test(path));
if (redirect) {
const target = redirect.to(path, ...redirect.from.exec(path).slice(1));
const currentUrl = new URL(window.location.href);
const targetURL = new URL(target, currentUrl.origin);
// Copy all URL parameters from currentUrl to targetURL
currentUrl.searchParams.forEach((value, key) => {
targetURL.searchParams.set(key, value);
});

targetURL.searchParams.set('redirect_from', path);
window.location.replace(targetURL.toString());
}
return path;
}

0 comments on commit a2eacf2

Please sign in to comment.