提问人:Simon_Weaver 提问时间:2/18/2009 最后编辑:BartoszKPSimon_Weaver 更新时间:1/24/2014 访问量:3777
在 Chrome 中测试时标头会过期
Expires headers when testing in Chrome
问:
对这里的“过期”标题感到非常困惑! 有时它会按预期工作 - 有时则不然。
我正在使用以下代码来设置我的过期标头。请注意,这是通过 MVC 自定义属性中的 ASP.NET 完成的 - 这在这里并不真正相关 - 但解释了它的来源。'filterContext'
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
// my own custom header so we know what time it was
filterContext.HttpContext.Response.AddHeader("CurrentTime", DateTime.Now.ToString());
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
这有时会给我这样的标题:
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=413
Date: Wed, 18 Feb 2009 05:24:19 GMT
Expires: Wed, 18 Feb 2009 05:21:12 GMT
CurrentTime: 2/17/2009 9:21:12 PM
有时是这样的:
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=600
Date: Wed, 18 Feb 2009 05:27:55 GMT
Expires: Wed, 18 Feb 2009 05:27:55 GMT
CurrentTime: 2/17/2009 9:27:55 PM
我正在通过 Fiddler 运行所有内容,并观察何时重新请求内容以及何时来自浏览器缓存。
现在奇怪的是,在IE中,缓存总是按预期工作。指向我的 ASP.NET MVC 操作方法的链接出现在 Fiddler 中,然后当我再次单击同一链接时,它来自缓存。
但是,在 Chrome 中,它有时会,有时不会来自缓存!来自缓存,我的意思是没有额外的HTTP请求。
例如,像这样的链接:
http://ipv4.fiddler:62669/gallery/mainimage/2
将来自 IE 中的缓存,但返回 chrome 中的 200。然后有时在 Chrome 中它确实来自缓存。我尝试清空浏览器缓存并重试 - 每次结果都相同。
Chrome 是试图做一些“聪明”的事情,却惨遭失败——还是我需要一个额外的标头?
我想知道的是,这是否与我的标题日期实际上永远不会在未来这一事实有关。如果我查看谷歌托管的jQuery文件的标题,我会看到标题如下(此处的到期时间为2010年 - 未来一年)。Expires
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 05:44:53 GMT
Expires: Thu, 18 Feb 2010 05:44:53 GMT
Expires 实际上不应该在将来吗??
根据 HTTP 规范:
如果响应同时包含 Expires 标头和 max-age 指令, max-age 指令覆盖 Expires 标头,即使 Expires 标头更具限制性。此规则 允许源站服务器提供, 对于给定的响应,更长 HTTP/1.1 的过期时间(或 later) 缓存而不是 HTTP/1.0 缓存。如果确定,这可能很有用 HTTP/1.0 缓存计算不正确 年龄或过期时间,可能是由于 到不同步的时钟。
因此,即使“Expires”与当前时间相同,Chrome 似乎也应该遵守 max-age 指令,但它似乎没有这样做。
答:
我在 ASP.NET MVC 源代码中发现了以下内容:
public virtual void RenderView(ViewContext viewContext) {
// TODO: Remove this hack. Without it, the browser appears to always load cached output
viewContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
ViewUserControlContainerPage containerPage = new ViewUserControlContainerPage(this);
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
RenderViewAndRestoreContentType(containerPage, viewContext);
}
所以这就解释了为什么我的标题总是当前时间。但是,我真的不认为这是绊倒 Chrome 的原因,因为我创建了最简单的页面,如下所示,而 Chrome 仍然很高兴回到服务器并给了我 200 分Expires
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TimeSpan cacheDuration = TimeSpan.FromSeconds(33);
var cache = Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
评论
我几乎得出结论,这是 Chrome 在缓存方面做了一些非常非常古怪的事情。
我把它简化到尽可能低的水平 - 从谷歌的服务器获取jQuery。
我输入了:
http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js
到 Chrome,Fiddler 提出了以下 200 个请求:
Requests started at: 22:58:00:7756
Responses completed at: 22:58:03:5020
Total Sequence time: 00:00:02.7263880
DNS Lookup time: 531ms
TCP/IP Connect time: 63ms
RESPONSE CODES
--------------
HTTP/200: 1
标题如下(注意 Expires 是今天之后的 1 年):
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:01 GMT
Expires: Thu, 18 Feb 2010 06:58:01 GMT
Vary: Accept-Encoding
然后我等了几秒钟,然后按回车键 - 在同一选项卡中。Fiddler 提出了另一个 **200* 请求:
Requests started at: 22:58:09:2516
Responses completed at: 22:58:12:3999
Total Sequence time: 00:00:03.1482360
RESPONSE CODES
--------------
HTTP/200: 1
标题是:
Cache-Control: public, max-age=31536000
Date: Wed, 18 Feb 2009 06:58:09 GMT
Expires: Thu, 18 Feb 2010 06:58:09 GMT
Vary: Accept-Encoding
显然这不是我所期望的。
是 - 两个请求的 Accept-Encoding 相同。
是的 - 第三个请求给了我 304
这是在我从未进行过任何开发的 Chrome 新安装上 - 而且我只是第一次安装了 Fiddler。
我迫不及待地想有人向我解释这一点。现在我放弃了 - 我认为我的缓存和过期代码很好。此外 ASP.NET MVC 似乎强制 Expires 为当前时间。这显然不是我的谷歌示例中的一个因素。
我认为 Chrome 太聪明了,这一定是一个错误 - 我使用的是 1.0.154.48 版。
评论