Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

cache interceptor ignores request "Cache-Control: max-age=0" (falsy check) — breaks fetch(url, {cache:'no-cache'}) through composed cache dispatchers

Abierto
#5,504 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
74/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Tranquilo
Stack tecnológico
javascript, nodejs

Línea de trabajo

Comienza en lib/interceptor/cache.js, cerca de la comprobación de request max-age, e inspecciona lib/web/fetch/index.js para ver el comportamiento del modo no-cache. Ejecuta la reproducción de composed-dispatcher proporcionada contra el interceptor de caché. Se considera terminado cuando max-age=0 realiza la validación, incluido el manejo condicional de 304, y una respuesta actualizada tras superar un max-age distinto de cero se almacena para la siguiente solicitud.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Bug Description

lib/interceptor/cache.js checks the request max-age directive with

if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) {

(currently interceptor/cache.js:283). For max-age=0 the parsed value 0 is falsy, so the
directive is ignored entirely and a cached response is served with no origin contact.
RFC 9111 §5.2.1.1: the client has indicated it is unwilling to accept any response whose age
exceeds 0s — the cache MUST NOT reuse the stored response without successful validation.

This also breaks fetch(url, { cache: 'no-cache' }) when the dispatcher is composed with the
cache interceptor: per the fetch spec, that mode appends Cache-Control: max-age=0
(lib/web/fetch/index.js, "cache mode is no-cache" step), which the interceptor then drops on the
floor — so the one documented way to force revalidation through fetch does nothing.
(Related umbrella: #3847.)

Secondary issue in the same block: when a nonzero request max-age is exceeded, the bypass
dispatches without a CacheHandler (return dispatch(opts, handler), interceptor/cache.js:286),
so the fresh 200 fetched because of the bypass is never stored — the very next plain request has
to revalidate or refetch again.

Reproducible By

const { Agent, interceptors, cacheStores, request } = require('undici')
const http = require('node:http')

let hits = 0
const server = http.createServer((req, res) => {
  hits++
  res.writeHead(200, { 'cache-control': 'max-age=60', etag: '"v1"' })
  res.end('hello')
}).listen(0, async () => {
  const origin = `http://localhost:${server.address().port}`
  const d = new Agent().compose(interceptors.cache({ store: new cacheStores.MemoryCacheStore() }))
  await (await request(origin, { dispatcher: d })).body.text()                      // hits=1, stored
  await (await request(origin, { dispatcher: d, headers: { 'cache-control': 'max-age=0' } })).body.text()
  console.log(hits) // observed: 1 — expected: 2 (validation required by RFC 9111 §5.2.1.1)
  server.close()
})

Observed on undici 8.7.0 (and current main), Node 22.

Expected Behavior

max-age=0 (and generally age >= max-age) should force the revalidation path (send
If-None-Match/If-Modified-Since, serve cached body on 304), same as the request no-cache
directive already does — not a silent cache hit, and not an un-stored full bypass.

Suggested fix sketch: treat request-max-age exceedance as staleness (feed it into the existing
isStale/revalidation flow) instead of the current falsy-guarded bypass, and wrap the bypass
dispatch in new CacheHandler(...) so the response updates the store.


Found during an agent-assisted HTTP-caching review for @jeswr; every claim reproduced on undici 8.6.0 (repo) and 8.7.0 (npm) on Node 22.23.1. Fix PR to follow.

Lenguaje dominante
JavaScript
Estrellas
7.7k
Forks
905
Merge medio
2 d 15 h
PR fusionados (30 d)
97

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de nodejs/undici

Todos los issues de nodejs/undici

Issues similares

Más issues de JavaScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.