浏览器缓存请求/响应,没有任何 Cache-Control 标头

Nic*_*ola 1 http-caching request-headers http-headers

我在 SPA Web 应用程序和 REST API 后端遇到浏览器缓存问题。我可以在打开开发人员工具的情况下在 Firefox 和 Safari 上重现它:我确保缓存未禁用。

当我进入第一个特定页面,该页面只是从 REST API 获取并显示对象时,我使用“硬刷新”(Mac 上的 CMD+R)来完成此操作。我看到以下标题:

第一个请求:

Host: localhost:5000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: application/json, text/plain, */*
Accept-Language: en,it;q=0.7,fr;q=0.3
Accept-Encoding: gzip, deflate, br
Origin: http://localhost:3000
DNT: 1
Connection: keep-alive
Referer: http://localhost:3000/literature/sde5e-zeb98
Cookie: ...
If-Modified-Since: Fri, 10 Jul 2020 16:19:24 GMT
If-None-Match: "2"
Cache-Control: max-age=0
Run Code Online (Sandbox Code Playgroud)

(注意Cache-Control标题,由于硬刷新而自动添加)

回复:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 6128
ETag: "2"
Last-Modified: Fri, 10 Jul 2020 16:19:24 GMT
Link: <https://localhost:5000/api/documents/sde5e-zeb98>; rel="self"
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 52
X-RateLimit-Reset: 1594398279
Retry-After: 60
X-Frame-Options: sameorigin
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31556926; includeSubDomains
Referrer-Policy: strict-origin-when-cross-origin
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers: Content-Type, ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Access-Control-Allow-Credentials: true
Vary: Origin
Server: Werkzeug/1.0.1 Python/3.6.7
Date: Fri, 10 Jul 2020 16:23:38 GMT
Run Code Online (Sandbox Code Playgroud)

请求按预期到达后端,我正在记录它。后端返回ETag + Last modified标头,但不返回其他缓存标头(例如 max-age)。我希望浏览器始终访问后端。

当我没有进行硬刷新,而是简单地在网站上导航到另一个页面,然后再次导航到此页面(不通过后退按钮)时,就会发生此问题,基本上是网站的正常使用。我希望浏览器每次都会向后端执行请求,后端返回 ETag 和200/304状态代码,浏览器相应地使用客户端缓存(后端的 ETag 计算是正确的)。问题是请求甚至没有到达后端,没有执行请求,没有后端命中,我不明白为什么。cached我可以在 Firefox 中看到该列中的值Transferred

她的要求:

Host: localhost:5000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: application/json, text/plain, */*
Accept-Language: en,it;q=0.7,fr;q=0.3
Accept-Encoding: gzip, deflate, br
Origin: http://localhost:3000
DNT: 1
Connection: keep-alive
Referer: http://localhost:3000/literature/sde5e-zeb98
Cookie: ...
Run Code Online (Sandbox Code Playgroud)

(没有Cache-Control标题,这是正确的,这应该是正常行为)

缓存响应(无后端命中):

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 6128
ETag: "2"
Last-Modified: Fri, 10 Jul 2020 16:19:24 GMT
Link: <https://localhost:5000/api/documents/sde5e-zeb98>; rel="self"
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 52
X-RateLimit-Reset: 1594398445
Retry-After: 60
X-Frame-Options: sameorigin
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31556926; includeSubDomains
Referrer-Policy: strict-origin-when-cross-origin
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers: Content-Type, ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Access-Control-Allow-Credentials: true
Vary: Origin
Server: Werkzeug/1.0.1 Python/3.6.7
Date: Fri, 10 Jul 2020 16:26:24 GMT
Run Code Online (Sandbox Code Playgroud)

我试图了解哪个标头正在阻止浏览器执行请求。我没有Cache-Control设置标题。我怀疑这可能是标题的问题Vary,但任何提示都会受到赞赏。

知道如何调试浏览器缓存请求的原因吗?什么标题是错误的?谢谢!

Kev*_*nry 8

缺少Cache-ControlExpires并不意味着缓存被禁用;这意味着浏览器可以自由地实施自己的缓存策略。如RFC 7234中所述:

由于源服务器并不总是提供显式的过期时间,因此当未指定显式时间时,缓存可以分配启发式过期时间,并采用使用其他标头字段值(例如时间Last-Modified)的算法来估计合理的过期时间。

您真正想要的缓存策略Cache-Control: no-cache,所以返回它。

响应可以由任何缓存存储,即使响应通常是不可缓存的。但是,存储的响应在使用之前必须始终首先通过源服务器进行验证。