Perché HttpCacheability.Private sopprime gli ETags?

Durante la scrittura di un IHttpHandler personalizzato mi sono imbattuto in un comportamento che non mi aspettavo riguardo l’object HttpCachePolicy.

Il mio gestore calcola e imposta un tag di quadro (utilizzando il metodo SetETag sulla HttpCachePolicy associata all’object di risposta corrente). Se imposto il controllo cache al pubblico usando il metodo SetCacheability, tutto funziona come un incantesimo e il server invia lungo l’intestazione del tag e-tag. Se l’ho impostato su privato, l’intestazione del tag e-tag verrà soppressa.

Forse non sono stato abbastanza duro ma non ho visto nulla nelle specifiche HTTP / 1.1 che giustificasse questo comportamento. Perché non desideri inviare E-Tag ai browser, impedendo comunque ai proxy di archiviare i dati?

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; } } } 

Tornerà

 Cache-Control: privato
 Content-Type: text / plain;  charset = utf-8
 Lunghezza del contenuto: 11

Ma se lo cambiamo in pubblico tornerà

 Cache-Control: pubblico
 Content-Type: text / plain;  charset = utf-8
 Lunghezza del contenuto: 11
 Etag: "statico"

Ho eseguito questo sul server di sviluppo ASP.NET e IIS6 finora con gli stessi risultati. Inoltre non sono in grado di impostare esplicitamente ETag usando

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

Aggiornamento : È ansible aggiungere manualmente l’intestazione ETag durante l’esecuzione in IIS7, sospetto che ciò sia causato dalla stretta integrazione tra ASP.NET e la pipeline IIS7.

Chiarimento : è una lunga domanda, ma la domanda principale è questa: perché ASP.NET fa questo, come posso aggirarlo e dovrei?

Aggiornamento : accetterò la risposta di Tony poiché è sostanzialmente corretto (vai Tony!). Ho scoperto che se si desidera emulare HttpCacheability.Private completamente è ansible impostare la cache su ServerAndPrivate ma si dispone anche di cache delle chiamate. SetOmitVaryStar (true) altrimenti la cache aggiungerà l’intestazione Vary: * all’output e non lo si desidera. Lo modifico nella risposta quando ottengo i permessi di modifica (o se vedi questo Tony forse potresti modificare la tua risposta per includere quella chiamata?)

Penso che sia necessario utilizzare HttpCacheability.ServerAndPrivate

Questo dovrebbe darti il ​​controllo della cache: privato nelle intestazioni e ti consente di impostare un ETag.

La documentazione su questo deve essere un po ‘meglio.

Modifica: Markus ha rilevato che hai anche la cache delle chiamate.SetOmitVaryStar (true) altrimenti la cache aggiungerà l’intestazione Vary: * all’output e non lo vuoi.

Sfortunatamente se si guarda System.Web.HttpCachePolicy.UpdateCachedHeaders() in .NET Reflector si vede che c’è un’istruzione if che controlla specificatamente che Cacheability non è Private prima di fare qualsiasi cosa ETag. In ogni caso, ho sempre trovato che Last-Modified/If-Modified-Since funziona bene per i nostri dati e comunque è un po ‘più semplice da monitorare in Fiddler.

Se come me non sei soddisfatto della soluzione qui menzionata di usare Cacheability.ServerAndPrivate e vuoi davvero utilizzare Private invece – forse perché stai personalizzando le pagine singolarmente per gli utenti e non ha senso memorizzare nella cache sul server – almeno in .NET 3.5 è ansible impostare ETag tramite Response.Headers.Add e questo funziona correttamente.

NB: se si esegue questa operazione, è necessario implementare il confronto tra le intestazioni client e la gestione della risposta HTTP 304, non è sicuro che .NET si occupi di ciò in circostanze normali.