Encabezados para evitar solicitudes 304 / If-modified-since / HEAD

31

¿Qué encabezados debería enviar para detener por completo todas las solicitudes al servidor después de que el contenido se haya almacenado en caché?

Tenemos un servidor de latencia muy alta (Sigh, VMWare), por lo que incluso enviar una HEADsolicitud al servidor tarda + 40ms.

Actualmente estos son los encabezados que se envían / ​​reciben;

Primera solicitud

El cliente envía;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

El servidor responde;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

Por lo tanto, envía un conjunto de encabezados Cache-Controly Expiresa 365 días en el futuro. Desafortunadamente, en la segunda actualización, solicita nuevamente el objeto con un If-Modified-Sinceencabezado.

Segundo requisito

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

Respuesta;

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

Desafortunadamente, debido al software proxy obsoleto tonto que no podemos usar Keep-Alive, o poner cualquier otro servidor / proxy frente a la aplicación. Tampoco podemos mejorar el rendimiento del servidor y reducir la latencia de la red. He estado tratando de averiguar qué encabezados podemos enviar para deshacernos de las solicitudes 301. He intentado usar ETags pero eso no hace ninguna diferencia, todavía envía un If-modified-sinceencabezado. También intenté eliminar el Last-Modifiedencabezado, pero eso solo causa una solicitud GET estándar sin almacenamiento en caché (revisé los registros, el servidor aún recibe solicitudes).

Los clientes son una combinación de Firefox (principalmente), IE 7, 8 y (algunos) 9, Chrome y Safari, pero este comportamiento parece estar apareciendo en todos los navegadores probados.

TL; DR;

Red terrible, ¿qué encabezados debo enviar para decirles a los clientes que nunca envíen If-modified-sincesolicitudes al servidor para validar su caché y que mantengan el contenido en caché hasta que Expiresse cumpla el encabezado?

Probablemente me estoy perdiendo algo obvio, pero todo lo que intento parece dar los mismos resultados.

Tenemos un servidor NGINX sentado frente a nuestro servidor de aplicaciones para que pueda agregar / eliminar los encabezados que desee. Nuestro proxy no es compatible con Keep-Alive y no hay manera de mejorar el rendimiento de la red. Debido al terrible diseño del software, la aplicación web carga +100 recursos en cada carga de página (Sí, el software empresarial es una mierda) con una latencia de ~ 40-50 ms por objeto.

Mancha
fuente
1
Hmm, eso es extraño. El envío de los encabezados de Caducidad y edad máxima debería evitar nuevas solicitudes de la imagen. Editar: por cierto, ¿cuál es el problema con el envío de un JPG text/plain?
DisgruntledGoat
1
@DisgruntledGoat Ahh, has asumido que un archivo .jpg es en realidad una imagen en lugar de un documento de texto. Bienvenido a mi mundo =) (En realidad, es un archivo de texto que contiene 'Hello World' para mis pruebas, el software simplemente renombra todos los archivos secuencialmente IMG_xxxx.jpg independientemente del tipo. ¿Genial, eh?)
Difuminar
¿Qué estabas usando para configurar los encabezados de solicitud http?
barlop

Respuestas:

25

Realmente no puedes controlar qué encabezados deciden enviarte los agentes de usuario. Si el archivo en cuestión está en la memoria caché del navegador y decide que necesita buscar una nueva versión, lo hará. De acuerdo con este artículo , estas son las situaciones que los navegadores solicitarán usando If-Modified-Since:

  • La entrada en caché no tiene fecha de vencimiento y se accede al contenido por primera vez en una sesión de navegador
  • La entrada en caché tiene una fecha de vencimiento pero ha expirado
  • El usuario ha solicitado una actualización de la página haciendo clic en el botón Actualizar o presionando F5

Entonces, si está volviendo a cargar la página para probar su almacenamiento en caché, no funcionará ya que el navegador volverá a solicitar las imágenes. Intente hacer clic en un enlace y luego en otro enlace a la primera página. Si sus usuarios vuelven a cargar páginas regularmente, es posible que deba repensar la estructura de su sitio / aplicación para evitarlo.

Una cosa que puede ayudar es agregar "público" al encabezado de control de caché, es decir Cache-Control: public, max-age=31536000. También supe recientemente que una fecha de vencimiento de más de un año no es válida. Dado que su fecha de vencimiento es exactamente un año, tal vez reducirlo en unos pocos días o semanas garantizaría que el archivo permanezca en la memoria caché del navegador y no se descarte.

Cabra descontento
fuente
Interesante, reduciré los vencimientos a 60 días y agregaré la bandera pública, y veré qué sucede. Esto parecía estar sucediendo en los clics de enlace en lugar de F5 (según Firebug y los registros del servidor)
Difuminar
Técnicamente, la especificación HTTP / 1.1 solo dice que "los servidores NO DEBEN enviar fechas de caducidad más de un año en el futuro" (presumiblemente porque es un tiempo ridículamente largo antes de la caducidad) y que "aproximadamente un año" en el futuro es la caducidad adecuada hora de enviar contenido que nunca se espera que caduque.
Ilmari Karonen
1
Después de jugar un poco, he llegado a la conclusión de que la expiración del 365d no está afectando a nuestros clientes, sin embargo, lo descarté para que sea seguro, parece que Cache-Control: public,...fue la clave de esta situación específica.
Mancha
¿Quieres decir que el encabezado "público" solucionó los viajes de ida y vuelta innecesarios? Lo intenté, pero sin éxito ...
phtrivier
2
En caso de que mi respuesta no lo aclare, volver a cargar la página en su navegador solicitará nuevamente los archivos . Simplemente haga clic en los enlaces para abrir páginas y el navegador usa su caché.
DisgruntledGoat
3

Tuve el mismo problema, y ​​las solicitudes definitivamente están afectando al servidor para que responda con el 304estado: estoy enviando el 304 a través de C # y seguro que afecta al servidor.

Solo me había Cache-Control: privatepuesto. No max-agey no ExpiresFuncionó como se esperaba; golpeo el servidor con el lugar If-Modified-Sincedonde pruebo el valor en comparación con lo que espero y entrego 304con el cuerpo de respuesta vacío; de lo contrario, 200llena el cuerpo de respuesta.

El Expiresencabezado de configuración tuvo los resultados deseados, 200 - (from cache)en el cliente y ninguna solicitud HTTP llegó al servidor.

Pero ... descubrí que configurar AMBOS max-age= y Expirespuede hacer que los navegadores no envíen If-Modified-Sinceencabezado Y que no se almacenen en caché si los valores no coinciden .

Algo a tener en cuenta si tiene problemas de almacenamiento en caché y utilizó los diferentes encabezados en combinación.

Andrew Scott
fuente
1

Un poco fuera de tema pero quizás útil. Otra mejora para sus solicitudes de contenido en caché es almacenar en caché en sessionStorage para que no necesite pedirle al servidor que valide la caché y reciba un 304. Busque, por ejemplo, google, abra la consola y escriba sessionStorage. Verá que están almacenando en caché CSS o DOM con sessionStorage. ofc, no puede usar eso en los antiguos navegadores IE.

Pablo Estornut
fuente
0

Revise su código fuente y asegúrese de que no haya META REFRESH para pasar a otra página. Use algo como sendRedirect en su lugar. En mi configuración, META REFRESH produce 304s en IE, pero no Chrome. sendRedirect no produce esto en ninguno de los navegadores.

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

vs

<% response.sendRedirect("nextpage") %>
Richard Sandoz
fuente