2009-06-15 7 views
79

¿Cuál podría ser la diferencia entre if-modified-since y if-none-match? Tengo la sensación de que if-none-match se usa para los archivos mientras que if-modified-since se usa para las páginas?if-modified-since vs if-none-match

Respuesta

98

En cuanto a las diferencias entre Last-Modified/If-Modified-Since y ETag/If-None-Match:

Ambos pueden ser utilizados indistintamente. Sin embargo, dependiendo del tipo de recurso y cómo se genera en el servidor, una u otra pregunta ("¿esto ha sido modificado desde ...?"/"¿Esto aún coincide con este ETag?") Puede ser más fácil de responder .

Ejemplos:

  • Si usted está sirviendo archivos, utilizando mtime como la fecha del archivo Last-Modified es la solución más simple.
  • Si está sirviendo una página web dinámica construida a partir de una serie de consultas SQL, comprobar si los datos devueltos por cualquiera de esas consultas ha cambiado puede ser poco práctico (a menos que todos ellos tengan algún tipo de columna de "última modificación") . En este caso, usando, p. un hash md5 del contenido de la página como ETag será mucho más fácil.
    OTOH, esto significa que todavía tiene que generar toda la página en el servidor, incluso para un GET condicional. Averiguar qué tiene que entrar exactamente en el ETag (claves primarias, números de revisión, ... etc.) puede ahorrarle mucho tiempo aquí.

Consulte estos enlaces para obtener más detalles sobre el tema:

+0

He enviado al navegador un ETag, pero nunca solicita la misma página con If-None-Match. ¿Cuál puede ser el problema? – Pacerier

+2

@pacerier: no se requiere que los navegadores usen Etag. Entonces podría ser un viejo navegador y simplemente ignorarlo. La otra posibilidad es que se acceda a la entidad con los parámetros url que cambian de llamada a llamada. Si el nombre de la entidad cambia, entonces etag no se usará para diferentes solicitudes. –

+0

@RafaelBaptista Para obtener más información sobre su segunda mitad del comentario, supongamos que tengo esta situación: tengo un servidor de archivos y el servidor admite versiones usando ETags y, por razones de compatibilidad con versiones anteriores, solíamos tener clientes con un parámetro de consulta my_current_version = (versión). Si envío una solicitud HTTP con valores variables para my_current_version, pero también con ETags, ¿qué criterio, como mejor práctica, se priorizará al determinar si se publicará una nueva versión o se devolverá un 304? ¡Gracias! –

22

If-Modified-Since se compara con Last-Modified mientras que If-None-Match se compara con ETag. Ambos Modified-Since y ETag se pueden usar para identificar una variante específica de un recurso.

Pero la comparación de If-Modified-Since a Last-Modified le da la información almacenada en caché si la variante es mayor o nueva mientras que la comparación de If-None-Match a ETag sólo te da la información sobre si ambos son idénticos o no. Además, la mayoría de los generadores ETag incluyen la información del sistema específico inode, por lo que mover un archivo a una unidad diferente también puede cambiar el ETag.

+0

Interesante, pero ¿por qué iba a usar verificaciones "idénticas" sobre las verificaciones de "última modificación"? ¿Cuales son los beneficios? Si tienes un archivo para servir, ¿cuál es una mejor opción? – Tower

+6

Con las computadoras, el tiempo es frágil. Los segundos intercalares, al cambiar entre el horario de ahorro de luz diurna y los relojes inexactos, pueden todos causar una verificación de "última modificación" para devolver el resultado incorrecto. Comparar el contenido en sí (o el hash MD5 del contenido) evita esos problemas. – devdanke

+0

A pesar de que entiendo completamente @devdanke, diría que verificar la marca de tiempo es mucho más rápido que verificar md5sum. El propósito de estos encabezados es hacerlo rápido, a veces se prefiere no transferir la versión nueva de una entidad al cliente que cargar el servidor con E/S. De todos modos, el usuario siempre puede presionar ctrl + shift + R (o ctrl + F5 o lo que sea) – Grief

3

menos que se indique como débil por el servidor, un ETag se considera un validador fuerte, y se puede usar para satificar una solicitud condicional a distancia. Sin embargo, la mayoría de ETags generados automáticamente presentan dificultades en situaciones de granjas de servidores, ya que a menudo usan información de inodos y/o un único contador persistente. En la práctica, he encontrado que el encabezado Last Modified es suficiente para contenido bastante estático, p. sirviendo contenido estático protegido, ya que el tiempo de escritura del archivo es un validador razonablemente bueno.

