@@ -16,6 +16,12 @@ import {
1616 type CdnResponseHeaders ,
1717} from "../packages/vinext/src/shims/cdn-cache.js" ;
1818import { createStaticFileSignal } from "../packages/vinext/src/server/request-pipeline.js" ;
19+ import { createWorkerCacheabilityAdmissionContext } from "../packages/vinext/src/server/cacheability-request.js" ;
20+ import {
21+ CACHEABILITY_REQUEST_STATE ,
22+ type RouteCacheabilityState ,
23+ } from "../packages/vinext/src/shims/cacheability-classification.js" ;
24+ import { runWithExecutionContext } from "../packages/vinext/src/shims/request-context.js" ;
1925
2026afterEach ( ( ) => setCdnCacheAdapter ( new DefaultCdnCacheAdapter ( ) ) ) ;
2127
@@ -94,6 +100,55 @@ describe("finalizeAppRscResponse — config header application", () => {
94100 expect ( response . headers . get ( "x-example-edge-policy" ) ) . toBeNull ( ) ;
95101 } ) ;
96102
103+ it ( "records the adapter's provisional policy before config headers run" , async ( ) => {
104+ const adapter : CdnCacheAdapter = {
105+ ownsBackgroundRevalidation : true ,
106+ async get ( ) {
107+ return null ;
108+ } ,
109+ async set ( ) { } ,
110+ buildResponseHeaders ( { cacheControl } ) : CdnResponseHeaders {
111+ return { "Cache-Control" : cacheControl || "no-store" } ;
112+ } ,
113+ hasExplicitNonCacheableResponsePolicy ( headers ) {
114+ return headers . get ( "Cache-Control" ) ?. includes ( "no-store" ) === true ;
115+ } ,
116+ async revalidateTag ( ) { } ,
117+ } ;
118+ setCdnCacheAdapter ( adapter ) ;
119+ const request = new Request ( "http://example.com/about" , {
120+ headers : { Accept : "text/html" } ,
121+ } ) ;
122+ const executionContext = createWorkerCacheabilityAdmissionContext (
123+ { waitUntil ( ) { } } ,
124+ request ,
125+ null ,
126+ "build-a" ,
127+ true ,
128+ ) ;
129+
130+ await runWithExecutionContext ( executionContext , ( ) =>
131+ finalizeAppRscResponse ( new Response ( "body" ) , request , {
132+ basePath : "" ,
133+ configHeaders : [
134+ {
135+ source : "/about" ,
136+ headers : [ { key : "Cache-Control" , value : "private, no-store" } ] ,
137+ } ,
138+ ] ,
139+ i18nConfig : null ,
140+ requestContext : makeRequestContext ( ) ,
141+ } ) ,
142+ ) ;
143+
144+ const state = Reflect . get (
145+ executionContext ,
146+ CACHEABILITY_REQUEST_STATE ,
147+ ) as RouteCacheabilityState ;
148+ expect ( state . frameworkResponseCachePolicy ) . toEqual ( { "cache-control" : "no-store" } ) ;
149+ expect ( state . finalResponseVetoReason ) . toContain ( "next.config headers set a non-cacheable" ) ;
150+ } ) ;
151+
97152 it ( "applies a matching config header to a 200 response" , async ( ) => {
98153 // Behavior: /about page response gets x-added header from next.config.js headers[].
99154 // Regression: expected null to be "config"
0 commit comments