| 1 | import { revalidatePath } from "next/cache"; |
| 2 | import { NextResponse } from "next/server"; |
| 3 | |
| 4 | export const dynamic = "force-dynamic"; |
| 5 | |
| 6 | /** |
| 7 | * The uncached half of the feed page's "Try again": the page itself is ISR, |
| 8 | * so its client retry must invalidate the cached entry before refreshing, |
| 9 | * or the click serves the same unavailable record for up to ten minutes. |
| 10 | * Same-origin only: a third-party page must not drive the visitor's |
| 11 | * regeneration. Direct HTTP clients can still revalidate, bounded by the |
| 12 | * same ISR cost as fetching /feed itself; no GitHub token is spent on |
| 13 | * behalf of the caller. |
| 14 | */ |
| 15 | export async function POST(req: Request) { |
| 16 | const site = req.headers.get("sec-fetch-site"); |
| 17 | if (site && site !== "same-origin") { |
| 18 | return NextResponse.json({ error: "cross-site" }, { status: 403 }); |
| 19 | } |
| 20 | if (!site) { |
| 21 | const origin = req.headers.get("origin"); |
| 22 | if (origin && new URL(origin).host !== req.headers.get("host")) { |
| 23 | return NextResponse.json({ error: "cross-site" }, { status: 403 }); |
| 24 | } |
| 25 | } |
| 26 | revalidatePath("/[locale]/feed", "page"); |
| 27 | revalidatePath("/feed", "page"); |
| 28 | return NextResponse.json({ revalidated: true, at: new Date().toISOString() }); |
| 29 | } |
| 30 |