From 7434be0d7094fbaf5abb47bc493e95e6516c3f1a Mon Sep 17 00:00:00 2001 From: TianKai Ma Date: Sun, 26 Jul 2026 02:06:53 +0800 Subject: [PATCH 1/2] fix(catalog): let the CDN cache anonymous catalog pages Anonymous catalog HTML fell through to the blanket no-store default, so every crawler hit paid for a full SSR render. Emit the existing PUBLIC/PRIVATE_LOCALE_CATALOG_HEADERS based on the request auth signal instead: anonymous GETs become briefly CDN-cacheable while authenticated renders stay private and uncacheable. Closes #654 --- src/hooks.server.ts | 38 ++++++- tests/unit/catalog-cache-control.test.ts | 127 +++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 tests/unit/catalog-cache-control.test.ts diff --git a/src/hooks.server.ts b/src/hooks.server.ts index ed4cf451d..871e0acbd 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -32,6 +32,10 @@ import { OAUTH_DEVICE_AUTHORIZATION_ENDPOINT_PATH, OAUTH_TOKEN_ENDPOINT_PATH, } from "@/lib/oauth/constants"; +import { + PRIVATE_LOCALE_CATALOG_HEADERS, + PUBLIC_LOCALE_CATALOG_HEADERS, +} from "@/lib/public-cache-control"; import { buildContentSecurityPolicy, createScriptNonce, @@ -110,6 +114,35 @@ function isHtmlResponse(response: Response) { return response.headers.get("content-type")?.includes("text/html"); } +function isCatalogPageRequest(event: Parameters[0]["event"]) { + return ( + event.request.method === "GET" && + (event.url.pathname === "/catalog" || + event.url.pathname.startsWith("/catalog/")) + ); +} + +// Catalog pages render identical content for every anonymous viewer, so let +// the CDN cache them briefly instead of re-running SSR for every crawler hit. +// Requests carrying an auth signal stay private/no-store so personalized +// renders can never be cached. +function applyCatalogCacheControl( + headers: Headers, + input: { hasAuthSignal: boolean; isCatalogPage: boolean }, +) { + if (!input.isCatalogPage) { + headers.set("Cache-Control", "no-store"); + return; + } + + const catalogHeaders = input.hasAuthSignal + ? PRIVATE_LOCALE_CATALOG_HEADERS + : PUBLIC_LOCALE_CATALOG_HEADERS; + for (const [name, value] of Object.entries(catalogHeaders)) { + headers.set(name, value); + } +} + function addScriptNonce(html: string, nonce: string) { return html.replace(/]*\bnonce=)/g, `