内容协商与缓存

9

我想知道基于内容协商的API如何使用缓存。由于获取XML或JSON格式的资源时,URI是相同的,例如:

http://example.com/bikes/mountain

该服务根据Accept类型头返回JSON/XML。缓存有多聪明呢?
例如,如果一个客户端使用Accept类型请求返回XML,则响应将由Web服务器缓存1分钟。第二个客户端使用Accept类型请求返回JSON请求同一资源。
缓存是否根据接受/内容类型进行检查?还是这会导致JSON请求者得到XML数据,因为这是服务器缓存的数据?我希望这已经被解决了,否则,这不是在URI中包含.xml/.json的一个很大的理由吗?
我的问题基本上是,我是否可以在使用标准缓存技术的同时安全地使用内容协商?
3个回答

4

可以的。请查看RFC 2616中关于Vary头的描述。

在我对Vary头的简单理解中,缓存将使用在vary头中命名的标头字段来唯一标识缓存表示。


4

Darrel的观点是正确的,Vary头告诉客户端可以使用哪些请求头来获取资源的不同表示。

该值告诉客户端可以通过设置或更改Accept头(在您的情况下为JSON或XML)来请求以不同文件格式呈现。如果使用Accept-Language头,则还可以获得英语和法语的不同表示。

这两个请求发送不同的值,因此它们应始终单独缓存。

当您在Vary头中使用“*”的值时,意味着响应不应被缓存。


根据https://www.smashingmagazine.com/2017/11/understanding-vary-header/ 的说法,浏览器并不会单独缓存它们,而只会缓存最后一次使用的URL和Vary头部组合。因此,您将会获得正确的响应(满足验证任务),但它不会储存多个变体(例如语言),这是相当不幸的情况。 - Florian

2
正如其他人所提到的,HTTP(REST)响应中应该包含Vary: Accept头,以确保缓存知道内容基于协商的内容类型而更改。这在某种意义上是有效的,因为浏览器不会被提供(或不使用)错误的缓存变体来响应不同请求的内容类型。
问题在于即使到今天(2022年),Chrome在其HTTP缓存中仅缓存URL的一个变体(Firefox似乎做得对)。他们将根据Vary头检测是否请求一次XML和一次JSON表示,并正确下载新表示,但他们仅缓存最后一个下载的表示。
如果您首先在URL上加载HTML内容,然后在相同的URL上加载协商的JSON数据(使用JavaScript fetch或类似工具),则这可能是一个问题。那么实际上这两个请求都不会真正被缓存:下载JSON会删除缓存的HTML,下一次用户加载页面时,缓存将具有JSON而不是HTML,因此必须再次下载HTML,从缓存中删除JSON,然后再次下载。
因此,在我看来,这使得需要在URL中包含.json或类似的东西。
正在进行一个关于HTTP表示变体的新标准制定过程。此外,也可以参考这篇Fastly博客文章。不幸的是,即使在Chrome中使用服务工作者也无法解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接