http - control - Cómo prevenir la solicitud que devuelve 304
html cache-control (4)
¿Cuándo un navegador NO hace una solicitud al servidor de un archivo?
En otras palabras, tengo un archivo JavaScript siendo servido. Su encabezado de respuesta HTTP tiene un ETag
, Cache-Control: public
y Expires: Tue, 19 Jan 2038 03:14:07 GMT
.
El servidor devuelve un 304
después de que el caché del navegador haya sido cebado.
Mi pregunta es, ¿por qué el navegador incluso está consultando con el servidor y obteniendo un 304
en primer lugar? No quiero que el navegador pregunte si hay una nueva versión; debería cargarse directamente desde el caché del navegador sin verificar las modificaciones con el servidor que sirve el script.
¿Qué combinación de encabezados de respuesta HTTP logra esto?
En primer lugar, la especificación HTTP relevante es RFC 7234 . Si miras la especificación, observarás dos cosas:
- La especificación nunca requiere , bajo ninguna circunstancia, que una memoria caché sirva una versión en caché del contenido sin revalidar. Hay muchos lugares donde la especificación señala que una memoria caché NO DEBE utilizar el contenido almacenado en caché para satisfacer una solicitud, pero ninguno en absoluto cuando INDICA que DEBE hacerlo o que NO DEBE volver a validar. Por lo tanto, los proveedores de navegadores siempre son libres de revalidar si así lo desean.
En segundo lugar, no estás haciendo nada mal de tu parte. Los navegadores son libres de guardar en caché las respuestas y usar esas respuestas en caché dados los encabezados que estás devolviendo. El punto clave está en la Sección 4 , donde se observa que una de las condiciones para atender una respuesta en caché es que la respuesta es:
fresco (ver Sección 4.2), o
permitido ser servido rancio (ver Sección 4.2.4), o
validado con éxito (ver Sección 4.3).
Dado que está escupiendo un encabezado
Expires
que está lejos en el futuro, y ese punto en el futuro aún no se ha alcanzado, la respuesta es ''nueva'' y, por lo tanto, no es necesaria la revalidación. Así que estás haciendo todo lo que la especificación sugiere que debes ser de tu parte. (Aunque utilizaCache-Control: max-age=foo
es una forma más moderna de establecer los tiempos de caducidad de la caché que usar el encabezadoExpires:
:).
Entonces, si desea cambiar el comportamiento de almacenamiento en caché de los navegadores, no tiene suerte.
Sin embargo , las cosas pueden no ser tan malas como crees. Probablemente solo esté viendo una solicitud y 304 porque está actualizando la página en su navegador cuando realiza la prueba. Los navegadores manejan los recursos almacenados en caché de forma diferente según cómo se haya activado la solicitud.
Ejecuté una prueba simple en la que creé una página HTML que contenía una etiqueta <script>
apuntando a un archivo JS, una etiqueta <img>
apuntando a una imagen y una etiqueta <link>
apuntando a una hoja de estilo CSS. Todos estos archivos fueron alojados en un servidor Apache configurado para servirlos con:
- un encabezado E-Tag,
- una fecha de Última modificación,
- un
Cache-Control: max-age=172800
encabezado
Naturalmente, todos los recursos fueron servidos con 200 códigos en la carga de la primera página. A partir de entonces, al realizar pruebas en las instalaciones de Chrome o Firefox con la configuración predeterminada, observé que:
- Si actualiza la página mediante la tecla F5 o el botón Actualizar , la página y todos los recursos se revalidan (es decir, se realiza una solicitud al servidor para cada recurso y se devuelve un 304).
- Si regresa a la página a través de un enlace o ingresa la URL en la barra de URL en una nueva pestaña, no se realiza ninguna revalidación (es decir, no se realizan solicitudes).
- En Chrome, si actualiza la página seleccionando la barra de URL y presionando Enter, la página se revalida pero no otros recursos. En Firefox, ni la página ni los recursos se revalidan.
Esta página indica que Internet Explorer tiene el mismo comportamiento:
Hay una serie de situaciones en las que Internet Explorer necesita comprobar si una entrada almacenada en caché es válida:
- La entrada en caché no tiene fecha de vencimiento y se está accediendo al contenido por primera vez en una sesión del navegador
- La entrada almacenada en caché tiene una fecha de caducidad pero ha expirado
- El usuario ha solicitado una actualización de página haciendo clic en el botón Actualizar o presionando F5
En otras palabras, normalmente solo verá estas solicitudes de revalidación si el usuario actualiza la página de manera explícita. A menos que tenga algunos requisitos muy particulares sobre cómo desea que se comporte el caché del navegador, este comportamiento parece perfectamente razonable.
Google y Mozilla tienen algo de documentación sobre el almacenamiento en caché HTTP (no encuentro nada equivalente en MSDN o en el sitio de desarrolladores de Apple), pero ninguno sugiere la existencia de encabezados de almacenamiento en caché específicos del proveedor que puedan usarse para modificar las reglas que utiliza el navegador para elegir cuándo revalidar. Lo que quieres hacer simplemente no es posible.
Si realmente necesita más control sobre este comportamiento, puede buscar en la memoria caché de aplicaciones HTML5 o desplegar su propia lógica de almacenamiento en caché utilizando almacenamiento local HTML5, como basket.js hace basket.js .
Existe una regla que establece que un encabezado Expires más de un año en el futuro viola el HTTP 1.1 RFC .
Por lo tanto, el encabezado de respuesta HTTP aquí no es válido ( Expires: Tue, 19 Jan 2038 03:14:07 GMT
). ¡Reparar esto puede resolver el problema!
Si está en mi bote y tiene una aplicación angular implementada en IIS, asegúrese de que su web.config esté configurado para reescribir correctamente la url, de la siguiente manera:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Detailed" />
<rewrite>
<rules>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Específicamente, tenga en cuenta el valor de url en
<action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />
Expires:
o Cache-Control: max-age=
debería funcionar. ¿Has confirmado en los registros del servidor que el navegador está realmente haciendo llamadas de red? Descubrí que Firebug, por ejemplo, tiene una salida confusa que sugiere que estás haciendo llamadas remotas cuando en realidad estás presionando el caché.