返回 CodeWhale
route.ts
根目录 / web / app / api / facts / v1 / [channel] / route.ts
1 import { getEnv } from "@/lib/kv";
2 import { isValidChannel, resolveCloudFacts, responseFor } from "@/lib/cloud-facts";
3
4 /**
5 * Public, credential-free cloud facts envelope for one channel (facts/v1).
6 *
7 * GET /api/facts/v1/<channel> → signed envelope JSON (strong ETag, CDN-cacheable)
8 * HEAD /api/facts/v1/<channel> → headers only
9 *
10 * The envelope is verified server-side before it is served; clients verify it
11 * again against the keys pinned in the binary. No cookies, no Vary, no query
12 * parameters: the response is identical for every caller so any CDN in front
13 * (Cloudflare today, Vercel if the host moves) can cache it.
14 */
15 export const dynamic = "force-dynamic";
16 export const revalidate = 0;
17
18 async function handle(req: Request, ctx: { params: Promise<{ channel: string }> }, method: "GET" | "HEAD"): Promise<Response> {
19 const { channel } = await ctx.params;
20 if (!isValidChannel(channel)) {
21 return responseFor({ kind: "none" }, req, channel, method);
22 }
23 const env = await getEnv();
24 const result = await resolveCloudFacts(channel, env);
25 return responseFor(result, req, channel, method);
26 }
27
28 export async function GET(req: Request, ctx: { params: Promise<{ channel: string }> }) {
29 return handle(req, ctx, "GET");
30 }
31
32 export async function HEAD(req: Request, ctx: { params: Promise<{ channel: string }> }) {
33 return handle(req, ctx, "HEAD");
34 }
35
35 lines TYPESCRIPT