什么是缓存控制:私有?

时间:2012-10-16 06:31:28

标签: http caching http-headers browser-cache cache-control

当我访问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/测试页面时,它告诉我“利用浏览器缓存”。

4 个答案:

答案 0 :(得分:160)

Cache-Control: private
  

表示全部或部分响应消息仅供单个用户使用,不得由共享缓存(例如代理服务器)缓存。

来自RFC2616 section 14.9.1

答案 1 :(得分:47)

要回答有关缓存工作原理的问题,即使网络服务器不包含标题:

  • 过期: [a date]
  • 缓存控制:max-age = [seconds]

服务器请求任何中间代理不要缓存内容(即该项只应缓存在私有缓存中,即仅在您自己的本地机器上):

  • 缓存控制:私有

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

  • 他们忘记包含过期,因此浏览器知道在该日期之前使用缓存副本
  • 他们忘记包含 Max-Age ,因此浏览器知道缓存商品有多长时间
  • 他们忘记包含电子标记,因此浏览器可以执行条件请求

但他们确实在响应中包含了 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

您的浏览器确实不得不延迟向服务器发送请求,并等待响应,但它确实无需重新下载静态内容。

为什么 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,浏览器甚至不必遭受网络往返;内容将来自缓存

“Cache-Control:max-age”和“Expires”之间的区别

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?

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代码,这意味着客户端可以使用它缓存的资源。