2011-06-27 18 views
12

Estoy tratando de encontrar los mejores encabezados HTTP para enviar en cuatro casos de uso. Espero encontrar encabezados que no dependan del rastreo de la versión de agente/agente de usuario, pero lo aceptaré si nada más se ajusta. Todas las URL se obtienen a través de un controlador totalmente personalizado para que pueda seleccionar todos los encabezados como me gusta, esto se trata de intermediarios y agentes de usuario. Si es posible, esto debería ser compatible con los clientes HTTP/1.0 y HTTP/1.1. Si existen múltiples soluciones, la mejor será la más corta cuando se envíe por cable.Encabezados HTTP: control de la memoria caché y el mecanismo del historial

contenido público estático

Todos "contenido público estático" es algo que HTTP es realmente todo: si la URL es la misma, el contenido es el mismo. Puedo hacerlo fácilmente: por ejemplo, puse el icono de perfil de usuario en http://domain.com/profiles/xyz/icon/1234abcd donde "1234abcd" es el SHA-1 del contenido del archivo del icono. Si cambio al ícono en el futuro, crearé una nueva URL y modificaré todas las referencias existentes que deberían usar el ícono nuevo. ¿Cuáles son los mejores encabezados para declarar que esto se puede almacenar en caché para siempre y se puede compartir? Actualmente estoy pensando algo en la línea:

Date: <current time> 
Expires: <current time + one year> 

¿Es esto suficiente para permitir el almacenamiento en caché de las aplicaciones del usuario y los servidores proxy? ¿Necesito Last-Modified o Pragma?

contenido no pública estática

Todos "contenido no pública estática" es algo que es estático sino que puede no estar disponible a todo el mundo. De hecho, este contenido estará disponible solo para los usuarios que hayan iniciado sesión seleccionados (la sesión se mantiene con la cookie de sesión que contiene el UUID de la sesión). Si la URL es la misma, el contenido es el mismo. Sin embargo, la respuesta no es pública. Un caso de uso podría ser una imagen compartida con amigos seleccionados en un servicio de red social. Actualmente estoy pensando algo así:

Date: <current time> 
Expires: <current time> 
Cache-Control: private, max-age=<huge number>, s-maxage=0 

¿Esto es suficiente para permitir el almacenamiento en caché por parte de los agentes de usuario y desactivar los proxies? ¿Necesito Pragma?

contenido público volátil

Todos "contenido público volátil" es materia que es volátil y está disponible para todo el mundo. Algo así como la página principal de http://slashdot.org/ cuando no está conectado. La intención es permitir la actualización rápida del contenido en una URL no cambiante. Tenga en cuenta que NO quiero romper el mecanismo de historial de agente de usuario (es decir, hacer clic en algo de una página volátil y luego presionar el botón Atrás no debe llevar la página volátil del servidor; sin embargo, hacer clic en un vínculo va a la página frontal debe buscar el recurso del servidor). Actualmente estoy pensando algo en la línea:

Date: <current time> 
Expires: <current time> 
Cache-Control: public, max-age=0, s-maxage=0 

¿Es esto suficiente para evitar el almacenamiento en caché, pero para permitir mecanismo de historial (botón Atrás)? Sé que si envío Cache-Control: no-store, must-revalidate puedo forzar la recarga, pero esto no es lo que quiero porque también romperá el botón de retroceso. ¿Necesito Last-Modified o Pragma?

Aunque esto es público, probablemente no tenga sentido permitir que los proxies intermedios guarden en caché esto porque es volátil.

contenido no volátil pública

Todos "contenido no volátil pública" es un material que es volátil y no está disponible para todo el mundo (privado). Algo así como la página principal de http://slashdot.org/ cuando estás conectado. La intención es permitir la actualización rápida del contenido en una URL no cambiante. Tenga en cuenta que NO quiero romper el mecanismo de historial de agente de usuario (es decir, hacer clic en algo de una página volátil y luego presionar el botón Atrás no debe llevar la página volátil del servidor; sin embargo, hacer clic en un vínculo va a la página frontal debe buscar el recurso del servidor). Actualmente estoy pensando algo en la línea:

