25

在编写自定义 IHttpHandler 时,我遇到了一种与 HttpCachePolicy 对象有关的行为,这是我没想到的。

我的处理程序计算并设置一个实体标签(使用与当前响应对象关联的 HttpCachePolicy 上的 SetETag 方法)。如果我使用 SetCacheability 方法将缓存控制设置为公共,那么一切都会像魅力一样工作,服务器会沿着电子标签标头发送。如果我将其设置为私有,则电子标签标题将被禁止。

也许我只是看起来不够努力,但我在 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; } }
}

将返回

缓存控制:私有
内容类型:文本/纯文本;字符集=utf-8
内容长度:11

但是,如果我们将其更改为公开,它将返回

缓存控制:公共
内容类型:文本/纯文本;字符集=utf-8
内容长度:11
Etag:“静态”

到目前为止,我已经在 ASP.NET 开发服务器和 IIS6 上运行它,结果相同。我也无法使用显式设置 ETag

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

更新:在 IIS7 中运行时可以手动附加 ETag 标头,我怀疑这是由于 ASP.NET 和 IIS7 管道之间的紧密集成造成的。

澄清:这是一个很长的问题,但核心问题是:为什么 ASP.NET 这样做,我怎样才能绕过它,我应该吗?

更新:我将接受托尼的回答,因为它基本上是正确的(去托尼!)。我发现如果你想完全模拟 HttpCacheability.Private,你可以将缓存能力设置为 ServerAndPrivate,但你也有调用缓存。SetOmitVaryStar (true) 否则缓存会将Vary: *标头添加到输出中,而您不希望这样。当我获得编辑权限时,我会将其编辑到答案中(或者如果您看到这个托尼,也许您可​​以编辑您的答案以包含该呼叫?)

4

3 回答 3

17

我认为您需要使用 HttpCacheability.ServerAndPrivate

这应该给你 cache-control: private 在标题中,让你设置一个 ETag。

这方面的文档需要更好一些。

编辑: Markus 发现您也调用了 cache.SetOmitVaryStar(true) 否则缓存会将 Vary: * 标头添加到输出中,而您不希望这样。

于 2008-08-29T05:25:27.503 回答
3

不幸的是,如果您System.Web.HttpCachePolicy.UpdateCachedHeaders()在 .NET Reflector 中查看,您会发现在执行任何 ETag 内容之前,有一条 if 语句专门检查 Cacheability 是否不是私有的。无论如何,我总是发现这Last-Modified/If-Modified-Since对我们的数据很有效,而且无论如何在 Fiddler 中更容易监控。

于 2008-08-28T22:27:44.247 回答
1

如果像我一样,您对此处提到的使用 Cacheability.ServerAndPrivate 的解决方法不满意,并且您真的想改用 Private - 也许是因为您正在为用户单独自定义页面并且在服务器上缓存没有意义 - 那么至少在 .NET 3.5 中,您可以通过 Response.Headers.Add 设置 ETag,这可以正常工作。

请注意,如果您这样做,您必须自己实现客户端标头的比较和 HTTP 304 响应处理 - 不确定 .NET 在正常情况下是否会为您处理这个问题。

于 2012-03-30T00:12:35.920 回答