feat: Implement HTTP caching for API routes and add a dashboard sidebar with city grouping and state persistence.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
function normalizeTag(tag: string) {
|
||||
return tag.trim().replace(/^W\//i, "");
|
||||
}
|
||||
|
||||
function ifNoneMatchHit(ifNoneMatch: string | null, etag: string) {
|
||||
if (!ifNoneMatch) return false;
|
||||
const target = normalizeTag(etag);
|
||||
return ifNoneMatch
|
||||
.split(",")
|
||||
.map((part) => normalizeTag(part))
|
||||
.some((part) => part === "*" || part === target);
|
||||
}
|
||||
|
||||
function buildEtag(body: string) {
|
||||
const hash = createHash("sha1").update(body).digest("hex");
|
||||
return `"${hash}"`;
|
||||
}
|
||||
|
||||
export function buildCachedJsonResponse(
|
||||
req: NextRequest,
|
||||
payload: unknown,
|
||||
cacheControl: string,
|
||||
) {
|
||||
const body = JSON.stringify(payload);
|
||||
const etag = buildEtag(body);
|
||||
const headers = new Headers({
|
||||
"Cache-Control": cacheControl,
|
||||
ETag: etag,
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
});
|
||||
|
||||
if (ifNoneMatchHit(req.headers.get("if-none-match"), etag)) {
|
||||
return new NextResponse(null, { status: 304, headers });
|
||||
}
|
||||
|
||||
return new NextResponse(body, { status: 200, headers });
|
||||
}
|
||||
Reference in New Issue
Block a user