0

IE(7 -10)似乎不尊重过期。我打开提琴手并正在检查。如果响应有一个 etag,那么它会执行 304,否则它会为在未来 1 年到期的资源执行 200。我也尝试设置最后修改。它似乎不起作用。在 chrome 中,当有一个过期标签时..它甚至不会发送到服务器(对于 304)它已经缓存了它。这是一些 Fiddler 标头

Req Headers
GET /geoip/city?country=US&state=ID HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: */*
Referer: http://localhost/register/BG/57ac5960-f0d5-11e3-90d1-af2b2634c624
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Host: localhost
Cookie: connect.sid=s%3AntN3Tq9zXgrnlo5YOR1bsSa0lHE987Nv.aBbljhmG5tpfYcIXMgonxnhhWaWwd%2BTQ4jIKLnqL4us

Response Headers
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: X-HTTP-Method-Override, Accept-Encoding
expires: Sun Jul 05 2015 23:15:21 GMT-0400 (Eastern Daylight Time)
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Date: Mon, 07 Jul 2014 03:15:21 GMT
Connection: keep-alive
Transfer-Encoding: chunked

并带有电子标签

req Headers
GET /geoip/city?country=US&state=ID HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: */*
Referer: http://localhost/register/BG/57ac5960-f0d5-11e3-90d1-af2b2634c624
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost
If-None-Match: W/"101c-2996882950"
Connection: Keep-Alive
Cookie: connect.sid=s%3AntN3Tq9zXgrnlo5YOR1bsSa0lHE987Nv.aBbljhmG5tpfYcIXMgonxnhhWaWwd%2BTQ4jIKLnqL4us

Response header
HTTP/1.1 304 Not Modified
X-Powered-By: Express
Vary: X-HTTP-Method-Override
expires: Sun Jul 05 2015 23:18:47 GMT-0400 (Eastern Daylight Time)
ETag: W/"101c-2996882950"
Date: Mon, 07 Jul 2014 03:18:48 GMT
Connection: keep-alive

根据 Ruud 的建议..这是请求/响应

