为什么HttpCacheability.Private抑制ETag?
在编写自定义IHttpHandler时,我遇到了关于HttpCachePolicy对象的意外行为。
我的处理程序计算并设置一个实体标签(使用与当前响应对象关联的HttpCachePolicy上的SetETag方法)。如果我使用SetCacheability方法将缓存控件设置为public,那么一切都会像超级按钮一样工作,并且服务器会发送e-tag标头。如果我将其设置为私有,则电子标签标头将被禁止显示。
也许我只是看起来不够努力,但是我没有在HTTP / 1.1规范中看到任何可以证明这种行为合理的东西。为什么在仍然禁止代理存储数据的同时,不希望将E-Tag发送给浏览器?
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; } } }
将返回
Cache-Control: private Content-Type: text/plain; charset=utf-8 Content-Length: 11
但是,如果我们将其更改为公开,它将返回
Cache-Control: public Content-Type: text/plain; charset=utf-8 Content-Length: 11 Etag: "static"
到目前为止,我已经在ASP.NET开发服务器和IIS6上运行了此程序,并获得了相同的结果。我也无法使用以下方式显式设置ETag
Response.AppendHeader("ETag", "static")
更新:在IIS7中运行时,可以手动添加ETag标头,我怀疑这是由于ASP.NET与IIS7管道之间的紧密集成引起的。
澄清:这是一个很长的问题,但核心问题是:ASP.NET为什么要这样做,我应该如何解决?我应该这样做吗?
更新:我将接受托尼的回答,因为它基本上是正确的(去托尼!)。我发现如果我们要模拟HttpCacheability.Private,则可以将可缓存性设置为ServerAndPrivate,但是我们也可以调用cache.SetOmitVaryStar(true),否则缓存将在输出中添加Vary:*标头,而我们不想那。当我获得编辑权限时,我会将其编辑为答案(或者,如果我们看到此Tony,也许我们可以编辑答案以包括该呼叫?)
解决方案
回答
不幸的是,如果我们查看.NET Reflector中的System.Web.HttpCachePolicy.UpdateCachedHeaders()
,我们会发现有一个if语句专门在执行任何ETag任务之前检查Cacheability是否为Private。无论如何,我总是发现Last-Modified / If-Modified-Since
对于我们的数据效果很好,无论如何在Fiddler中进行监视要容易一些。
回答
我认为我们需要使用HttpCacheability.ServerAndPrivate
那应该在标题中为我们提供cache-control:private,并让我们设置一个ETag。
关于该文档的文档需要更好一些。
编辑:Markus发现我们也有调用cache.SetOmitVaryStar(true),否则缓存会将Vary:*标头添加到输出中,而我们不希望这样做。