Date: <current time> 
Expires: <current time> 
Cache-Control: private, max-age=0, s-maxage=0 

¿Es esto suficiente para evitar el almacenamiento en caché, pero para permitir mecanismo de historial (botón Atrás)? ¿Necesito Pragma?


cosas que aún deben probar con mis cabeceras sugerida:

  • Verificar que el contenido privado no se filtrará a través de servidores proxy HTTP/1.0.
  • Verifique que el almacenamiento en caché funcione correctamente en los proxies.
  • Verifique que el almacenamiento en caché funcione correctamente en los agentes de usuario.
  • Verifique que el mecanismo de historial de agente de usuario funciona en agentes de usuario (en todos los casos).
  • Compruebe que al seguir un enlace a una página volátil obtiene contenido nuevo del servidor.
  • Verifique todos los resultados cuando use HTTPS en lugar de HTTP.
+0

Conozco una pregunta similar anterior en http://stackoverflow.com/questions/2970938/ideal-http-cache-control-headers-for-different-types-of-resources - sin embargo, eso es Faltan tres piezas importantes del rompecabezas: el comportamiento del botón de retroceso, la compatibilidad del agente de usuario y el soporte proxy HTTP/1.0. –

+0

La otra fuente frecuentemente citada http://www.mnot.net/cache_docs/ también sufre de no tratar el comportamiento del agente de usuario en el mundo real con respaldo de botón y HTTP/1.0 proxy. –

+0

Aquí hay un artículo sobre Cache-Control: http://palisade.plynt.com/issues/2008Jul/cache-control-attributes/ - también falta el comportamiento del botón de retroceso en el mundo real, la compatibilidad del agente de usuario y el soporte proxy HTTP/1.0. –

Respuesta

10

Voy a responder a mi propia pregunta:

estático contenido público

Date: <current time> 
Expires: <current time + one year> 

Justificación: Esto es compatible con los servidores proxy HTTP/1.0 y RFC 2616 Sección 14: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21 El encabezado Last-Modified no es necesario para el almacenamiento en caché correcto (porque los agentes de usuario conformes siguen el encabezado Expires) pero puede incluirse para el consumo del usuario final. Incluir el encabezado Last-Modified también puede disminuir la transferencia de datos del servidor en caso de que el usuario presione el botón Recargar/Actualizar. Si se agrega el encabezado Last-Modified, debe reflejar datos reales en lugar de algo inventado. Si desea disminuir la transferencia de datos del servidor (en caso de que el usuario accione el botón Recargar/Actualizar) y no puede incluir el encabezado real Last-Modified, puede agregar el encabezado ETag para permitir el GET condicional (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26). Si ya incluye Last-Modified también agregar ETag es solo desperdicio. Tenga en cuenta que Last-Modified es claramente superior porque también es compatible con clientes y proxies HTTP/1.0. Un valor adecuado para ETag en el caso de páginas dinámicas es SHA-1 de los contenidos de la página/recurso. Tenga en cuenta que el uso de Last-Modified o ETag no ayudará con la carga del servidor, solo con la tasa de transferencia de datos/conexión a Internet saliente del servidor.

contenido no pública estática

Date: <current time> 
Expires: <current time> 
Cache-Control: private, max-age=31536000, s-maxage=0 
Vary: Cookie 

Justificación: Los Date y Expires encabezados son para HTTP/1.0 compatibilidad y porque no hay manera sensata para especificar que la respuesta es privada, estas cabeceras comunican que la la respuesta no puede ser almacenada en caché. El encabezado Cache-Control indica que esta respuesta puede ser almacenada en memoria caché privada, pero que la memoria caché compartida no puede almacenar en caché la respuesta. Se agrega s-maxage=0 porque private no es compatible con todos los proxies que admiten Cache-Control (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3 - No tengo idea de qué proxies están rotos). El max-age se establece en el valor de 60*60*24*365 (1 año) porque la especificación HTTP/1.1 no define ningún límite superior para este parámetro, supongo que esto depende de la implementación. Los encabezados Expires DEBEN estar limitados a un año en el futuro, por lo que usar la misma lógica aquí debería estar bien. El encabezado Vary: Cookie es obligatorio porque la sesión que se usa para verificar si el visitante puede ver el contenido se transfiere en una cookie; porque la respuesta devuelta depende del valor de la cookie, la memoria caché no puede usar la respuesta en caché si se cambia el encabezado de la cookie.

