什么是 Cache-Control: private?

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

看起来缓存起作用了。如果这对缓存有效,那么 过期缓存-控制: 最大年龄的意义是什么。更令人困惑的是,当我在 https://developers.google.com/speed/pagespeed/insights/测试页面时,它告诉我“利用浏览器缓存”。

137282 次浏览
Cache-Control: private

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

来自 RFC2616第14.9.1节

RFC 2616,第14.9.1节:

指示响应消息的全部或部分用于单个用户,并且不能由共享缓存缓存... 私有(非共享)缓存可以缓存响应。


浏览器可以使用这些信息。当然,当前的“用户”可能意味着很多东西: 操作系统用户,浏览器用户(例如 Chrome 的配置文件) ,等等。没有具体说明。

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


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

Private 这个词的这种用法只能控制响应可以缓存的位置,不能确保消息内容的隐私性。

Exires 实体头字段提供响应过期的日期/时间。Maxage 字段给出的 age 值(以秒为单位)比认为陈旧的响应大。

虽然上面的头字段给客户端一个机制来决定是否向服务器发送请求。在某些情况下,客户端向服务器发送请求,响应的年龄值大于最大值,这是否意味着服务器需要向客户端发送资源?也许资源从未改变。

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

回答你的问题,为什么缓存是工作的,即使网络服务器没有包括标题:

  • 过期: [a date]
  • Cache-Control: max-age = [seconds]

服务器友好地要求任何中间代理不要缓存内容(也就是说,条目只能缓存在 二等兵缓存中,也就是说,只能在您自己的本地机器上缓存) :

  • Cache-Control: private

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

  • 他们忘记了包含 过期了(这样浏览器知道在那个日期之前使用缓存的副本)
  • 他们忘记了包含 最大年龄(这样浏览器就知道缓存的条目可以支持多长时间)
  • 他们忘记包含 E-Tag(这样浏览器就可以执行条件请求)

是的在回复中包含 最后修改日期:

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

因为浏览器知道文件被修改的日期,所以它可以执行 一个 href = “ https://developer.mozilla.org/en-US/docs/Web/HTTP/Contionary _ request”rel = “ noReferrer”> 条件请求 。它会要求服务器提供文件,但指示服务器只发送自2012/10/163: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秒内继续获得缓存版本。如果它是一个公司代理,那么所有67,198个用户在同一个15秒的窗口中点击同一个页面都将得到相同的内容——所有内容都通过快速缓存提供。每个人都有好表现。

添加 Cache-Control: max-age的好处是,浏览器甚至不需要 来执行“条件”请求。

  • 如果只指定了 Last-Modified,则浏览器必须执行 If-Modified-Since请求,并监视 304 Not Modified响应
  • 如果指定了 max-age,浏览器甚至不需要经历网络往返; 内容将直接从缓存中提取出来。

“缓存控制: 最大年龄”与“过期”的区别

Expires是现代 Cache-Control: max-age头文件的遗产(约1998年) :

  • Expires: 指定一个日期 < em > (讨厌)

  • max-age: 指定秒 < em > (好)

  • 如果指定了 都有,那么浏览器将使用 max-age:

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

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

什么是 ETag?

ETag 类似于 最后修改,除了它不一定是一个日期——它只需要是一个 强 > something

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

200 OK
ETag: "247986"

我的 ETag 可以是一个静态资源(例如图像、 js、 css、字体)的 SHA1散列,也可以是缓存呈现页面的 SHA1散列(例如,Mozilla MDN wiki 就是这么做的; 它们散列最终的标记) :

200 OK
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

与基于 最后修改的条件请求的情况完全一样:

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,因为它适用于除 文件以外的事物,或者具有 约会概念的事物。只有