2008-08-28 17 views
24

Mientras escribía un IHttpHandler personalizado encontré un comportamiento que no esperaba con respecto al objeto HttpCachePolicy.¿Por qué HttpCacheability.Private suprime ETags?

Mi manejador calcula y establece una etiqueta de entidad (utilizando el método SetETag en la HttpCachePolicy asociada con el objeto de respuesta actual). Si configuro el control de caché en público usando el método SetCacheability todo funciona como un amuleto y el servidor lo envía a lo largo del encabezado de etiqueta electrónica. Si lo configuro en privado, se suprimirá el encabezado de la etiqueta electrónica.

Tal vez simplemente no he buscado lo suficiente pero no he visto nada en la especificación de HTTP/1.1 que justifique este comportamiento. ¿Por qué no desea enviar E-Tag a los navegadores al mismo tiempo que prohíbe que los servidores proxy almacenen los datos?

using System; 
using System.Web; 

public class Handler : IHttpHandler { 
    public void ProcessRequest (HttpContext ctx) { 
     ctx.Response.Cache.SetCacheability(HttpCacheability.Private); 
     ctx.Response.Cache.SetETag("\"static\""); 
     ctx.Response.ContentType = "text/plain"; 
     ctx.Response.Write("Hello World"); 
    } 

    public bool IsReusable { get { return true; } } 
} 

Volverá

 
Cache-Control: private 
Content-Type: text/plain; charset=utf-8 
Content-Length: 11 

Pero si cambiamos al público que va a volver

 
Cache-Control: public 
Content-Type: text/plain; charset=utf-8 
Content-Length: 11 
Etag: "static" 

me he encontrado esto en el servidor de desarrollo de ASP.NET y IIS6 hasta el momento con los mismos resultados. También soy incapaz de establecer explícitamente la ETag utilizando

Response.AppendHeader("ETag", "static") 

actualización: Es posible añadir la cabecera ETag manualmente cuando se ejecuta en IIS 7, Sospecho que esto se debe a la estrecha integración entre ASP.NET y el IIS7 tubería.

Aclaración: Es una cuestión de largo, pero la cuestión fundamental es la siguiente: ¿por qué ASP.NET hacer esto, ¿cómo puedo conseguir alrededor de él y debería hacerlo?

actualización: Voy a aceptar Tony's answer ya que es esencialmente correcta (ir a Tony!). Descubrí que si quieres emular HttpCacheability.Private por completo, puedes establecer la caché en ServerAndPrivate pero también tienes caché de llamadas. SetOmitVaryStar (true) de lo contrario, la caché agregará el Vary: * encabezado a la salida y no desea eso. Voy a editar eso en la respuesta cuando obtengo permisos de edición (o si ves este Tony quizás podrías editar tu respuesta para incluir esa llamada?)

Respuesta

17

creo que es necesario utilizar HttpCacheability.ServerAndPrivate

que debe darle Cache-Control: privado en las cabeceras y dejar que se establece una ETag.

La documentación sobre eso necesita ser un poco mejor.

Editar: Markus descubrió que también tiene caché de llamada.SetOmitVaryStar (true) de lo contrario, la caché agregará el encabezado Vary: * al resultado y usted no quiere eso.

+2

No sé si [esta respuesta] (http://stackoverflow.com/a/2633452/1869660) a una pregunta diferente describe la razón por la @Markus agrega la llamada a 'SetOmitVaryStar()', pero como de ASP.NET 4.0 puede que ya no sea necesario. – Sphinxxx

3

Desafortunadamente, si miras a System.Web.HttpCachePolicy.UpdateCachedHeaders() en el reflector .NET, ves que hay una declaración if que comprueba específicamente que Cacheability no es Private antes de hacer cualquier cosa ETag. En cualquier caso, siempre he encontrado que Last-Modified/If-Modified-Since funciona bien para nuestros datos y es un poco más fácil de monitorear en Fiddler de todos modos.

0

Si, como yo, no está contento con la solución mencionada aquí de usar Cacheability.ServerAndPrivate, y realmente quiere usar Private en su lugar, quizás porque está personalizando páginas individualmente para los usuarios y no tiene sentido almacenar en caché en el servidor - al menos en .NET 3.5 puede establecer ETag a través de Response.Headers.Add y esto funciona bien.

N.B. si hace esto, debe implementar la comparación de los encabezados de los clientes usted mismo y el manejo de la respuesta HTTP 304 - no estoy seguro si .NET se ocupa de esto en circunstancias normales.

+3

Siempre puede llamar a 'HttpCachePolicy.SetNoServerCaching' para deshabilitar el almacenamiento en caché de salida (es decir, el almacenamiento en caché del servidor). Esto anula la parte del "servidor" de 'HttpCacheability.ServerAndPrivate'. –

+0

@WilliamGross ¡Esta debería ser probablemente la respuesta aceptada! Gracias. – James

Cuestiones relacionadas