GET /geoip/city?country=US&state=MO HTTP/1.1
Cache-Control: public, max-age=31536000
Accept: */*
X-Requested-With: XMLHttpRequest
Referer: http://localhost/register/BG/57ac5960-f0d5-11e3-90d1-af2b2634c624
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
If-None-Match: W/"3bf9-3115988671"
Host: localhost
Cookie: connect.sid=s%3AZvwd9g7PAbQl7QHVx0ucpBMNnELll1R_.6KIvAtRWv9FK3zxxXVZfJBCpSv962zxLeTkvGd7mQq8

HTTP/1.1 304 Not Modified
X-Powered-By: Express
Vary: X-HTTP-Method-Override
expires: Mon Jul 06 2015 08:37:49 GMT-0400 (Eastern Daylight Time)
Cache-Control: public, max-age=31536000
last-modified: Sat Jul 07 2012 08:37:49 GMT-0400 (Eastern Daylight Time)
ETag: W/"3bf9-3115988671"
Date: Mon, 07 Jul 2014 12:37:49 GMT
Connection: keep-alive
4

3 回答 3

1

您的 HTTP 请求不包含If-Modified-Since标头。这通常意味着该页面尚未被缓存。这可能是由于没有Cache-Control标题。如果没有该标头,Web 浏览器可能会应用其自己的默认缓存行为。在 IE7/8/9/10 的情况下,这很可能是这样的:“您的 URL 有一个查询字符串,我们不要缓存它。”

请尝试将此标头添加到 HTTP 请求中:

Cache-Control: public, max-age=31536000

您的 HTTP 请求包含X-Requested-With: XMLHttpRequest,因此我假设您正在使用 XMLHttpRequest 将 HTTP 请求发送到 Web 服务器。您可能可以像这样添加标题:

req.setRequestHeader("Cache-Control", "public, max-age=31536000");

除了上述之外,您可能还需要Last-Modified在 HTTP 响应中有一个标头;If-Modified-Since客户端可能需要此日期/时间在下一次 HTTP 请求时放入标头。

使用 Fiddler 验证:

  • HTTP 请求包含标头Cache-Control
  • HTTP 响应包含标头Last-Modified
  • 第二次,HTTP 请求同时包含Cache-ControlIf-Modified-Since

当所有其他方法都失败时,您甚至可以考虑将自己的If-Modified-Since标头推送到 HTTP 请求中。

上述标题的文档可以在http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html的第 14.9、14.25 和 14.29 节中找到

于 2014-07-07T08:18:15.827 回答
0

我认为您不了解 Expires 的用途。这只是告诉浏览器:“将其保存在缓存中,直到......”但它没有告诉:“并且不要检查它是否未被修改”!所以使用“Expires”,也使用“Last-modified”,两个正确的(有效的 RFC 1123)日期值:“Sun, 05 Jul 2015 23:15:21 GMT”。它应该工作。

于 2014-07-12T21:04:33.933 回答
0

一种可能的解释是:

Expires: Sun Jul 05 2015 23:15:21 GMT-0400 (Eastern Daylight Time)

不是有效的 RFC 1123 日期。尝试将 response-header 字段更改为:

Expires: Sun, 05 Jul 2015 23:15:21 GMT

RFC 2616规定:

HTTP/1.1 客户端和缓存必须像过去一样对待其他无效的日期格式,特别是包括值“0”(即“已经过期”)。

从那里开始,Web 浏览器的行为取决于是否存在Last-Modified和/或ETag响应头字段。

  • 没有Last-Modified/ ETag:因为Expires有一个无效的日期,并且没有Cache-Control可以依靠(你做了 test Cache-Control,但是 Last-Modified/ ETag,不是没有),缓存很可能被禁用;客户端将发送请求,服务器将响应 200。
  • 使用Last-Modified/ ETag:缓存可能已启用,但Expires日期无效,因此客户端被迫发送请求以验证缓存是否过时。服务器以 304 响应以确认缓存正常。

从您的故事中,我了解到这正是 IE 7-10 所做的。

另一方面,RFC 2616指出:

鼓励日期值的接收者在接受可能由非 HTTP 应用程序发送的日期值时保持稳健,有时通过代理/网关检索或发布消息到 SMTP 或 NNTP 时就是这种情况。

因此,某些浏览器可能比其他浏览器更自由,并尽最大努力解析您的日期(Chromium 问题 153759似乎暗示了这一点)。这或许可以解释为什么 Chrome 会在 IE 没有命中缓存时命中缓存。

注意:您可以考虑添加Cache-Control: public, max-age=31536000到响应标头中,除了(或作为替代)Expires. 也可以看看:


编辑: 我用 IE9 做了一个非常简单的测试。在 Linux 机器上,我反复运行以下命令(使其充当单次 Web 服务器):

cat h1.txt b1.txt | sudo nc -l 91

这是我的h1.txt;因为我在 Linux 机器上创建了它,所以我必须使用它unix2dos来确保每一行都以\r\n. 相关的响应头字段是ExpiresLast-Modified

HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Date: Sat, 12 Jul 2014 20:07:43 GMT
Expires: Sun, 05 Jul 2015 23:15:21 GMT
Last-Modified: Sat, 12 Jul 2013 20:07:43 GMT
Server: WEBrick/1.3.1 (Ruby/1.9.2/2014-01-23)
Content-Length: 252
Connection: keep-alive

b1.txt是一个带有一段 JavaScript 调用的 HTML 页面XMLHttpRequest,向同一页面发送 HTTP 请求(因为我懒得设置另一个页面)。

<html>
<head>
<title>Test</title>
</head>
<body>
<button onclick="SendReq()">Send request</button>
<script>
function SendReq() {
    var rq = new XMLHttpRequest();
    rq.open('GET', 'http://192.168.1.103:91/', true);
    rq.send();
}
</script>
</body>
</html>

我没有安装 Fiddler;我改用 Wireshark(过滤tcp.port == 91)来监控流量。事实上,我可以随意点击网页上的按钮,没有流量,直到我清除 IE9 的缓存。

这意味着 IE9 的缓存工作正常;问题必须出在网络服务器上;更具体地说,在响应标头中。任何小错误都可能破坏缓存。您原来的 Expires 标头字段(带有非 GMT 日期)就是一个很好的例子。

正如 Pierre 所指出的那样,请务必在响应标头中放置Last-Modified和/或ETag,否则即使页面存在于缓存中,IE 也可能会往返于 Web 服务器。但我怀疑每个网络浏览器都是这种情况,而不仅仅是旧版 IE。

于 2014-07-09T19:24:40.493 回答