import { timingSafeEqual } from "node:crypto"; /** * Called by the API after content changes: drops all cached pages so the next request * renders fresh HTML. Protected by a shared secret (NUXT_REVALIDATE_SECRET). */ export default defineEventHandler(async (event) => { const expected = useRuntimeConfig().revalidateSecret; const given = getHeader(event, "x-revalidate-secret") ?? ""; if (!expected || !safeEqual(given, expected)) { throw createError({ statusCode: 401, statusMessage: "Unauthorized" }); } // route-rule caches (swr) are stored as cache:nitro:routes:* const storage = useStorage("cache"); const keys = await storage.getKeys("nitro:routes"); await Promise.all(keys.map((k) => storage.removeItem(k))); return { cleared: keys.length }; }); function safeEqual(a: string, b: string) { const ab = Buffer.from(a); const bb = Buffer.from(b); return ab.length === bb.length && timingSafeEqual(ab, bb); }