La caché decide dos veces: primero con la petición (¿es elegible, es decir, se consulta la caché?) y después con la respuesta (¿se puede guardar y durante cuánto tiempo?).
Peticiones elegibles
Una petición solo se busca en la caché si se cumple todo esto. Si no, va directa al origen y se marca como DYNAMIC.
- La caché está activada para el nombre y el modo desarrollo no.
- El método es
GEToHEAD, sin cabeceraUpgrade(WebSocket) y sin cuerpo. - No coincide ninguna regla de caché
bypass. - La extensión de la ruta está en la lista por defecto de abajo, o una regla
cachehace elegible la petición. - La ruta no es ambigua: sin parámetros de ruta con
;, sin/,\, NUL, CR ni LF codificados, sin barra invertida y sin un último segmento que acabe en punto (/x.css.).
La Cache-Control y el Pragma de la propia petición se ignoran, así que un cliente no puede obligar al borde a volver a pedir al origen.
Extensiones por defecto
7z avi avif apk apng bin bmp bz2 class css csv doc docx dmg ejs eot eps exe flac gif gz ico iso jar
jpeg jpg js jxl m4a m4v mid midi mjs mkv mov mp3 mp4 ogg otf pdf pict pls png ppt pptx ps rar svg
svgz swf tar tif tiff ttf wasm webm webmanifest webp woff woff2 xls xlsx zip zstademás de robots.txt. El HTML, el JSON, el XML, txt y los source maps no están en la lista: necesitan una regla cache.
Frescura: cuánto tiempo se guarda una respuesta
El borde toma el TTL de la primera de estas cabeceras que envíe el origen:
OpenWAF-CDN-Cache-Control: un cache-control solo para el borde de OpenWAF, que nunca se reenvía a los navegadores.CDN-Cache-Control(RFC 9213), que se reenvía tal cual.Cache-Control:s-maxagey despuésmax-age.Expires.- Los valores por defecto de abajo, si no hay ninguna de las anteriores.
La Cache-Control siempre llega al navegador tal como la envió el origen, salvo que configures un TTL del navegador.
TTL por defecto
Sin ninguna cabecera de frescura, y solo para la lista de extensiones por defecto:
| Estado | TTL en el borde |
|---|---|
200, 206, 301 | 2 horas |
302, 303 | 20 minutos, solo en peticiones sin Cookie ni Authorization |
404, 410 | 3 minutos |
| Cualquier otro | no se guarda |
Los directorios de build conocidos de los frameworks habituales reciben 7 días en lugar de 2 horas: /_next/static/, /_nuxt/, /_astro/, /_app/immutable/, /build/assets/ y /packs/, salvo los ficheros que cambian a propósito, como version.json, latest.json, sw.js, service-worker, manifest.json, page-data/ y app-data.json.
Una ruta que una regla hace elegible (HTML, JSON…) no recibe TTL por defecto: necesita frescura del origen o un TTL en la regla.
Ningún objeto se conserva más de 30 días.
Respuestas que nunca se guardan
Estas respuestas llegan al visitante sin guardarse y se marcan como BYPASS:
Cache-Control: no-storeoprivate. Conprivate="Set-Cookie", la respuesta se guarda sin esa cabecera.- Una cabecera
Set-Cookie, salvo que una regla fije el TTL del borde (entonces se quitaSet-Cookiede la copia guardada). - Una petición con
Authorizationcuya respuesta no digapublic,s-maxagenimust-revalidate. - Un
Varyque nombre algo distinto deAccept-Encoding,Accept(solo imágenes) uOrigin, incluidosVary: *yVary: Cookie. Consulta Claves de caché. - Un código de estado que no se puede cachear, un cuerpo mayor que el tamaño máximo de objeto (100 MB por defecto) o una codificación distinta de gzip o Brotli.
- Documentos personales: para
pdf,doc(x),xls(x),ppt(x),csv,zip,7z,rar,tarygz, una petición conCookieoAuthorizationsolo se guarda si el origen envió frescura explícita. - Las páginas que genera el propio borde: retos, páginas de bloqueo, la puerta de acceso y las redirecciones.
Armadura anti-engaño de caché
Activada por defecto. Cuando la extensión de la URL promete un tipo pero el origen responde text/html, application/json, application/xhtml+xml o text/plain (salvo robots.txt y .csv), la respuesta no se guarda. Así se corta el ataque clásico en el que /account.php/x.css devuelve una página HTML personal que, si no, se cachearía y se serviría a otros. Se admiten las discrepancias inofensivas, como application/octet-stream o un .jpg servido como image/webp.
Revalidación y contenido caducado
no-cache,max-age=0os-maxage=0conETagoLast-Modified: la respuesta se guarda y se revalida con el origen cada vez que se usa (If-None-Match/If-Modified-Since); un304evita volver a enviar el cuerpo.- Un objeto caducado con validadores se revalida:
REVALIDATEDsi llega un304yEXPIREDsi llega un200nuevo. - Caducado mientras se revalida: con el
stale-while-revalidatedel origen, el objeto caducado se sirve (UPDATING) mientras se actualiza en segundo plano. - Caducado si hay error: cuando el origen falla (error de red, tiempo agotado,
500,502,503,504), se sirve el objeto caducado (STALE) durante elstale-if-errordel origen o, si no lo envía, hasta 24 horas por defecto. must-revalidate,proxy-revalidate,no-cacheys-maxagedesactivan el contenido caducado.
Range, HEAD y fallos simultáneos
- Un
GETcon un únicoRangeque no está en caché pide el objeto entero una sola vez, lo guarda y responde el rango a medida que llega (206), así que los vídeos también se cachean. - Un
HEADse sirve desde la caché si el objeto está; si no, va al origen y no se guarda nada. - Cuando muchos visitantes piden a la vez el mismo objeto que no está en caché, solo una petición va al origen; las demás esperan hasta 5 segundos y se sirven con el resultado.
Compresión
El borde pide al origen br, gzip y guarda una sola copia por URL en la codificación que eligió el origen. Si el navegador de un visitante no acepta esa codificación, recibe la copia descomprimida al vuelo; Vary: Accept-Encoding no divide la caché.