请教一下关于浏览器(HTTP)缓存的问题

2019-07-25 17:56:16 +08:00
 xiaoz

比如这张图片: https://f002.backblazeb2.com/file/test-imgurl/imgs/2019/07/085f80437d5da3bd_thumb.jpg 是存放在 B2 的,已经设置了Cache-Control: max-age=6000,但是发现浏览器每次刷新都是返回的 200 状态码,而不是 304,浏览器并没有缓存这张图片,这是哪个 header 影响导致的呢?还是其它原因?

1695 次点击
所在节点    问与答
13 条回复
meik2333
2019-07-25 18:10:26 +08:00
etag 和 last-modified 至少要提供一个吧,不然无法判断照片是否被修改过。
YuxiangLuo
2019-07-25 18:14:10 +08:00
因为你直接在地址栏输入的图片地址,用 img 标签加载试试。
xiaoz
2019-07-25 18:42:15 +08:00
@YuxiangLuo 但是你访问这张图片试试 https://cdn.xiaoz.me/wp-content/uploads/2019/07/snipaste_20190721_155819.png 也是直接访问图片,再次刷新是可以返回 304 的。
Itanium
2019-07-25 18:52:45 +08:00
以 etag 为例,这个需要服务器告诉浏览器是否取缓存
客户端存下 etag,然后在 headers 里加上 if-none-match 再把服务器给的 etag 传回去,如果图片没发生改变 etag 不会变,服务器返回 304 让浏览器从本地缓存取
JK9993
2019-07-25 18:55:39 +08:00
chrome 缓存了也会返回 200
Cynic222
2019-07-25 19:05:18 +08:00
你要看是不是 from cache
limuyan44
2019-07-25 19:11:11 +08:00
你没发现这 2 个图片请求头和返回头都不一样吗
gbin
2019-07-25 19:29:56 +08:00
#5 说的对。
如果 HTTP 响应头被设置了 `Cache-Control: max-age=6000`,在缓存的有效期内,也就是 6000 秒内,HTTP 请求不对缓存的资源做新鲜度校验,而是直接返回 200。如果你想每次都对缓存资源做新鲜度校验,那么你可以设置成 no-store (或者设置 must-revalidate ),no-store 的意思是不建议直接使用缓存而不是不使用缓存,这种情况下,HTTP 请求会配合 ETag + If-Modified 等多个请求头对资源校验,如果资源没有被更改服务器才会返回 304,告诉客户端资源没有被修改,可以直接取本地缓存。
gbin
2019-07-25 19:50:41 +08:00
@gbin #8 不建议直接使用缓存是 no-cache,no-store 是禁止使用缓存
wszgrcy
2019-07-25 20:04:18 +08:00
有强制缓存和协商缓存
gbin
2019-07-25 20:05:10 +08:00
你给的两张图片为什么返回的值一个是 200 一个是 304?
这是因为两张图片的 Request Headers 中设置了 max-age=0,这是客户端告诉服务器本地缓存过期时间是 0,但是这并不是说客户端不能缓存,而是说每次请求都需要做新鲜度校验,如果资源没有被修改就返回 304 客户端取本地缓存,否则返回 200。第一张图片服务器没有返回 ETag 标志,再次请求的时候客户端无法比对成功,所以返回了 200 (猜测是后端动态生成的缩略图?),第二张请求时返回了 ETag 标志,再此请求时使用 if-none-match 和 ETag 比对,if-modified-since 和 last-modified 比对,如果都比对成功说明资源没有被修改,所以客户端直接取缓存。
gbin
2019-07-25 20:19:35 +08:00
另外还有一个点就是 #2 说的,为什么你直接浏览器输入 URL 和使用 img 标签呈现效果不一样,
比如 https://0x400.com/2019-07-10-lc-67-add-binary.html 这个连接中有一张图片,如果你直接刷新页面你会看到图片是 from disk 或者 from cache,也就是命中缓存了,此时返回的就是 200. 但是如果你直接在浏览器中输入图片的 url,你会发现返回的是 304,这就是因为 Chrome 的 Reload 操作会主动携带 max-age=0 的请求头对图片做新鲜度校验。
meik2333
2019-07-25 20:21:42 +08:00
@YuxiangLuo #2
@JK9993 #5
@gbin #11

他们说的对,Chrome 如果本地缓存了,状态是 200 (from disk cache) 或者 200 (from memory cache),在 Chrome 中如果直接通过 URL 打开图片的话,会在 Request 中添加 cache-control: max-age=0 来让缓存不生效( https://superuser.com/questions/313131/how-do-i-stop-chrome-sending-cache-control-max-age-0-when-i-hit-enter ),因此如果需要测试 cache-control 是否生效的话,需要用 img 标签加载。

然后就是为什么他是 304 你是 200 的问题了,这个就是我刚才说的,因为你没有给 etag 和 last-modified。但是如果使用 img 标签加载的话,你们两个的图片都是可以被缓存的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/586209

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX