images htaccess for expires equiv control content cache http caching http-headers browser-cache

htaccess - http cache



¿Qué es Cache-Control: privado? (4)

Cuando visito chesseng.herokuapp.com recibo un encabezado de respuesta que se parece a

Cache-Control:private Connection:keep-alive Content-Encoding:gzip Content-Type:text/css Date:Tue, 16 Oct 2012 06:37:53 GMT Last-Modified:Tue, 16 Oct 2012 03:13:38 GMT Status:200 OK transfer-encoding:chunked Vary:Accept-Encoding X-Rack-Cache:miss

y luego actualizo la página y obtengo

Cache-Control:private Connection:keep-alive Date:Tue, 16 Oct 2012 06:20:49 GMT Status:304 Not Modified X-Rack-Cache:miss

así que parece que el almacenamiento en caché está funcionando. Si eso funciona para el almacenamiento en caché, entonces ¿cuál es el punto de Expira y Cache-Control: max-age . Para aumentar la confusión, cuando pruebo la página en https://developers.google.com/speed/pagespeed/insights/ , me dice "Aproveche el almacenamiento en caché del navegador".


El campo Expira el encabezado de entidad proporciona la fecha / hora después de la cual la respuesta se considera obsoleta. El campo Cache-control: maxage proporciona el valor de antigüedad (en segundos) más grande que la respuesta considerada obsoleta.

A pesar de que el campo de encabezado anterior proporciona un mecanismo al cliente para decidir si se envía una solicitud al servidor. En algunas condiciones, el cliente envía una solicitud para cortar y el valor de edad de la respuesta es más grande que el valor de maxage, dosis que significa que el servidor necesita enviar el recurso al cliente. Tal vez el recurso nunca cambió.

Para resolver este problema, HTTP1.1 da la última cabecera modificada. El servidor da la última fecha de modificación de la respuesta al cliente. Cuando el cliente necesita este recurso, enviará If-Modified-Since head field al servidor. Si esta fecha es anterior a la fecha de modificación del recurso, el servidor enviará el recurso al cliente y dará el código 200. De lo contrario, devolverá el código 304 al cliente y esto significa que el cliente puede usar el recurso que guardó en caché.


Para responder a su pregunta sobre por qué funciona el almacenamiento en caché, aunque el servidor web no haya incluido los encabezados:

  • Vence: [a date]
  • Cache-Control: max-age = [seconds]

El servidor solicitó gentilmente a los proxies intermedios que no almacenaran en caché el contenido (es decir, el elemento solo se debe almacenar en caché en un caché privado , es decir, solo en su máquina local):

  • Cache-Control: privado

Pero el servidor olvidó incluir cualquier tipo de pistas de almacenamiento en caché:

  • olvidaron incluir Expires , por lo que el navegador sabe usar la copia en caché hasta esa fecha
  • se les olvidó incluir Max-Age , por lo que el navegador sabe por cuánto tiempo es bueno el elemento almacenado en caché
  • se les olvidó incluir E-Tag , por lo que el navegador puede hacer una solicitud condicional

Pero incluyeron una fecha de Última modificación en la respuesta:

Last-Modified: Tue, 16 Oct 2012 03:13:38 GMT

Como el navegador conoce la fecha en que se modificó el archivo, puede realizar una "solicitud condicional" . Le pedirá al servidor el archivo, pero le pedirá al servidor que solo envíe el archivo si se ha modificado desde 2012/10/16 3:13:38:

GET / HTTP/1.1 If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT

El servidor recibe la solicitud, se da cuenta de que el cliente ya tiene la versión más reciente. En lugar de enviar al cliente 200 OK , seguido por el contenido de la página, en su lugar le dice que su versión en caché es buena:

304 Not Modified

Su navegador tuvo que sufrir el retraso de enviar una solicitud al servidor y esperar una respuesta, pero sí tuvo que volver a descargar el contenido estático.

¿Por qué Max-Age ? ¿Por qué expira ?

Porque Last-Modified apesta.

No todo en el servidor tiene una fecha asociada. Si estoy construyendo una página sobre la marcha, no hay una fecha asociada a ella, es ahora . Pero estoy perfectamente dispuesto a dejar que el usuario guarde en caché la página de inicio durante 15 segundos:

200 OK Cache-Control: max-age=15

Si el usuario martilla F5 , seguirá obteniendo la versión en caché durante 15 segundos. Si se trata de un proxy corporativo, entonces todos los 67198 usuarios que accedan a la misma página en la misma ventana de 15 segundos obtendrán los mismos contenidos, todos servidos desde el caché cercano. Ganancia de rendimiento para todos.

La virtud de agregar Cache-Control: max-age es que el navegador ni siquiera tiene que realizar una solicitud condicional .

  • si especificó Last-Modified , el navegador debe realizar una solicitud If-Modified-Since y esperar una respuesta 304 Not Modified
  • si especificó max-age , el navegador ni siquiera tendrá que sufrir el viaje de ida y vuelta de la red; el contenido saldrá directamente de los cachés

La diferencia entre "Cache-Control: max-age" y "Expira"

Expires es un equivalente heredado del moderno (c. 1998) Cache-Control: max-age encabezado Cache-Control: max-age :

  • Expires : especifica una fecha (yuck)
  • max-age : especifica segundos (bondad)
  • Y si ambos están especificados, entonces el navegador usa max-age :

    200 OK Cache-Control: max-age=60 Expires: 20180403T192837

Cualquier sitio web escrito después de 1998 ya no debería usar Expires y, en su lugar, usar max-age .

¿Qué es ETag?

ETag es similar a Last-Modified , excepto que no tiene que ser una fecha, solo tiene que ser algo .

Si estoy sacando una lista de productos de una base de datos, el servidor puede enviar la última rowversion la rowversion como un ETag, en lugar de una fecha:

200 OK ETag: "247986"

Mi ETag puede ser el hash SHA1 de un recurso estático (por ejemplo, imagen, js, css, fuente), o de la página renderizada en caché (es decir, esto es lo que hace el wiki de Mozilla MDN; ellos tienen el marcado final):

200 OK ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Y exactamente como en el caso de una solicitud condicional basada en Last-Modified :

GET / HTTP/1.1 If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT 304 Not Modified

Puedo realizar una solicitud condicional basada en ETag:

GET / HTTP/1.1 If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4" 304 Not Modified

Un ETag es superior a Last-Modified porque funciona para cosas además de archivos , o cosas que tienen una noción de fecha . Simplemente es


RFC 2616, sección 14.9.1 :

Indica que todo o parte del mensaje de respuesta está destinado a un único usuario y NO DEBE ser almacenado en caché por un caché compartido ... Un caché privado (no compartido) PUEDE almacenar en caché la respuesta.

Los navegadores podrían usar esta información. Por supuesto, el "usuario" actual puede significar muchas cosas: usuario del sistema operativo, un usuario del navegador (por ejemplo, perfiles de Chrome), etc. No está especificado.

Para mí, un ejemplo más concreto de Cache-Control: private es que los servidores proxy (que generalmente tienen muchos usuarios) no lo almacenarán en caché. Está destinado para el usuario final y nadie más.

FYI, el RFC deja en claro que esto no proporciona seguridad. Se trata de mostrar el contenido correcto, no asegurar el contenido.

Este uso de la palabra privado solo controla dónde se puede almacenar la respuesta en la memoria caché y no puede garantizar la privacidad del contenido del mensaje.


Cache-Control: private

Indica que todo o parte del mensaje de respuesta está destinado a un único usuario y NO DEBE ser almacenado en caché por un caché compartido, como un servidor proxy.

De RFC2616 sección 14.9.1