El ETag es de lejos el más flexible.Los clientes conformes deben enviar el ETag en una solicitud condicional, mientras que DEBEN enviar ambos si están disponibles.

13

Valor de marca de tiempo utilizado en Última modificación/If-Modified-Since tiene una precisión limitada: un segundo y eso simplemente no es suficiente para un contenido que cambia rápidamente como, por ejemplo, aplicación de chat web donde se puede publicar más de un mensaje en cualquier segundo dado. ETag/If-None-Match puede ayudar a resolver ese problema.

7

Como se afirma en las mejores prácticas de Google:

Es importante especificar uno de Expira o Cache-Control max-age, y uno de Last-Modified o ETag, para todos los recursos cacheables. Es redundante especificar Caducidad y Control de caché: max-age, o para especificar Last-Modified y ETag.

https://developers.google.com/speed/docs/best-practices/caching

+0

esa URL ya no tiene un texto similar. No se menciona ninguna restricción contra el uso de 'Last-Modified' con' ETag' (o, en el lado useragent, 'If-Modified-Since' with'If-None-Match'). Del mismo modo, la especificación W3 no te restringe. Dice que no se debe usar 'If-Modified-Since' con' If-Match', pero supongo que es porque el conjunto de documentos que tienen fechas actualizadas pero con el mismo contenido definido por ETag debería ser bastante pequeño. – mpag

0

Dado que ambos robots de Google y Bing utilizan If-Modified-Since y no If-None-Match, es bueno para apoyarlo.

Hay una manera de admitir If-Modified-Since incluso en páginas complejas sin tener en cuenta los tiempos de modificación. Usamos este método en WikiMentions.com. Este método hace muchas suposiciones sobre la configuración. Puede no funcionar para todos.

Su html renderizado debe ser una función pura de los datos devueltos por las llamadas de API. Considere una página de ejemplo example.com/shows/cosmos. Se puede necesitar más de un llamadas a la API:

api.example.com/shows/cosmos 
api.example.com/cast/cosmos 
api.example.com/related/cosmos 
api.example.com/featured 

Si cada llamada devuelve un etag entonces se podría generar un etag para su página HTML mediante la concatenación de estos etags y el resultado hash. A continuación, puede usar esto como etag para la página html. A continuación, puede almacenar este etag en memcached junto con la hora en que se creó y el html generado.

{ 
    “Modified”: timestamp, 
    “Content”: rendered page, 
    “E-tag”: hash of concatenated etags of api calls 
} 

Ahora, cuando se solicita una página por primera vez:

  • Realizar llamadas API para la página
  • Generar etag concatenada
  • búsqueda etag en memcached (No existirá)
  • representar la página
  • Agregar a memcached
  • Enviar a usuario

Cuando se solicita una página de nuevo por algún otro nuevo visitante:

  • Realizar llamadas API para la página
  • Generar etag concatenada
  • búsqueda etag en memcached (Se existirá)
  • Enviar copia en caché de la visita anterior

Whe Página na es solicitado por un visitante de volver (con If-Modified-Since):

  • Realizar llamadas API para la página
  • Generar etag concatenada
  • búsqueda etag en memcached (existirá)
  • Si el tiempo de modificación en memcached es posterior a If-Modified-Since
    • Enviar copia en caché
  • Else
    • Enviar un 304 sin modificar

Ventajas:

  • puede soportar tanto If-Modified-Since y If-None-Match.
  • No hay páginas de re-rendering para nuevos visitantes si ya se ha procesado anteriormente .
  • Nunca sirva el contenido obsoleto.

Advertencias:

  • No hay necesidad de obtener el html prestados de memcached si estamos vamos a enviar un 304. Por lo que podría almacenar por separado en memcached con un prefijo unido a la etag como clave.
  • Cuando cambia su código de representación, los datos de la API no cambian, pero lo hace su html renderizado. Como resultado, no podrá ver sus cambios ya que solo verá html almacenado en caché.Para evitar esto, necesita para generar una pequeña cadena aleatoria cada vez que compile y anexarla a los etags antes de hash.
  • Esto no funcionará si el html representado no es una función pura de los datos de la API (por ejemplo: cadenas timeago). Una solución que utilizamos en WikiMentions es renderizar marcas de tiempo gmt y convertirlas a timeago en el lado del cliente después de que se cargue React.

Esto puede no funcionar para todos dependiendo de la configuración. Funciona para nosotros Usamos tornado para nuestra API y Reaccionamos con Node.js para nuestro front-end.

Cuestiones relacionadas