当我访问chesseng.herokuapp.com时,我得到一个看起来像
的响应标题Cache-Control:private
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/css
Date:Tue, 16 Oct 2012 06:37:53 GMT
Last-Modified:Tue, 16 Oct 2012 03:13:38 GMT
Status:200 OK
transfer-encoding:chunked
Vary:Accept-Encoding
X-Rack-Cache:miss
然后我刷新页面并获取
Cache-Control:private
Connection:keep-alive
Date:Tue, 16 Oct 2012 06:20:49 GMT
Status:304 Not Modified
X-Rack-Cache:miss
所以看起来缓存工作正常。如果这适用于缓存,那么 Expires 和 Cache-Control:max-age 的重点是什么。更令人困惑的是,当我在https://developers.google.com/speed/pagespeed/insights/测试页面时,它告诉我“利用浏览器缓存”。
答案 0 :(得分:160)
答案 1 :(得分:47)
要回答有关缓存工作原理的问题,即使网络服务器不包含标题:
[a date]
[seconds]
服务器请求任何中间代理不要缓存内容(即该项只应缓存在私有缓存中,即仅在您自己的本地机器上):
但是服务器忘了包含任何类型的缓存提示:
但他们确实在响应中包含了 Last-Modified 日期:
Last-Modified: Tue, 16 Oct 2012 03:13:38 GMT
由于浏览器知道文件被修改的日期,因此可以执行 conditional request 。它将向服务器询问该文件,但指示服务器仅在自2012/10/16 3:13:38之后修改该文件时发送该文件:
GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT
服务器收到请求,意识到客户端已经拥有最新版本。而不是发送客户端200 OK
,然后是页面内容,而是告诉您缓存版本是好的:
304 Not Modified
您的浏览器确实不得不延迟向服务器发送请求,并等待响应,但它确实无需重新下载静态内容。
因为上次修改很糟糕。
并非服务器上的所有内容都与之关联的日期。如果我正在动态构建页面,则没有与之关联的日期 - 它现在是 。但我非常愿意让用户将主页缓存15秒:
200 OK
Cache-Control: max-age=15
如果用户锤击 F5 ,他们将继续获得缓存版本15秒。如果它是公司代理,那么在同一个15秒窗口中访问同一页面的所有67198用户都将获得相同的内容 - 所有这些用户都是从关闭缓存中提供的。每个人的表现都胜出。
添加Cache-Control: max-age
的好处是浏览器甚至不必执行条件请求。
Last-Modified
,则浏览器必须执行请求If-Modified-Since
,并注意304 Not Modified
响应max-age
,浏览器甚至不必遭受网络往返;内容将来自缓存 Expires
是现代(c.1998)Cache-Control: max-age
标题的遗产等价物:
Expires
:您指定日期(yuck) max-age
:您指定秒(善良) 如果指定两者,则浏览器会使用max-age
:
200 OK
Cache-Control: max-age=60
Expires: 20180403T192837
1998年以后编写的任何网站都不应再使用Expires
,而是使用max-age
。
ETag 类似于 Last-Modified ,但它不一定是日期 - 它只需要是 的东西 即可。
如果我从数据库中提取产品列表,服务器可以将最后一个rowversion
作为ETag发送,而不是日期:
200 OK
ETag: "247986"
我的ETag可以是静态资源(例如图像,js,css,字体)或缓存的渲染页面的SHA1哈希值(即这是Mozilla MDN wiki所做的;它们对最终标记进行哈希):< / p>
200 OK
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
与基于 Last-Modified 的条件请求完全相同:
GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT
304 Not Modified
我可以根据ETag执行条件请求:
GET / HTTP/1.1
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
304 Not Modified
ETag
优于Last-Modified
,因为它适用于除文件之外的其他内容,或具有 date 概念的内容。只是是
答案 2 :(得分:18)
RFC 2616,section 14.9.1:
表示全部或部分响应消息仅供单个用户使用,不得由共享缓存缓存...私有(非共享)缓存可以缓存响应。
浏览器可以使用此信息。当然,当前的“用户”可能意味着很多东西:操作系统用户,浏览器用户(例如Chrome的配置文件)等。它没有指定。
对我而言,Cache-Control: private
的更具体的例子是代理服务器(通常有很多用户)不会缓存它。它适用于最终用户,而不是其他任何人。
仅供参考,RFC明确指出这不提供安全性。它是关于显示正确的内容,而不是保护内容。
单词private的这种用法仅控制可以缓存响应的位置,并且无法确保消息内容的隐私。
答案 3 :(得分:0)
Expires entity-header字段给出了响应被认为是陈旧的日期/时间.Cache-control:maxage字段给出的年龄值(以秒为单位)大于响应被认为是陈旧的。
虽然上面的头字段给客户端一个机制来决定是否向服务器发送请求。在某些情况下,客户端向服务器发送请求,响应的年龄值大于maxage值,这意味着服务器需要将资源发送给客户端吗?也许资源从未改变过。
为了解决这个问题,HTTP1.1提供了最后修改过的头。服务器将响应的最后修改日期提供给客户端。当客户端需要此资源时,它会将If-Modified-Since头字段发送到服务器。如果此日期在资源的修改日期之前,服务器将把资源发送到客户端并提供200个代码。否则,它将向客户端返回304代码,这意味着客户端可以使用它缓存的资源。