Podría personalmente romper la última parte. Al no incluir el encabezado Vary: Cookie puedo mejorar mucho el almacenamiento en caché. Por ejemplo: tengo una imagen de perfil en http://domain.com/icon/12 que se devuelve solo para usuarios autenticados seleccionados. Tengo un visitante X con la identificación de la sesión 5f2 y permito la imagen a ese usuario. El visitante X cierra sesión y luego inicia sesión de nuevo. Ahora X tiene la identificación de sesión 2e8 almacenada en su cookie de sesión. Si tengo Vary: cookie, el agente de usuario de X no puede usar la imagen en caché y se ve obligado a volver a cargar esto en su caché. Como el contenido varía según las cookies, no se puede usar un GET condicional con la última modificación.No he probado si usar ETag podría ayudar en este caso porque en ese caso, la respuesta del servidor sería la misma (coincida con SHA-1 ETag calculada a partir del contenido de la respuesta). Tenga en cuenta que Internet Explorer (al menos hasta la versión 9) siempre obliga a GET condicional para los recursos que incluyen Vary: Cookie (fuente: http://blogs.msdn.com/b/ie/archive/2010/07/14/caching-improvements-in-internet-explorer-9.aspx). Esto se debe a que la implementación del caché interno de MSIE no recuerda qué Cookie envió por primera vez, por lo que no puede saber si la Cookie actual es la misma.

Sin embargo, aquí hay un ejemplo de un problema que se produce al dejar caer el encabezado Vary: Cookie para mostrar por qué esto es realmente necesario para un comportamiento técnicamente correcto. Vea el ejemplo anterior e imagine que después de que X se haya desconectado, el visitante Y inicia sesión con el mismo agente de usuario (el agente de usuario puede haberse reiniciado entre X e Y, no importa). Si Y visualiza una página que incluye un enlace al http://domain.com/icon/12, Y verá el ícono incrustado dentro de la página aunque Y no podría ver el ícono si X no hubiera estado usando el mismo agente de usuario previamente. En mi caso, no considero que esto sea un problema lo suficientemente grande porque Y podría acceder al ícono de forma manual inspeccionando el caché del agente de usuario independientemente de la posible adición de Vary: Cookie. Sin embargo, este problema puede evitar que Y note que técnicamente no tendría acceso a este contenido (esto puede ser importante, por ejemplo, si Y es coautor del contenido). Si el contenido se considera confidencial, el servidor debe enviar no-store independientemente de los problemas causados ​​por esta directiva Cache-Control.

Aquí también, agregar Last-Modified encabezado ayudará a los usuarios presionando el botón Recargar/Actualizar (consulte la discusión anterior).

contenido público volátil

Date: <current time> 
Expires: <current time> 
Cache-Control: public, max-age=0, s-maxage=0 
Last-Modified: <real-last-modification-time> 

Justificación: Dile a clientes HTTP/1.0 y los servidores proxy que esta respuesta debe ser considerada rancio inmediatamente. Se incluye el tiempo Last-Modified para permitir omitir la transmisión de datos de contenido cuando se vuelve a acceder al recurso y el cliente admite el GET condicional. Si no se puede usar Last-Modified, se puede usar ETag como reemplazo (vea la discusión anterior). Es fundamental utilizar Last-Modified para permitir el GET condicional con clientes compatibles con HTTP/1.0.

Si el contenido puede retrasarse aunque sea levemente, entonces Expires, max-age y s-maxage [sic] deben ajustarse adecuadamente. Por ejemplo, agregar 5 segundos a esos podría ayudar mucho para el sitio altamente popular, como lo sugiere la respuesta de symcbean. Tenga en cuenta que, a diferencia del GET condicional, aumentar el tiempo de caducidad reducirá la carga del servidor en lugar de simplemente disminuir el tráfico de datos de salida del servidor (porque el servidor verá menos solicitudes en total).

