Files
tiago 894c9e6ab9 feat: speculative challenges, jwt challenge tokens, standalone
optimizations, format
releases widget@0.1.38; standalone@2.2.0
2026-03-01 13:20:48 +00:00

63 lines
1.8 KiB
HTML
Vendored

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script>
window.CAP_CUSTOM_FETCH = async (url, options) => {
if (url === "/api/challenge") {
return new Response(
JSON.stringify({
challenge: Array.from({ length: 5 }, () => [
Array.from(window.crypto.getRandomValues(new Uint8Array(Math.ceil(32 / 2))))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("")
.slice(0, 32),
Array.from(window.crypto.getRandomValues(new Uint8Array(Math.ceil(2 / 2))))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("")
.slice(0, 4),
]),
token: "",
expires: Date.now() + 6000 * 100,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}
if (url === "/api/redeem") {
return new Response(
JSON.stringify({
success: true,
token: "ok",
expires: Date.now() + 1000 * 60,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}
return await window.fetch(url, options);
};
</script>
</head>
<body>
<script src="/widget.js"></script>
<cap-widget data-cap-api-endpoint="/api/"></cap-widget>
<script>
const widget = document.querySelector("cap-widget");
widget.solve();
widget.addEventListener("solve", function (e) {
fetch(e.detail.token === "ok" ? "/solved" : "/failed");
});
</script>
</body>
</html>