Para aprovechar todas las capas de caché disponibles, tu aplicación debe poder comunicar qué respuestas son cacheables y las condiciones que se deben cumplir para que la respuesta cacheada siga considerándose válida. Esto se consigue añadiendo cabeceras HTTP de caché en la respuesta.
Truco Ten en cuenta que HTTP no es más que el lenguaje (un lenguaje simple de texto) que los clientes web (navegadores, por ejemplo) y los servidores web utilizan para comunicarse entre sí. Cuando hablamos de la caché HTTP, estamos hablando de la parte de ese lenguaje que permite a los clientes y servidores intercambiar información relacionada con la caché.
HTTP especifica las siguientes cuatro cabeceras relacionadas con la caché:
Cache-Control
Expires
ETag
Last-Modified
La cabecera más importante y versátil es la cabecera Cache-Control
, que en realidad permite establecer muchas opciones relacionadas con la caché.
14.3.1. La cabecera Cache-Control
La cabecera Cache-Control
es única porque no sólo permite establecer una opción de configuración de caché sino varias. Cada opción está separada por una coma:
Cache-Control: private, max-age=0, must-revalidate Cache-Control: max-age=3600, must-revalidate
Symfony permite establecer los valores de la cabecera Cache-Control
mediante una interfaz sencilla orientada a objetos:
// ...
use Symfony\Component\HttpFoundation\Response;
$response = new Response();
// indica si la respuesta es pública o privada
$response->setPublic();
$response->setPrivate();
// establece la duración máxima de la caché privada o compartida
$response->setMaxAge(600);
$response->setSharedMaxAge(600);
// establece una directiva Cache-Control concreta
$response->headers->addCacheControlDirective('must-revalidate', true);
14.3.2. Respuestas públicas y privadas
Tanto las gateway cache como las proxy cache se considean cachés compartidas porque el contenido guardado en caché se comparte con más de un usuario. Si por error estas cachés almacenan alguna vez información privada del usuario, se servirá la misma información privada a todos los usuarios. ¡Imagina que la información de tu cuenta se guarda en caché y luego se devuelve a cualquier usuario posterior que solicite la página de su cuenta!
Para resolver esta situación, cada respuesta puede indicar si es pública o privada:
- public: indica que la respuesta se puede guardar en cualquier caché privadas o compartidas.
- private: indica que toda o parte de la respuesta es exclusiva para un solo usuario y no se debe guardar en una caché compartida.
Symfony por defecto considera que todas las respuestas son privadas. Para aprovechar las ventajas de las cachés compartidas (como el proxy inverso de Symfony2), tendrás que indicar explícitamente que la respuesta es pública.
14.3.3. Métodos seguros
La caché HTTP sólo funciona para métodos HTTP seguros (como GET
y HEAD
). Un método seguro es aquél que nunca cambia de estado la aplicación en el servidor al servir la petición (por supuesto sí que puedes guardar información de log, etc.) Esto tiene dos consecuencias que son bastante lógicas:
- Nunca debes cambiar el estado de tu aplicación al responder a una petición
GET
oHEAD
. Incluso si no utilizas una gateway cache, la presencia del proxy cache significa que las peticionesGET
oHEAD
pueden llegar al servidor o no. - No esperes que haya métodos
PUT
,POST
oDELETE
en la caché. Estos métodos están diseñados para utilizarse cuando modificas el estado de tu aplicación (por ejemplo, al borrar una entrada del blog). Si estos métodos se cachearan, el resultado sería que algunas peticiones que modifican el estado de la aplicación nunca llegarían a la aplicación.
14.3.4. Reglas de caché y valores predeterminados
HTTP 1.1 por defecto permite guardar en la caché cualquier recurso a menos que incluya una cabecera Cache-Control
. En la práctica, la mayoría de las cachés no hacen nada cuando las peticiones tienen una cookie, una cabecera de autorización, utilizan un método no seguro (es decir, PUT
, POST
, DELETE
), o cuando las respuestas tienen un código de estado de redirección.
Cuando la aplicación no establece ninguna cabecera Cache-Control
, Symfony2 añade esta cabecera aplicando las siguientes reglas:
- Si no has definido ninguna cabecera relacionada con la caché (
Cache-Control
,Expires
,ETag
oLast-Modified
),Cache-Control
se establece ano-cache
, lo que significa que la respuesta no se guarda en la caché. - Si la cabecera
Cache-Control
está vacía pero utilizas alguna de las otras cabeceras de caché, su valor se establece aprivate, must-revalidate
. - Si al menos una directiva de
Cache-Control
está establecida, y no se han añadido directivaspublic
oprivate
de forma explícita, Symfony2 añade la directivaprivate
automáticamente (excepto cuando utilizass-maxage
).