diff --git a/packages/cloudflare/src/cache/kv-data-adapter.runtime.ts b/packages/cloudflare/src/cache/kv-data-adapter.runtime.ts index bf01363b8e..934568e6ad 100644 --- a/packages/cloudflare/src/cache/kv-data-adapter.runtime.ts +++ b/packages/cloudflare/src/cache/kv-data-adapter.runtime.ts @@ -469,6 +469,13 @@ export class KVCacheHandler implements CacheHandler { effectiveRevalidate = data.revalidate; } if (effectiveRevalidate === 0) return Promise.resolve(); + if ( + typeof effectiveRevalidate === "number" && + !Number.isFinite(effectiveRevalidate) && + effectiveRevalidate !== Infinity + ) { + return Promise.resolve(); + } const now = Date.now(); const revalidateAt = @@ -684,7 +691,11 @@ function validateCacheEntry(raw: unknown): KVCacheEntry | null { } if (obj.cacheControl !== undefined) { if (!isUnknownRecord(obj.cacheControl)) return null; - if (typeof obj.cacheControl.revalidate !== "number") return null; + // `null` is the JSON encoding of `Infinity` used by static pages. + if (typeof obj.cacheControl.revalidate !== "number" && obj.cacheControl.revalidate !== null) { + return null; + } + if (obj.cacheControl.revalidate === null) obj.cacheControl.revalidate = Infinity; if (obj.cacheControl.expire !== undefined && typeof obj.cacheControl.expire !== "number") { return null; } diff --git a/tests/kv-cache-handler.test.ts b/tests/kv-cache-handler.test.ts index bbe18fa08e..6b58e97224 100644 --- a/tests/kv-cache-handler.test.ts +++ b/tests/kv-cache-handler.test.ts @@ -639,6 +639,44 @@ describe("KVCacheHandler", () => { expect(hit?.cacheControl).toEqual({ revalidate: 60, expire: 300, stale: 30 }); }); + it("round-trips the Infinity revalidate used by static pages", async () => { + await handler.set( + "static-infinity", + { + kind: "APP_PAGE", + html: "