contenido no volátil pública

Date: <current time> 
Expires: <current time> 
Cache-Control: private, max-age=0, s-maxage=0 
Last-Modified: <real-last-modification-time> 
Vary: Cookie 

Justificación: Dile a clientes HTTP/1.0 y los servidores proxy que esta respuesta debe ser considerada rancio inmediatamente. Se incluye el tiempo Last-Modified para permitir omitir la transmisión de datos de contenido cuando se vuelve a acceder al recurso y el cliente admite el GET condicional. Si no se puede usar Last-Modified, se puede usar ETag como reemplazo (vea la discusión anterior). Es fundamental utilizar Last-Modified para permitir el GET condicional con clientes compatibles con HTTP/1.0. También tenga en cuenta que Cache-Control no debe incluir no-cache, must-revalidate o no-store porque al usar cualquiera de estas directivas se saltará el botón Atrás en al menos un agente de usuario.Sin embargo, si el contenido que el servidor está transfiriendo contiene material confidencial que no debe almacenarse en el almacenamiento permanente, la bandera no-store DEBE usarse independientemente de que se haya roto el botón Atrás. Advertencia: tenga en cuenta que el uso de no-store no puede evitar que el material confidencial termine en el disco duro sin cifrado si el sistema operativo tiene habilitado el intercambio y el intercambio no está encriptado. También tenga en cuenta que usar no-store tiene muy poco sentido a menos que la conexión esté encriptada (HTTPS/SSL).

2

mayoría bien, sin embargo, sí es necesario tener en cuenta que HTTP/1.0 proxies pueden almacenar en caché el contenido servido como

Cache-Control: private 

lo que debe establecer una cabecera explícita fecha de cambio, así como la expira encabezamiento.

Para su "Contenido estático no público" debe agregar un encabezado 'Varies: Cookie'.

Para su 'contenido público volátil': ¿Qué tan rápido está cambiando? Establecer un TTL de +5 segundos puede descargar mucho esfuerzo de sus servidores.

Para 'Contenido no público volátil', probablemente debería agregar no-cache, must-revalidate al encabezado de control de caché.

Los encabezados Pragma emitidos desde el servidor no deberían tener ningún efecto en los clientes ni en los servidores proxy.

Haz probar lo que sucede cuando expira su caché (IME se puede acabar con un sistema aún más lento que uno visitada sin caché poblada debido a todas las peticiones condicionales/304 respuestas)

+0

Soy consciente de que 'Cache-Control: private' no es entendido por HTTP/1.0 proxies. Esa es la razón por la que puse 'Fecha' y' Vence' a la hora actual. Esto, si lo he entendido correctamente, debería caducar el contenido de los proxies HTTP/1.0 inmediatamente. ¿Por qué necesito un encabezado 'Date-Modified' explícito? ¿Lo requieren algunos agentes de usuario? –

+0

Creo que agregar 'no-cache, must-revalidate' a 'Volatile no public content' romperá el botón atrás al menos en Firefox e Internet Explorer. Mi intención es mantener el botón Atrás para mostrar el historial real (en lugar de una vista transparente del estado del servidor) si es posible; ver http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.13 para más detalles. –

+0

Creo que la sintaxis del encabezado es 'Vary: Cookie'. Lo he pensado, pero como también el agente de usuario (navegador) respeta este encabezado, rompería el almacenamiento en caché de los agentes de usuario. Por ejemplo: tengo una imagen de perfil en 'http: // domain.com/icon/12' que se devuelve solo para usuarios autenticados seleccionados. Tengo un visitante X con ID de sesión '5f2' y le dejo la imagen a ese usuario. El visitante X cierra la sesión y luego vuelve a iniciar sesión. Ahora X tiene la identificación de sesión '2e8' almacenada en la cookie de sesión. Si tengo 'Vary: cookie', el agente de usuario de X no puede usar la imagen en caché. Técnicamente, 'Vary: cookie' sería el correcto. –

Cuestiones relacionadas