Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 60885d2

Browse filesBrowse files
authored
feat: cache 404s indefinitely for bot probes (opennextjs#2668)
* feat: cache 404s indefinitely for bot probes * test: update unit tests * chore: refactor to clean up function signature with object parameterisation
1 parent 0ab5748 commit 60885d2
Copy full SHA for 60885d2

File tree

Expand file treeCollapse file tree

4 files changed

+121
-85
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+121
-85
lines changed

‎src/run/handlers/server.ts

Copy file name to clipboardExpand all lines: src/run/handlers/server.ts
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export default async (request: Request, context: FutureContext) => {
112112

113113
await adjustDateHeader({ headers: response.headers, request, span, tracer, requestContext })
114114

115-
setCacheControlHeaders(response.headers, request, requestContext)
115+
setCacheControlHeaders(response, request, requestContext)
116116
setCacheTagsHeaders(response.headers, requestContext)
117117
setVaryHeaders(response.headers, request, nextConfig)
118118
setCacheStatusHeader(response.headers)

‎src/run/headers.test.ts

Copy file name to clipboardExpand all lines: src/run/headers.test.ts
+105-83Lines changed: 105 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -199,43 +199,43 @@ describe('headers', () => {
199199
const givenHeaders = {
200200
'cdn-cache-control': 'public, max-age=0, must-revalidate',
201201
}
202-
const headers = new Headers(givenHeaders)
203202
const request = new Request(defaultUrl)
204-
vi.spyOn(headers, 'set')
203+
const response = new Response(null, { headers: givenHeaders })
204+
vi.spyOn(response.headers, 'set')
205205

206206
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
207-
setCacheControlHeaders(headers, request, ctx)
207+
setCacheControlHeaders(response, request, ctx)
208208

209-
expect(headers.set).toHaveBeenCalledTimes(0)
209+
expect(response.headers.set).toHaveBeenCalledTimes(0)
210210
})
211211

212212
test('should not set any headers if "netlify-cdn-cache-control" is present', () => {
213213
const givenHeaders = {
214214
'netlify-cdn-cache-control': 'public, max-age=0, must-revalidate',
215215
}
216-
const headers = new Headers(givenHeaders)
217216
const request = new Request(defaultUrl)
218-
vi.spyOn(headers, 'set')
217+
const response = new Response(null, { headers: givenHeaders })
218+
vi.spyOn(response.headers, 'set')
219219

220220
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
221-
setCacheControlHeaders(headers, request, ctx)
221+
setCacheControlHeaders(response, request, ctx)
222222

223-
expect(headers.set).toHaveBeenCalledTimes(0)
223+
expect(response.headers.set).toHaveBeenCalledTimes(0)
224224
})
225225

226226
test('should mark content as stale if "{netlify-,}cdn-cache-control" is not present and "x-nextjs-cache" is "STALE" (GET)', () => {
227227
const givenHeaders = {
228228
'x-nextjs-cache': 'STALE',
229229
}
230-
const headers = new Headers(givenHeaders)
231230
const request = new Request(defaultUrl)
232-
vi.spyOn(headers, 'set')
231+
const response = new Response(null, { headers: givenHeaders })
232+
vi.spyOn(response.headers, 'set')
233233

234234
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
235-
setCacheControlHeaders(headers, request, ctx)
235+
setCacheControlHeaders(response, request, ctx)
236236

237-
expect(headers.set).toHaveBeenCalledTimes(1)
238-
expect(headers.set).toHaveBeenNthCalledWith(
237+
expect(response.headers.set).toHaveBeenCalledTimes(1)
238+
expect(response.headers.set).toHaveBeenNthCalledWith(
239239
1,
240240
'netlify-cdn-cache-control',
241241
'public, max-age=0, must-revalidate, durable',
@@ -246,107 +246,129 @@ describe('headers', () => {
246246
const givenHeaders = {
247247
'x-nextjs-cache': 'STALE',
248248
}
249-
const headers = new Headers(givenHeaders)
250249
const request = new Request(defaultUrl)
251-
vi.spyOn(headers, 'set')
250+
const response = new Response(null, { headers: givenHeaders })
251+
vi.spyOn(response.headers, 'set')
252252

253253
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
254-
setCacheControlHeaders(headers, request, ctx)
254+
setCacheControlHeaders(response, request, ctx)
255255

256-
expect(headers.set).toHaveBeenCalledTimes(1)
257-
expect(headers.set).toHaveBeenNthCalledWith(
256+
expect(response.headers.set).toHaveBeenCalledTimes(1)
257+
expect(response.headers.set).toHaveBeenNthCalledWith(
258258
1,
259259
'netlify-cdn-cache-control',
260260
'public, max-age=0, must-revalidate, durable',
261261
)
262262
})
263263

264264
test('should set durable SWC=1yr with 1yr TTL if "{netlify-,}cdn-cache-control" is not present and `revalidate` is `false` (HEAD)', () => {
265-
const headers = new Headers()
266265
const request = new Request(defaultUrl, { method: 'HEAD' })
267-
vi.spyOn(headers, 'set')
266+
const response = new Response()
267+
vi.spyOn(response.headers, 'set')
268268

269269
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
270-
setCacheControlHeaders(headers, request, ctx)
270+
setCacheControlHeaders(response, request, ctx)
271271

272-
expect(headers.set).toHaveBeenCalledTimes(1)
273-
expect(headers.set).toHaveBeenNthCalledWith(
272+
expect(response.headers.set).toHaveBeenCalledTimes(1)
273+
expect(response.headers.set).toHaveBeenNthCalledWith(
274274
1,
275275
'netlify-cdn-cache-control',
276276
's-maxage=31536000, stale-while-revalidate=31536000, durable',
277277
)
278278
})
279279

280280
test('should set durable SWC=1yr with given TTL if "{netlify-,}cdn-cache-control" is not present and `revalidate` is a number (GET)', () => {
281-
const headers = new Headers()
282281
const request = new Request(defaultUrl)
283-
vi.spyOn(headers, 'set')
282+
const response = new Response()
283+
vi.spyOn(response.headers, 'set')
284284

285285
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: 7200 }
286-
setCacheControlHeaders(headers, request, ctx)
286+
setCacheControlHeaders(response, request, ctx)
287287

288-
expect(headers.set).toHaveBeenCalledTimes(1)
289-
expect(headers.set).toHaveBeenNthCalledWith(
288+
expect(response.headers.set).toHaveBeenCalledTimes(1)
289+
expect(response.headers.set).toHaveBeenNthCalledWith(
290290
1,
291291
'netlify-cdn-cache-control',
292292
's-maxage=7200, stale-while-revalidate=31536000, durable',
293293
)
294294
})
295295

296296
test('should set durable SWC=1yr with 1yr TTL if "{netlify-,}cdn-cache-control" is not present and `revalidate` is a number (HEAD)', () => {
297-
const headers = new Headers()
298297
const request = new Request(defaultUrl, { method: 'HEAD' })
299-
vi.spyOn(headers, 'set')
298+
const response = new Response()
299+
vi.spyOn(response.headers, 'set')
300300

301301
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: 7200 }
302-
setCacheControlHeaders(headers, request, ctx)
302+
setCacheControlHeaders(response, request, ctx)
303303

304-
expect(headers.set).toHaveBeenCalledTimes(1)
305-
expect(headers.set).toHaveBeenNthCalledWith(
304+
expect(response.headers.set).toHaveBeenCalledTimes(1)
305+
expect(response.headers.set).toHaveBeenNthCalledWith(
306306
1,
307307
'netlify-cdn-cache-control',
308308
's-maxage=7200, stale-while-revalidate=31536000, durable',
309309
)
310310
})
311311

312312
test('should not set any headers on POST request', () => {
313-
const headers = new Headers()
314313
const request = new Request(defaultUrl, { method: 'POST' })
315-
vi.spyOn(headers, 'set')
314+
const response = new Response()
315+
vi.spyOn(response.headers, 'set')
316316

317317
const ctx: RequestContext = { ...createRequestContext(), routeHandlerRevalidate: false }
318-
setCacheControlHeaders(headers, request, ctx)
318+
setCacheControlHeaders(response, request, ctx)
319319

320-
expect(headers.set).toHaveBeenCalledTimes(0)
320+
expect(response.headers.set).toHaveBeenCalledTimes(0)
321321
})
322322
})
323323

324324
test('should not set any headers if "cache-control" is not set and "requestContext.usedFsRead" is not truthy', () => {
325-
const headers = new Headers()
326325
const request = new Request(defaultUrl)
327-
vi.spyOn(headers, 'set')
326+
const response = new Response()
327+
vi.spyOn(response.headers, 'set')
328328

329-
setCacheControlHeaders(headers, request, createRequestContext())
329+
setCacheControlHeaders(response, request, createRequestContext())
330330

331-
expect(headers.set).toHaveBeenCalledTimes(0)
331+
expect(response.headers.set).toHaveBeenCalledTimes(0)
332332
})
333333

334334
test('should set permanent, durable "netlify-cdn-cache-control" if "cache-control" is not set and "requestContext.usedFsRead" is truthy', () => {
335-
const headers = new Headers()
336335
const request = new Request(defaultUrl)
337-
vi.spyOn(headers, 'set')
336+
const response = new Response()
337+
vi.spyOn(response.headers, 'set')
338+
339+
const requestContext = createRequestContext()
340+
requestContext.usedFsRead = true
341+
342+
setCacheControlHeaders(response, request, requestContext)
343+
344+
expect(response.headers.set).toHaveBeenNthCalledWith(
345+
1,
346+
'cache-control',
347+
'public, max-age=0, must-revalidate',
348+
)
349+
expect(response.headers.set).toHaveBeenNthCalledWith(
350+
2,
351+
'netlify-cdn-cache-control',
352+
'max-age=31536000, durable',
353+
)
354+
})
355+
356+
test('should set permanent, durable "netlify-cdn-cache-control" if 404 response for URl ending in .php', () => {
357+
const request = new Request(`${defaultUrl}/admin.php`)
358+
const response = new Response(null, { status: 404 })
359+
vi.spyOn(response.headers, 'set')
338360

339361
const requestContext = createRequestContext()
340362
requestContext.usedFsRead = true
341363

342-
setCacheControlHeaders(headers, request, requestContext, true)
364+
setCacheControlHeaders(response, request, requestContext)
343365

344-
expect(headers.set).toHaveBeenNthCalledWith(
366+
expect(response.headers.set).toHaveBeenNthCalledWith(
345367
1,
346368
'cache-control',
347369
'public, max-age=0, must-revalidate',
348370
)
349-
expect(headers.set).toHaveBeenNthCalledWith(
371+
expect(response.headers.set).toHaveBeenNthCalledWith(
350372
2,
351373
'netlify-cdn-cache-control',
352374
'max-age=31536000, durable',
@@ -358,45 +380,45 @@ describe('headers', () => {
358380
'cache-control': 'public, max-age=0, must-revalidate',
359381
'cdn-cache-control': 'public, max-age=0, must-revalidate',
360382
}
361-
const headers = new Headers(givenHeaders)
362383
const request = new Request(defaultUrl)
363-
vi.spyOn(headers, 'set')
384+
const response = new Response(null, { headers: givenHeaders })
385+
vi.spyOn(response.headers, 'set')
364386

365-
setCacheControlHeaders(headers, request, createRequestContext())
387+
setCacheControlHeaders(response, request, createRequestContext())
366388

367-
expect(headers.set).toHaveBeenCalledTimes(0)
389+
expect(response.headers.set).toHaveBeenCalledTimes(0)
368390
})
369391

370392
test('should not set any headers if "cache-control" is set and "netlify-cdn-cache-control" is present', () => {
371393
const givenHeaders = {
372394
'cache-control': 'public, max-age=0, must-revalidate',
373395
'netlify-cdn-cache-control': 'public, max-age=0, must-revalidate',
374396
}
375-
const headers = new Headers(givenHeaders)
376397
const request = new Request(defaultUrl)
377-
vi.spyOn(headers, 'set')
398+
const response = new Response(null, { headers: givenHeaders })
399+
vi.spyOn(response.headers, 'set')
378400

379-
setCacheControlHeaders(headers, request, createRequestContext())
401+
setCacheControlHeaders(response, request, createRequestContext())
380402

381-
expect(headers.set).toHaveBeenCalledTimes(0)
403+
expect(response.headers.set).toHaveBeenCalledTimes(0)
382404
})
383405

384406
test('should set expected headers if "cache-control" is set and "cdn-cache-control" and "netlify-cdn-cache-control" are not present (GET request)', () => {
385407
const givenHeaders = {
386408
'cache-control': 'public, max-age=0, must-revalidate',
387409
}
388-
const headers = new Headers(givenHeaders)
389410
const request = new Request(defaultUrl)
390-
vi.spyOn(headers, 'set')
411+
const response = new Response(null, { headers: givenHeaders })
412+
vi.spyOn(response.headers, 'set')
391413

392-
setCacheControlHeaders(headers, request, createRequestContext())
414+
setCacheControlHeaders(response, request, createRequestContext())
393415

394-
expect(headers.set).toHaveBeenNthCalledWith(
416+
expect(response.headers.set).toHaveBeenNthCalledWith(
395417
1,
396418
'cache-control',
397419
'public, max-age=0, must-revalidate',
398420
)
399-
expect(headers.set).toHaveBeenNthCalledWith(
421+
expect(response.headers.set).toHaveBeenNthCalledWith(
400422
2,
401423
'netlify-cdn-cache-control',
402424
'public, max-age=0, must-revalidate, durable',
@@ -407,18 +429,18 @@ describe('headers', () => {
407429
const givenHeaders = {
408430
'cache-control': 'public, max-age=0, must-revalidate',
409431
}
410-
const headers = new Headers(givenHeaders)
411432
const request = new Request(defaultUrl, { method: 'HEAD' })
412-
vi.spyOn(headers, 'set')
433+
const response = new Response(null, { headers: givenHeaders })
434+
vi.spyOn(response.headers, 'set')
413435

414-
setCacheControlHeaders(headers, request, createRequestContext())
436+
setCacheControlHeaders(response, request, createRequestContext())
415437

416-
expect(headers.set).toHaveBeenNthCalledWith(
438+
expect(response.headers.set).toHaveBeenNthCalledWith(
417439
1,
418440
'cache-control',
419441
'public, max-age=0, must-revalidate',
420442
)
421-
expect(headers.set).toHaveBeenNthCalledWith(
443+
expect(response.headers.set).toHaveBeenNthCalledWith(
422444
2,
423445
'netlify-cdn-cache-control',
424446
'public, max-age=0, must-revalidate, durable',
@@ -429,27 +451,27 @@ describe('headers', () => {
429451
const givenHeaders = {
430452
'cache-control': 'public, max-age=0, must-revalidate',
431453
}
432-
const headers = new Headers(givenHeaders)
433454
const request = new Request(defaultUrl, { method: 'POST' })
434-
vi.spyOn(headers, 'set')
455+
const response = new Response(null, { headers: givenHeaders })
456+
vi.spyOn(response.headers, 'set')
435457

436-
setCacheControlHeaders(headers, request, createRequestContext())
458+
setCacheControlHeaders(response, request, createRequestContext())
437459

438-
expect(headers.set).toHaveBeenCalledTimes(0)
460+
expect(response.headers.set).toHaveBeenCalledTimes(0)
439461
})
440462

441463
test('should remove "s-maxage" from "cache-control" header', () => {
442464
const givenHeaders = {
443465
'cache-control': 'public, s-maxage=604800',
444466
}
445-
const headers = new Headers(givenHeaders)
446467
const request = new Request(defaultUrl)
447-
vi.spyOn(headers, 'set')
468+
const response = new Response(null, { headers: givenHeaders })
469+
vi.spyOn(response.headers, 'set')
448470

449-
setCacheControlHeaders(headers, request, createRequestContext())
471+
setCacheControlHeaders(response, request, createRequestContext())
450472

451-
expect(headers.set).toHaveBeenNthCalledWith(1, 'cache-control', 'public')
452-
expect(headers.set).toHaveBeenNthCalledWith(
473+
expect(response.headers.set).toHaveBeenNthCalledWith(1, 'cache-control', 'public')
474+
expect(response.headers.set).toHaveBeenNthCalledWith(
453475
2,
454476
'netlify-cdn-cache-control',
455477
'public, s-maxage=604800, durable',
@@ -460,14 +482,14 @@ describe('headers', () => {
460482
const givenHeaders = {
461483
'cache-control': 'max-age=604800, stale-while-revalidate=86400',
462484
}
463-
const headers = new Headers(givenHeaders)
464485
const request = new Request(defaultUrl)
465-
vi.spyOn(headers, 'set')
486+
const response = new Response(null, { headers: givenHeaders })
487+
vi.spyOn(response.headers, 'set')
466488

467-
setCacheControlHeaders(headers, request, createRequestContext())
489+
setCacheControlHeaders(response, request, createRequestContext())
468490

469-
expect(headers.set).toHaveBeenNthCalledWith(1, 'cache-control', 'max-age=604800')
470-
expect(headers.set).toHaveBeenNthCalledWith(
491+
expect(response.headers.set).toHaveBeenNthCalledWith(1, 'cache-control', 'max-age=604800')
492+
expect(response.headers.set).toHaveBeenNthCalledWith(
471493
2,
472494
'netlify-cdn-cache-control',
473495
'max-age=604800, stale-while-revalidate=86400, durable',
@@ -478,18 +500,18 @@ describe('headers', () => {
478500
const givenHeaders = {
479501
'cache-control': 's-maxage=604800, stale-while-revalidate=86400',
480502
}
481-
const headers = new Headers(givenHeaders)
482503
const request = new Request(defaultUrl)
483-
vi.spyOn(headers, 'set')
504+
const response = new Response(null, { headers: givenHeaders })
505+
vi.spyOn(response.headers, 'set')
484506

485-
setCacheControlHeaders(headers, request, createRequestContext())
507+
setCacheControlHeaders(response, request, createRequestContext())
486508

487-
expect(headers.set).toHaveBeenNthCalledWith(
509+
expect(response.headers.set).toHaveBeenNthCalledWith(
488510
1,
489511
'cache-control',
490512
'public, max-age=0, must-revalidate',
491513
)
492-
expect(headers.set).toHaveBeenNthCalledWith(
514+
expect(response.headers.set).toHaveBeenNthCalledWith(
493515
2,
494516
'netlify-cdn-cache-control',
495517
's-maxage=604800, stale-while-revalidate=86400, durable',

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.