# Cabeceras de estado de la caché

> Lee X-Cache-Status, la cabecera estándar Cache-Status y Age para saber si el borde sirvió una respuesta desde la caché y, si no, por qué.

Cada respuesta de un nombre con la caché activada lleva dos cabeceras que dicen qué hizo la caché, y `Age` cuando sirvió una copia guardada.

```sh
curl -sI https://www.example.com/app.css | grep -i -E 'x-cache-status|cache-status|age'
```

## X-Cache-Status

Usa los valores que quizá conozcas de otras CDN:

| Valor | Significado |
|---|---|
| `HIT` | Servida desde la caché del borde. |
| `MISS` | Elegible pero aún no estaba en caché: se pidió al origen y se guardó si se podía. |
| `EXPIRED` | La copia guardada había caducado; llegó una nueva del origen. |
| `REVALIDATED` | La copia guardada había caducado; el origen la confirmó con un `304`. |
| `UPDATING` | Copia caducada servida mientras se actualiza en segundo plano (stale-while-revalidate). |
| `STALE` | Copia caducada servida porque el origen falló. |
| `BYPASS` | Elegible, pero la respuesta no se podía guardar (por ejemplo `Set-Cookie` o `private`). |
| `DYNAMIC` | No elegible: no se consultó la caché (HTML sin regla, una regla `bypass`, un `POST`…). |

Si no hay cabecera, la caché no intervino: la respuesta vino del WAF, de un reto, de la puerta de acceso o de una redirección del borde.

## Cache-Status

La cabecera estándar del RFC 9211, con el motivo en `detail`:

```http
Cache-Status: OpenWAF; hit
Cache-Status: OpenWAF; fwd=uri-miss; stored
Cache-Status: OpenWAF; fwd=stale; fwd-status=304
Cache-Status: OpenWAF; fwd=bypass; detail=set-cookie
```

| `detail` | Con | Significado |
|---|---|---|
| `stored` | `MISS`, `EXPIRED` | La respuesta se guardó. |
| `not-stored`, `busy` | `MISS` | Se podía guardar, pero esta copia no se guardó. |
| `set-cookie` | `BYPASS` | La respuesta pone una cookie. |
| `private`, `no-store` | `BYPASS` | La `Cache-Control` del origen prohíbe guardarla. |
| `auth` | `BYPASS` | La petición traía `Authorization` y la respuesta no permitía compartirla. |
| `vary` | `BYPASS`, `DYNAMIC` | Un `Vary` no admitido, o la petición traía una cabecera del `vary_bypass_if_present` de una regla. |
| `size` | `BYPASS` | Mayor que el tamaño máximo de objeto. |
| `deception` | `BYPASS` | La bloqueó la armadura anti-engaño. |
| `status` | `BYPASS` | El código de estado no se puede cachear. |
| `uncacheable` | `BYPASS` | Sin información de frescura y sin TTL por defecto aplicable (por ejemplo, HTML elegible por una regla sin TTL). |
| `personal` | `BYPASS` | Un documento personal pedido con cookies o `Authorization`, sin frescura explícita. |
| `rule` | `BYPASS`, `DYNAMIC` | Un TTL por estado de `-1` en una regla, o una regla `bypass`. |
| `invalid`, `encoding` | `BYPASS` | Una `Cache-Control` no válida, o una codificación distinta de gzip o Brotli. |
| `extension` | `DYNAMIC` | La extensión no está en la lista por defecto y ninguna regla hace elegible la ruta. |
| `disabled`, `dev-mode` | `DYNAMIC` | La caché está desactivada o el modo desarrollo está activado. |
| `method`, `upgrade`, `body` | `DYNAMIC` | No es `GET`/`HEAD`, es un upgrade a WebSocket o la petición trae cuerpo. |
| `path`, `query`, `key` | `DYNAMIC` | Una ruta ambigua, una consulta con el nivel *Sin cadena de consulta* o una clave demasiado larga. |

## Age

Se envía en `HIT`, `STALE`, `UPDATING` y `REVALIDATED`: los segundos desde que el objeto se guardó o se revalidó por última vez. Un `Age` que envíe tu origen en una respuesta que no se cacheó se reenvía tal cual.

## Cabeceras que quita el borde

`OpenWAF-CDN-Cache-Control` y `Cache-Tag` son solo para el borde y se quitan antes de que la respuesta llegue al visitante. Un `X-Cache-Status` que envíe tu origen se sustituye.
