2011-06-14 15 views
19

Tengo problemas para formular encabezados de caché HTTP para la siguiente situación.HTTP: combinando caché de caducidad y validación

Nuestro servidor tiene grandes datos que cambian tal vez un par de veces a la semana. Quiero que los navegadores guarden en caché esta información. Además, quiero minimizar la latencia de los accesos condicionales ya que la red no es confiable.

El comportamiento extremo que busco es la siguiente:

  1. cliente solicita un recurso que no ha visto antes.
  2. El servidor responde con el recurso junto con ETag y max-age (24 horas).
  3. Hasta que hayan transcurrido 24 horas, el cliente utilizará el recurso en caché.
  4. Después de la fecha de vencimiento, el cliente realizará una solicitud de validación (If-None-Match: [etag])
  5. Si los recursos no ha cambiado:
    • servidor responde con 304 Not Modified
    • cliente es informado de alguna manera que el recurso existente tiene un nuevo vencimiento fecha de 24 horas a partir de ahora
    • volver al paso 3

Reducido a su esencia ... ¿puede una respuesta 304 contener un nuevo max-age? ¿O es el original max-age honrado para solicitudes posteriores?

Respuesta

29

Sí, una respuesta 304 puede contener un nuevo max-age (o ETag u otros encabezados de respuesta para el caso).

Hice un experimento usando Firefox 4 para probar si se respeta el máximo original o el nuevo, y la respuesta fue que el nuevo max-age es respetado, por lo que debería poder implementar lo que desea hacer.

Es importante recordar que max-age es relativo a la cabecera Date respuesta, no Last-Modified, por lo que cada vez que el servidor establece una directiva max-age de 24 horas, que está diciendo "24 horas a partir de este momento". Por lo tanto, suponiendo que eso es lo que desea, no tendrá que cambiar su max-age en absoluto, simplemente siempre devuelva 86400.

De todos modos, aquí hay un resumen y descarga de mi experimento. Básicamente, toco una URL de prueba que establece un ETag y establece max-age en 120 segundos. En consecuencia, el servidor devuelve la página con estas cabeceras de respuesta:

HTTP/1.1 200 OK 
Date: Tue, 14 Jun 2011 23:48:51 GMT 
Cache-Control: max-age=120 
Etag: "901ea3d0ac9303ae4855a09676f96701" 
Last-Modified: Mon, 13 Jun 2011 22:20:03 GMT 

entonces repiten golpear "entrar" en la barra de direcciones para cargar la página (pero no forzar una recarga dura). No hubo tráfico de red, ya que Firefox recargó la página varias veces desde el caché. Luego, después de 120 segundos, la próxima vez que presiono Enter, Firefox envió un GET condicional al servidor, como era de esperar. La solicitud y la respuesta del servidor fueron:

GET /example HTTP/1.1 
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT 
If-None-Match: "901ea3d0ac9303ae4855a09676f96701" 

HTTP/1.1 304 Not Modified 
Date: Tue, 14 Jun 2011 23:50:54 GMT 
Etag: "901ea3d0ac9303ae4855a09676f96701" 
Cache-Control: max-age=240 

Tenga en cuenta que en la respuesta 304, que he tenido el cambio de servidor max-age de 120 segundos a 240.

Entonces, la gran pregunta es, ¿qué pasaría después de 120 segundos? ¿Firefox respetaría el nuevo max-age y continuaría cargando la página desde el caché o golpearía el servidor? La respuesta es que continuó carga de la página de la memoria caché, y no volvió a solicitud hasta después de que se llegó a 240 segundos:

GET /example HTTP/1.1 
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT 
If-None-Match: "901ea3d0ac9303ae4855a09676f96701" 

HTTP/1.1 304 Not Modified 
Date: Tue, 14 Jun 2011 23:54:56 GMT 
Etag: "901ea3d0ac9303ae4855a09676f96701" 
Cache-Control: max-age=240 

repetí a través de otro de 240 segundo ciclo y las cosas funcionaban como era de esperar. Entonces, con suerte, eso responde la pregunta para ti.

El RFC explica cómo se supone que se deben implementar los cálculos de edad y cómo funcionan los demás parámetros de Cache-Control. No hay garantía de que todos los navegadores y proxy sigan las reglas, pero en este punto HTTP 1.1 es bastante antiguo y uno esperaría que la mayoría de ellos haga lo mismo que Firefox.

(Nota: Por razones de brevedad en estos ejemplo vertederos, He eliminado cabeceras irrelevantes como anfitrión, conexión /, el contenido de codificación/longitud/tipo de mantenimiento de conexión, de agente de usuario, etc.)

+1

"I luego repite presionando "enter" en la barra de direcciones para cargar la página (pero no forzar una recarga dura). " - ¡Esta fue la información clave que necesitaba para hacer el experimento yo mismo! ¡Gracias por la respuesta bien documentada! – roufamatic

+3

Reprobé lo que describiste con FireFox. Con Chrome, presionar "enter" en la barra de ubicación aún causaba un 304. Encontré que ir a otra página (por ejemplo, google.com) y luego presionar el botón "Atrás" mostraría el comportamiento de la memoria caché según lo deseado. (Curiosamente, si llegué a mi página a través del botón "avanzar" SIEMPRE mostraba el archivo en caché.) – roufamatic

+0

Gracias, eso es una buena información sobre Chrome. Supongo que lo principal que debes hacer si pruebas es intentar simular lo que hagan tus usuarios, sea cual sea la combinación de enlaces que hacen clic, haciendo clic en marcadores (tráfico directo), que puedes estimar a partir de los datos del referer (supongo que estos ambos se cargarían desde el caché válido). Y desglose por navegador. O simplemente confíe en Firefox/Chrome y esté contento de que esté implementando HTTP correctamente de la manera que desee. – joelhardi

Cuestiones relacionadas