剩余内容协商和缓存
我想知道缓存如何与基于内容协商的 API 一起使用。由于要获取 XML 或 JSON 格式的资源,URI 将是相同的,例如:
http://example.com/bikes/mountain
服务根据 Accept 类型标头返回 JSON / XML。缓存有多智能?
例如:
- 如果一个客户端使用 Accept 类型请求此操作以返回 XML。
- 响应被 Web 服务器缓存 1 分钟。
- 第二个客户端使用 Accept 类型请求相同的资源以返回 JSON
缓存检查是否接受/内容类型?或者这会导致 JSON 请求者取回 XML 数据,因为那是服务器缓存的数据?我希望这是显而易见的事情,已经得到处理,否则,在 URI 中包含 .xml / .json 不是一个相当大的论点吗?
我想我的问题基本上是,我可以在仍然使用标准缓存技术的同时安全地使用内容协商吗?
I'm wondering how caching works with content negotiation based API. Since the to get a resource in XML or JSON, the URI will be the same, for example:
http://example.com/bikes/mountain
The service returns JSON / XML based on the Accept type header. How smart are caches?
For example:
- if one client requested this using Accept type to return XML.
- the response is cached by web server for say 1 minute.
- second client requests same resource using Accept type to return JSON
Does caching check accept / content types at all? Or would this result in the JSON requester getting XML data back since thats what the server had cached? I'm hoping this is something so obvious its already been taken care of, otherwise, isn't that a pretty large argument to include .xml / .json in the URI?
I guess my question is basically, can i safely use content negotiation while still using standard caching techniques?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Darrel 是正确的,因为 Vary 标头告诉客户端可以改变哪些请求标头以获得资源的不同表示形式。
该值告诉客户端它可以通过设置或更改 Accept 标头(在您的情况下为 JSON 或 XML)来请求不同文件格式的表示形式。如果您使用 Accept-Language 标头,您还可以获得英语和法语的山地自行车的不同表示形式。
这两个请求发送不同的值,因此应始终单独缓存它们。
当您在 Vary 标头中使用“*”值时,这意味着不应缓存响应。
Darrel is correct in that the Vary header tells the client which request headers it can vary to get different representations of a resource.
That value tells the client that it can ask for the representation in a different file format, by setting or changing the Accept header (in your case, JSON or XML). You could also get a different representation of your mountain bike in English and in French if you use the Accept-Language header.
The two requests send different values, so they should always be cached separately.
When you use a value of '*' in Vary header, that means the response should not be cached.
是的。看看 RFC 2616 中对 Vary 标头的描述
在我的简单化中了解了变化标头后,缓存将使用变化标头中命名的标头字段来唯一标识缓存的表示形式。
Yes. Look at the description of the Vary header in RFC 2616
In my simplistic understanding of the vary header, caches will use the header fields that are named in the vary header to uniquely identify the cached representation.
正如其他人提到的,应该在 HTTP (REST) 响应中使用
Vary: Accept
标头,以确保缓存知道内容根据协商的内容类型进行更改。这是有效的,因为浏览器不会为不同请求的内容类型提供(或不会使用)错误的缓存变体。问题是,即使到今天(2022 年),Chrome 在其 HTTP 缓存中也只能为每个 URL 缓存一个变体(Firefox 似乎做了正确的事情)。如果您请求一次 XML 和一次 JSON 表示形式,它们将根据
Vary
标头进行检测,并正确下载新的表示形式,但它们只会缓存最后下载的表示形式。如果您首先在 URL 加载 HTML 内容,然后在同一 URL 加载内容协商的 JSON 数据(使用 JavaScript
fetch
或其他内容),这可能会出现问题。那么实际上这两个请求都不会真正被缓存:下载 JSON 将删除缓存的 HTML,下次用户加载页面时,缓存将有 JSON 而不是 HTML,因此必须再次下载 HTML,从缓存中删除 JSON 。然后必须重新下载。因此,在我看来,这使得需要在 URL 或类似内容中包含
.json
。HTTP 表示变体的新标准正在进行中。另请参阅这篇Fastly 博客文章。遗憾的是,即使使用 Service Worker 目前也无法在 Chrome 中为您提供帮助。
As other have mentioned, one should
Vary: Accept
header in HTTP (REST) responses to make sure caches are aware that content changes based on negotiated content type. That works in the sense that browsers will not be served (or will not use) wrong cached variant for a different requested content type.The issue is that even as of today (2022) Chrome in its HTTP cache cache only one variant per URL (Firefox seems to do the right thing). They will detect based on
Vary
header if you request once XML and once JSON representation and correctly download a new representation, but they will cache only the last one downloaded.This can be a problem if you first load HTML contents at URL which then loads a content-negotiated JSON data at the same URL (using JavaScript
fetch
or something). Then in practice none of those two requests will really be cached: downloading JSON will remove the cached HTML, and next time user loads the page, cache will have JSON and not HTML, so HTML will have to be downloaded again, removing JSON from cache. Which then has to be downloaded again.So in my view, this makes it required to include
.json
in URLs or something like that.There is ongoing process on a new standard for HTTP Representation Variants. See also this Fastly blog post. And sadly even using service workers does currently not help you here in Chrome.