async function constructHTML(context: RequestContext) {
const { pathname } = new URL(context.request.url);
if (pathname.startsWith("/api/")) return await context.next();
if (
pathname.startsWith("/assets/") ||
["/app.webmanifest", "/favicon.ico", "/robots.txt"].includes(pathname) ||
pathname.startsWith("/files/")
)
return await context.env.ASSETS.fetch(context.request);
return await context.next();
}
async function generateTokenHash(token: string) {
const hash = await crypto.subtle.digest(
"SHA-512",
new TextEncoder().encode(token)
);
return btoa(String.fromCharCode(...new Uint8Array(hash)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
}
async function setAuth(context: RequestContext) {
const cookies = context.request.headers.get("cookie");
if (!cookies) return await context.next();
const cookieList = cookies.split(/; /);
for (const c of cookieList) {
const [name, value] = c.split("=");
if (name !== "_s") continue;
const userData = await context.env.DATA.get(
`auth_${await generateTokenHash(value)}`
);
if (userData) context.data.current_user = JSON.parse(userData);
break;
}
return await context.next();
}
async function setBody(context: RequestContext) {
if (context.request.method === "POST") {
if (context.request.headers.get("content-type") !== "application/json")
return new Response('{"error":"Invalid content-type"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
let body: { [k: string]: any };
try {
body = await context.request.json();
} catch {
return new Response('{"error":"Invalid JSON"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
}
context.data.body = body;
}
return await context.next();
}
async function setHeaders(context: RequestContext) {
const nonce = crypto.randomUUID().replace(/-/g, "");
context.data.nonce = nonce;
const response = await context.next();
const rtvValues = [
"Aldaria",
"Altadena",
"DEMA",
"Dragonborn",
"Hollywood",
"Parkway East",
"Parkway North",
"Parkway West",
"Tokyo",
"Wintervale",
];
response.headers.set(
"RTV",
rtvValues[Math.round(Math.random() * (rtvValues.length - 1))]
);
response.headers.set("X-XSS-Protection", "1; mode=block");
const policies = {
"connect-src": ["https://*.ingest.sentry.io", "'self'"],
"default-src": ["'self'"],
"frame-src": ["https://challenges.cloudflare.com"],
"img-src": [
"https://cdn.discordapp.com/avatars/*",
"https://tr.rbxcdn.com",
"'self'",
],
"media-src": ["https://mediaproxy.carcrushers.cc"],
"script-src": ["https://challenges.cloudflare.com", "'self'"],
"style-src": [`nonce-${nonce}`, "'self'"],
};
const directives = [];
for (const [k, v] of Object.entries(policies))
directives.push(`${k} ${v.join(" ")}`);
response.headers.set("Content-Security-Policy", directives.join("; "));
return response;
}
export const onRequest = [setAuth, constructHTML, setBody, setHeaders];