Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion functions/_middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@
// inline script into every page on the zone and copies the nonce from script-src onto
// it, so the script runs without 'unsafe-inline'. Our own scripts load from /assets/,
// and the one-line inline "js" class script is allowed by its hash in _headers.
export async function onRequest({ next }) {
//
// Links pasted from chat apps and AI answers often carry Markdown or punctuation stuck
// to the end ("/**", "/privacy)."). A 404 whose path ends in that junk redirects to the
// path without it; whatever is left is served or 404s as usual, so a page that exists is
// never redirected and the clean path cannot loop.
const JUNK = /(?:[*_)\].,;:!'"`>]|%2A|%29|%5D|%22|%27|%60|%3E)+$/i;
export const tidyPath = (p) => { const t = p.replace(JUNK, ""); return t !== p ? (t || "/") : null; };

export async function onRequest({ request, next }) {
const res = await next();
if (res.status === 404) {
const url = new URL(request.url);
const tidy = tidyPath(url.pathname);
if (tidy) return Response.redirect(new URL(tidy + url.search, url).toString(), 301);
}
const csp = res.headers.get("Content-Security-Policy");
if (!csp || !(res.headers.get("Content-Type") || "").includes("text/html")) return res;
const bytes = crypto.getRandomValues(new Uint8Array(16));
Expand Down
Loading