什么是缓存控制:私有?


148

当我访问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

因此似乎缓存正在运行。如果该方法适用于缓存,那么ExpiresCache-Control:max-age的意义是什么?更令人困惑的是,当我在https://developers.google.com/speed/pagespeed/insights/上测试页面时,它告诉我“利用浏览器缓存”。


Answers:


74

要回答有关为什么缓存仍然起作用的问题,即使Web服务器未包含标头也是如此:

  • 过期: [a date]
  • 快取控制: max-age =[seconds]

服务器恳请任何中间代理不缓存内容(即,该项目仅应缓存在专用缓存中,即仅在您自己的本地计算机上):

  • 缓存控制:私有

但是服务器忘记了包含任何类型的缓存提示:

  • 他们忘记了包含Expires,因此浏览器知道在该日期之前都使用缓存的副本
  • 他们忘记了包含Max-Age,因此浏览器知道缓存的内容适合多长时间
  • 他们忘记了包含E-Tag,因此浏览器可以执行条件请求

但它们的确在响应中包含了“ 最后修改日期”:

Last-Modified: Tue, 16 Oct 2012 03:13:38 GMT

因为浏览器知道文件的修改日期,所以它可以执行条件请求。它将向服务器询问文件,但指示服务器仅发送自2012/10/16 3:13:38以来已被修改的文件:

GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT

服务器收到请求,意识到客户端已经具有最新版本。而不是发送client 200 OK,然后发送页面内容,而是告诉您缓存的版本是好的:

304 Not Modified

您的浏览器确实必须忍受向服务器发送请求并等待响应的延迟,但是确实节省了重新下载静态内容的麻烦。

为什么选择Max-Age?为什么到期

因为最后修改很烂。

并非服务器上的所有内容都有与其关联的日期。如果我正在动态建立网页,则没有日期相关联- 现在是。但我非常愿意让用户将首页缓存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:您指定一个日期(不正确)
  • max-age:您指定秒数(有效)
  • 如果同时指定了两者,则浏览器将使用max-age

    200 OK
    Cache-Control: max-age=60
    Expires: 20180403T192837 
    

1998年以后编写的任何网站都不应再使用Expires,而应使用max-age

什么是ETag?

ETagLast-Modified相似,不同之处在于ETag不必是日期-只需是某物即可

如果我要从数据库中提取产品列表,则服务器可以将最后一个rowversion作为ETag 发送,而不是发送日期:

200 OK
ETag: "247986"

我的ETag可以是静态资源(例如图像,js,css,字体)的SHA1哈希值,也可以是缓存的呈现页面的SHA1哈希值(即Mozilla MDN Wiki的工作;它们哈希最终标记):

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

An ETag之所以优越,Last-Modified是因为它适用于文件以外的内容或具有日期概念的内容。它只是


1
太棒了!我为此悬赏。如果cache-control不存在会怎样?而你只有Etag?它仍然不需要针对服务器发出“条件请求”吗?我脱机时看到的行为是它只是从缓存中返回。但是,当它处于脱机状态时,无法发出该有条件的请求。那么这是否意味着如果您保持离线状态,它将无限期缓存?我已经在这里详细询问了这个问题。你可以看看吗?
亲爱的

167
Cache-Control: private

指示全部或部分响应消息是针对单个用户的,并且不得由共享缓存(例如代理服务器)缓存。

根据RFC2616第14.9.1节


14
因为它是由您的浏览器缓存的。您是响应所针对的唯一用户。
Dan D.

13
不,不是因为Cache-Control:private仅声明共享缓存(例如代理缓存)不应缓存响应。
Dan D.

5
@Trejkaz不,这实际上意味着一个用户。用户是一个具有自己的主目录的帐户,缓存位于其中。同一用户拥有的那些配置文件可以共享其缓存。如您所见。但是,如果同一计算机上的两个配置文件由不同用户拥有,则它们不得共享其缓存,除非该缓存被视为共享缓存。
Dan D.

2
嗯,所以是每个用户在OS级别上。是的,我想知道的原因是因为Chrome的隐身窗口与非隐身窗口之间存在明显的信息泄漏,后者使用缓存来做到这一点。
Trejkaz

2
@didibus proxy-revalidate要求代理每次访问时都必须重新验证。其中as private阻止代理缓存。
Dan D.

20

RFC 2616, 第14.9.1节

指示全部或部分响应消息是针对单个用户的,并且不得由共享缓存进行缓存...专用(非共享)缓存可以缓存响应。


浏览器可以使用此信息。当然,当前的“用户”可能意味着很多事情:操作系统用户,浏览器用户(例如Chrome的个人资料)等。未指定。

对我来说,更具体的例子Cache-Control: private是,代理服务器(通常有许多用户)将不缓存它。它是针对最终用户的,没有其他人使用。


仅供参考,RFC明确指出这不提供安全性。这是关于显示正确的内容,而不是保护内容。

专用一词的这种用法仅控制可以在何处缓存响应,并且不能确保消息内容的私密性。


5
私有(非共享)缓存可以缓存响应。这部分是关键。谢谢。
奥利弗2014年

0

Expires实体标题字段提供了将响应视为过时的日期/时间。Cache-control:maxage字段给出了比认为响应过时的响应大的寿命值(以秒为单位)。

尽管头字段上方提供了一种机制,使客户端可以决定是否将请求发送到服务器。在某些情况下,客户端发送请求进行服务器发送,响应的年龄值大于最大值,是否表示服务器需要将资源发送给客户端?也许资源从未改变。

为了解决此问题,HTTP1.1提供了最后修改的头。服务器将响应的最后修改日期提供给客户端。当客户端需要此资源时,它将向服务器发送If-Modified-Since头字段。如果此日期早于资源的修改日期,则服务器会将资源发送给客户端并提供200代码。否则,它将向客户端返回304代码,这意味着客户端可以使用其缓存的资源。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.