56

我试图理解这一点,并搜索了类似的问题,但我仍然没有 100% 了解它应该如何工作。

我在请求图像资源时收到此响应:

Response Headers
    Server  Apache-Coyote/1.1
    Date    Mon, 19 Oct 2009 09:04:04 GMT
    Expires Mon, 19 Oct 2009 09:06:05 GMT
    Cache-Control   public, max-age=120
    Etag    image_a70703fb393a60b6da346c112715a0abd54a3236
    Content-Disposition inline;filename="binary-216-420"
    Content-Type    image/jpg;charset=UTF-8
    Content-Length  4719

期望的行为是客户端应该将此缓存 120 秒,然后再次从服务器请求它。在 120 秒内,没有请求发送到服务器。

然后,120 秒后,发送请求并收到 304 响应:

Response Headers
    Server  Apache-Coyote/1.1
    Date    Mon, 19 Oct 2009 09:06:13 GMT

Request Headers
    Host    localhost:8080
    User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
    Accept  image/png,image/*;q=0.8,*/*;q=0.5
    Accept-Language en-us,no;q=0.8,sq;q=0.7,en;q=0.5,sv;q=0.3,nn;q=0.2
    Accept-Encoding gzip,deflate
    Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive  300
    Connection  keep-alive
    Referer http://localhost:8080/cms/site/0/en/home
    Cookie  JSESSIONID=768ABBE1A3BFABE3B535900233330650; versionsCssDisplayState=block; iceInfo=iceOn:false,activePortletKey:,icePagePanelX:1722,icePagePanelY:3
    If-None-Match   image_a70703fb393a60b6da346c112715a0abd54a3236

到目前为止,一切顺利。但是,在下一个请求(大约 120 秒)时,我会认为资源应该被缓存 120 秒。另一方面,我在浏览器(Firefox)中看到的是,它从这一点开始总是请求资源并接收 304 响应。

我应该在 304 响应中附加缓存控制标头吗?从我在规范中看到的内容来看,似乎应该省略缓存控制设置,并且缓存应该自动将其缓存 120 秒?

4

3 回答 3

49

RFC7232更新 RFC2616 说:

生成 304 响应的服务器必须生成以下任何一个头字段,这些字段将在对同一请求的 200(OK)响应中发送:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary。

于 2010-12-08T23:45:42.647 回答
41

从理论上讲,您不必为 304 发送 Cache-Control - 收件人应该继续使用它从原始 200 收到的缓存指令。但是,正如您所发现的,实际上,如果您不这样做继续发送 Cache-Control,浏览器将忽略您最初发送的缓存指令,并恢复为自己的默认启发式。

因此,在实践中,您应该在 304 中包含与 200 相同的 Cache-Control。规范仅要求您将其发送为 304,如果它与您之前发送的不同(请参阅10.3.5 304 Not Modified) ——但它当然不会禁止你在相同的时候重复它。

并专门回应另一个答案(结构)中的错误观点:

  1. 确实希望中间缓存来缓存响应(即更新资源的缓存条目)。根据客户端是否包含条件标头,如 If-Modified-Since,它们将适当地响应来自客户端的 200 或 304 请求。

  2. 120 秒的 ttl将由304 刷新(因此同一个客户端至少在另外 120 秒内不应再次请求同一资源)。并且客户端,只要他们仍然缓存了内容,就会继续对资源发出有条件的请求,您可以继续使用 304 响应。

于 2009-12-23T22:19:22.430 回答
2

如果我理解正确,那么浏览器实际上缓存了 120 秒,并且您的服务器正在响应 304 Not Modified 到后续的 If-Modified-Since 请求。当最终用户访问相同的 URL 时,会发生此“IMS”请求。此时浏览器可以发送一个 If-Modified-Since 请求。浏览器想知道它是否显示过时的内容。这似乎很正常。

收到此请求后,您的服务器应回复 200 OK, 304 Not Modified(或 4XX,如有必要)。

我不认为您应该将您的服务器设置为发送带有 304 响应的 Cache-Control 标头,原因有两个:
1.您不希望任何中间缓存来缓存该 304 响应(它们有可能)
2. 304 响应不会刷新 120 秒 TTL。从 200 OK 响应开始,浏览器会将对象保留 120 秒。120 秒后,浏览器应该发送 GET 请求,而不是 If-Modified-Since,因此您的服务器将响应文件的字节,而不仅仅是 304 响应。

请注意,浏览器不会在 120 秒后再次自动请求该文件,除非最终用户通过页面加载或直接将 URL 输入到他们的地址栏来明确请求它(或者除非您有一个自定义应用程序以某种方式控制该功能)。

编辑了第一段以更好地阅读(希望如此)

于 2009-10-19T10:13:30.820 回答