在编写自定义 IHttpHandler 时,我遇到了有关 HttpCachePolicy 对象的意外行为。

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

也许我只是没有仔细研究,但我没有在 HTTP/1.1 规范中看到任何可以证明这种行为合理的内容。为什么您不想将电子标签发送到浏览器,同时仍禁止代理存储数据?

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,但你也有调用缓存。设置省略变量星号(true) 否则缓存将添加 各不相同:* 标头到输出,而您不希望这样。当我获得编辑权限时,我会将其编辑到答案中(或者如果您看到这个托尼,也许您可​​以编辑您的答案以包含该呼叫?)

有帮助吗?

解决方案

我认为你需要使用 HttpCacheability.ServerAndPrivate

这应该给你缓存控制:标头中的 private 并允许您设置 ETag。

关于这方面的文档需要更好一点。

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

其他提示

不幸的是,如果你看 System.Web.HttpCachePolicy.UpdateCachedHeaders() 在 .NET Reflector 中,您会看到有一个 if 语句专门在执行任何 ETag 操作之前检查可缓存性是否不是私有的。无论如何,我总是发现 Last-Modified/If-Modified-Since 对于我们的数据来说效果很好,并且在 Fiddler 中更容易监控。

如果像我一样,您对这里提到的使用 Cacheability.ServerAndPrivate 的解决方法不满意,并且您确实想使用 Private - 可能是因为您正在为用户单独定制页面,并且在服务器上缓存没有意义 - 那么至少在 .NET 3.5 中,您可以通过 Response.Headers.Add 设置 ETag,效果很好。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top