我在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
(请注意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
请求已按预期到达后端,我正在记录它。后端返回ETag + Last modified
头,但不返回其他缓存头(例如max-age)。我希望浏览器始终访问后端。
当我没有进行强制刷新,而只是简单地在网站上导航到另一个页面,然后再次导航到该页面(不是通过后退按钮)时,就会发生此问题,这基本上是网站的正常使用情况。
我希望浏览器每次都向后端执行请求,后端返回ETag和200/304
状态代码,并且浏览器相应地使用客户端缓存(后端的ETag计算是正确的)。
问题在于请求甚至没有到达后端,没有执行请求,没有命中后端,我也不明白为什么。我可以在Firefox的cached
列中看到值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: ...
(没有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
我试图了解哪个标头正在阻止浏览器执行请求。我没有设置Cache-Control
标头。
我怀疑Vary
标头可能有问题,但任何提示都值得赞赏。
有什么主意如何调试浏览器为什么要缓存请求?什么标题错误?谢谢!
答案 0 :(得分:3)
缺少Cache-Control
或Expires
并不意味着缓存被禁用;这意味着浏览器可以自由实施自己的缓存策略。如RFC 7234中所述:
由于原始服务器并不总是提供明确的到期时间, 当明确的时间时,缓存可以分配启发式到期时间 未指定,使用使用其他标头字段的算法 值(例如
Last-Modified
时间)来估计合理的值 到期时间。
您实际想要的caching policy是Cache-Control: no-cache
,请返回。
响应可能由 any 缓存存储,即使该响应通常是不可缓存的。但是,存储的响应必须在使用前始终先经过原始服务器的验证。