@@ -10,8 +10,22 @@ const globalCache = new NodeCache({ stdTTL: 3600, checkperiod: 600 });
1010const MAX_RESOURCE_SIZE = 15 * ( 1024 ** 2 ) ; // 15MB
1111var ALLOWED_RESOURCES = [ 'document' , 'stylesheet' , 'image' , 'media' , 'font' , 'other' ] ;
1212const ALLOWED_STATUSES = [ 200 , 201 ] ;
13- const REQUEST_TIMEOUT = 1800000 ;
13+ const REQUEST_TIMEOUT = 180000 ;
1414const MIN_VIEWPORT_HEIGHT = 1080 ;
15+ const MAX_WAIT_FOR_REQUEST_CALL = 30000 ;
16+
17+ const normalizeSameSite = ( value ) => {
18+ if ( ! value ) return 'Lax' ;
19+
20+ const normalized = value . trim ( ) . toLowerCase ( ) ;
21+ const mapping = {
22+ 'lax' : 'Lax' ,
23+ 'strict' : 'Strict' ,
24+ 'none' : 'None'
25+ } ;
26+
27+ return mapping [ normalized ] || value ;
28+ } ;
1529
1630export async function prepareSnapshot ( snapshot : Snapshot , ctx : Context ) : Promise < Record < string , any > > {
1731 let processedOptions : Record < string , any > = { } ;
@@ -269,11 +283,11 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
269283 return false ;
270284 }
271285
272- if ( cookie . sameSite && ! [ 'Strict' , 'Lax' , 'None' ] . includes ( cookie . sameSite ) ) {
286+ const sameSiteValue = normalizeSameSite ( cookie . sameSite ) ;
287+ if ( ! [ 'Strict' , 'Lax' , 'None' ] . includes ( sameSiteValue ) ) {
273288 ctx . log . debug ( `Skipping invalid custom cookie: invalid sameSite value '${ cookie . sameSite } '` ) ;
274289 return false ;
275290 }
276-
277291 return true ;
278292 } ) . map ( cookie => ( {
279293 name : cookie . name ,
@@ -282,7 +296,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
282296 path : cookie . path || '/' ,
283297 httpOnly : cookie . httpOnly || false ,
284298 secure : cookie . secure || false ,
285- sameSite : cookie . sameSite || 'Lax'
299+ sameSite : normalizeSameSite ( cookie . sameSite )
286300 } ) ) ;
287301
288302 if ( validCustomCookies . length > 0 ) {
@@ -311,6 +325,8 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
311325 }
312326 }
313327
328+ const pendingRequests = new Set < string > ( ) ;
329+
314330 // Use route to intercept network requests and discover resources
315331 await page . route ( '**/*' , async ( route , request ) => {
316332 const requestUrl = request . url ( )
@@ -369,8 +385,14 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
369385 body = globalCache . get ( requestUrl ) . body ;
370386 } else {
371387 ctx . log . debug ( `Resource not found in cache or global cache ${ requestUrl } fetching from server` ) ;
388+ if ( ctx . build . checkPendingRequests ) {
389+ pendingRequests . add ( requestUrl ) ;
390+ }
372391 response = await page . request . fetch ( request , requestOptions ) ;
373392 body = await response . body ( ) ;
393+ if ( ctx . build . checkPendingRequests ) {
394+ pendingRequests . delete ( requestUrl ) ;
395+ }
374396 }
375397
376398 // handle response
@@ -398,15 +420,26 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
398420
399421 let responseOfRetry , bodyOfRetry
400422 ctx . log . debug ( `Resource had a disallowed status ${ requestUrl } fetching from server again` ) ;
423+ if ( ctx . build . checkPendingRequests ) {
424+ pendingRequests . add ( requestUrl ) ;
425+ }
401426 responseOfRetry = await page . request . fetch ( request , requestOptions ) ;
402427 bodyOfRetry = await responseOfRetry . body ( ) ;
403-
428+ if ( ctx . build . checkPendingRequests ) {
429+ pendingRequests . delete ( requestUrl ) ;
430+ }
404431 if ( responseOfRetry && responseOfRetry . status ( ) && ALLOWED_STATUSES . includes ( responseOfRetry . status ( ) ) ) {
405432 ctx . log . debug ( `Handling request after retry ${ requestUrl } \n - content-type ${ responseOfRetry . headers ( ) [ 'content-type' ] } ` ) ;
406433 cache [ requestUrl ] = {
407434 body : bodyOfRetry . toString ( 'base64' ) ,
408435 type : responseOfRetry . headers ( ) [ 'content-type' ]
409436 }
437+ if ( ctx . config . useGlobalCache ) {
438+ globalCache . set ( requestUrl , {
439+ body : bodyOfRetry . toString ( 'base64' ) ,
440+ type : responseOfRetry . headers ( ) [ 'content-type' ]
441+ } ) ;
442+ }
410443 route . fulfill ( {
411444 status : responseOfRetry . status ( ) ,
412445 headers : responseOfRetry . headers ( ) ,
@@ -457,6 +490,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
457490 }
458491 }
459492
493+
460494 // Continue the request with the fetched response
461495 route . fulfill ( {
462496 status : response . status ( ) ,
@@ -673,6 +707,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
673707 } catch ( error ) {
674708 ctx . log . debug ( `Network idle failed due to ${ error } ` ) ;
675709 }
710+
676711
677712
678713 if ( ctx . config . allowedAssets && ctx . config . allowedAssets . length ) {
@@ -862,6 +897,28 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
862897 ctx . log . debug ( `Processed options: ${ JSON . stringify ( processedOptions ) } ` ) ;
863898 }
864899
900+ // Wait for pending requests to complete
901+ const checkPending = async ( ) => {
902+ let startTime = Date . now ( ) ;
903+ ctx . log . debug ( `${ pendingRequests . size } Pending requests before wait for ${ snapshot . name } : ${ Array . from ( pendingRequests ) } ` ) ;
904+ while ( pendingRequests . size > 0 ) {
905+ const elapsedTime = Date . now ( ) - startTime ;
906+ if ( elapsedTime >= MAX_WAIT_FOR_REQUEST_CALL ) {
907+ ctx . log . debug ( `Timeout reached (${ MAX_WAIT_FOR_REQUEST_CALL / 1000 } s). Stopping wait for pending requests.` ) ;
908+ ctx . log . debug ( `${ pendingRequests . size } Pending requests after wait for ${ snapshot . name } : ${ Array . from ( pendingRequests ) } ` ) ;
909+ break ;
910+ }
911+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
912+ }
913+ if ( pendingRequests . size === 0 ) {
914+ ctx . log . debug ( `No pending requests for ${ snapshot . name } .` ) ;
915+ }
916+ } ;
917+
918+ if ( ctx . build . checkPendingRequests ) {
919+ await checkPending ( ) ;
920+ }
921+
865922 // Validate and report CSS injection after selector processing
866923 if ( processedOptions . customCSS ) {
867924 try {
0 commit comments