为什么HttpCacheability.Private抑制ETag?

时间:2020-03-05 18:44:32  来源:igfitidea点击:

在编写自定义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:*标头添加到输出中,而我们不希望这样做。