@@ -212,6 +212,12 @@ async function runCoordinatedWordPressRequest(request: Request, env: Env, coordi
212212 if ( ! lease . pointer || lease . pointer . revision !== bootstrapped . pointer . revision ) throw new Error ( "Canonical bootstrap promotion was not observed by its next lease." )
213213 cacheRuntime ( lease . pointer , bootstrapped )
214214 }
215+ const cachedPage = route === "wordpress" ? await matchWordPressPageCache ( request , lease . pointer ) : null
216+ if ( cachedPage ) {
217+ await releaseLease ( coordinator , request . url , lease )
218+ finalized = true
219+ return cachedPage
220+ }
215221 runtime = await getRuntime ( env , lease . pointer , new URL ( request . url ) . origin )
216222 const mutatesCanonicalState = isMutation ( request , route )
217223 let response : Response
@@ -236,6 +242,7 @@ async function runCoordinatedWordPressRequest(request: Request, env: Env, coordi
236242 }
237243 finalized = true
238244 if ( mutatesCanonicalState ) await discardRuntime ( runtime )
245+ else if ( route === "wordpress" ) response = await cacheWordPressPage ( request , lease . pointer , response )
239246 return response
240247 } catch ( error ) {
241248 if ( ! finalized ) await abortLease ( coordinator , request . url , lease )
@@ -244,6 +251,54 @@ async function runCoordinatedWordPressRequest(request: Request, env: Env, coordi
244251 }
245252}
246253
254+ function isCacheableWordPressPageRequest ( request : Request ) : boolean {
255+ if ( request . method !== "GET" && request . method !== "HEAD" ) return false
256+ if ( request . headers . has ( "authorization" ) || request . headers . has ( "cookie" ) ) return false
257+ const url = new URL ( request . url )
258+ if ( [ "/wp-admin" , "/wp-login.php" , "/wp-json" ] . some ( ( path ) => url . pathname === path || url . pathname . startsWith ( `${ path } /` ) ) ) return false
259+ return ! url . searchParams . has ( "preview" ) && ! url . searchParams . has ( "rest_route" )
260+ }
261+
262+ async function matchWordPressPageCache ( request : Request , pointer : MarkdownPointer ) : Promise < Response | null > {
263+ if ( ! isCacheableWordPressPageRequest ( request ) ) return null
264+ const cache = typeof caches === "undefined" ? undefined : ( caches as CacheStorage & { default ?: Cache } ) . default
265+ if ( ! cache ) return null
266+ try {
267+ const cached = await cache . match ( wordPressPageCacheKey ( request , pointer ) )
268+ return cached ? pageCacheResponse ( cached , request . method === "HEAD" , "hit" ) : null
269+ } catch {
270+ return null
271+ }
272+ }
273+
274+ async function cacheWordPressPage ( request : Request , pointer : MarkdownPointer , response : Response ) : Promise < Response > {
275+ if ( ! isCacheableWordPressPageRequest ( request ) || response . status !== 200 || ! response . headers . get ( "content-type" ) ?. includes ( "text/html" ) || response . headers . has ( "set-cookie" ) ) return response
276+ if ( request . method === "HEAD" ) return pageCacheResponse ( response , true , "miss" )
277+ const cache = typeof caches === "undefined" ? undefined : ( caches as CacheStorage & { default ?: Cache } ) . default
278+ const cacheable = pageCacheResponse ( response , false , "miss" )
279+ if ( cache ) {
280+ try {
281+ await cache . put ( wordPressPageCacheKey ( request , pointer ) , cacheable . clone ( ) )
282+ } catch {
283+ // Page caching is an optimization; canonical rendering remains authoritative.
284+ }
285+ }
286+ return cacheable
287+ }
288+
289+ function wordPressPageCacheKey ( request : Request , pointer : MarkdownPointer ) : Request {
290+ const url = new URL ( request . url )
291+ url . searchParams . set ( "__wp_codebox_revision" , pointer . revision )
292+ return new Request ( url , { method : "GET" } )
293+ }
294+
295+ function pageCacheResponse ( response : Response , head : boolean , status : "hit" | "miss" ) : Response {
296+ const headers = new Headers ( response . headers )
297+ headers . set ( "cache-control" , "public, max-age=60, s-maxage=31536000" )
298+ headers . set ( "x-wp-codebox-page-cache" , status )
299+ return new Response ( head ? null : response . body , { status : response . status , statusText : response . statusText , headers } )
300+ }
301+
247302function isMutation ( request : Request , route : "wordpress" | "health" | "r2-mutate" ) : boolean {
248303 return route === "r2-mutate" || ! [ "GET" , "HEAD" , "OPTIONS" ] . includes ( request . method )
249304}
0 commit comments