Skip to content

Commit

Permalink
feat(smart-redirects): add smart redirects for (temporary) client-sid…
Browse files Browse the repository at this point in the history
  • Loading branch information
trieloff committed Oct 16, 2024
1 parent 94a0e5c commit fc1262d
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
4 changes: 4 additions & 0 deletions 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<title>404</title>
<meta name="template" content="404"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script type="module">
import { applyRedirects } from '/scripts/redirects.js';
await applyRedirects();
</script>
<script src="/scripts/scripts.js" type="module"></script>
<link rel="icon" href="data:,">
</head>
Expand Down
83 changes: 83 additions & 0 deletions scripts/redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
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) - 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') {
try {
const response = await fetch(path);
const redirects = await response.json();
if (redirects.data) {
return activateRedirects(redirects.data);
}
return [];
} catch (error) {
return [];
}
}

export async function getRedirect(redirects, path, currentURL) {
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 targetURL = new URL(target, currentURL);
// Copy all URL parameters from currentURL to targetURL
currentURL.searchParams.forEach((value, key) => {
targetURL.searchParams.set(key, value);
});

targetURL.searchParams.set('redirect_from', path);
return targetURL.toString();
}
return null;
}

export async function isValidRedirect(url) {
// we try to fetch the URL, if it fails we return false
try {
const response = await fetch(url);
return response.ok && response.status === 200;
} catch (error) {
return false;
}
}

export async function applyRedirects(
redirects = fetchRedirects(),
path = window.location.pathname,
) {
const redirect = await getRedirect(redirects, path, new URL(window.location.href));
if (redirect && await isValidRedirect(redirect)) {
window.location.replace(redirect);
}
return path;
}

0 comments on commit fc1262d

Please sign in to comment.