HTTP:结合过期和验证缓存

发布于 2024-11-15 16:58:36 字数 559 浏览 3 评论 0原文

我在为以下情况制定 HTTP 缓存标头时遇到问题。

我们的服务器拥有大量数据,每周可能会更改几次。我希望浏览器缓存这些数据。此外,由于网络不可靠,我希望最大限度地减少条件获取的延迟。

我追求的最终行为是这样的:

  1. 客户端请求以前从未见过的资源。
  2. 服务器响应资源以及 ETag 和 max-age(24 小时)。
  3. 直到 24 小时过去,客户端才会使用缓存的资源。
  4. 过期日期之后,客户端将执行验证请求 (If-None-Match: [etag])
  5. 如果资源未更改:
    • 服务器响应 304 Not Modified
    • 客户端以某种方式获悉现有资源在 24 小时后有一个新的到期日期
    • 返回第 3 步

归结为本质... 304 响应可以包含新的 max-age 吗?或者后续请求是否会遵循原始的 max-age

I'm having trouble formulating HTTP cache headers for the following situation.

Our server has large data that changes perhaps a couple times a week. I want browsers to cache this data. Additionally, I want to minimize latency from conditional gets as the network is unreliable.

The end behavior I'm after is this:

  1. Client requests a resource it hasn't seen before.
  2. Server responds with resource along with ETag and max-age (24 hours).
  3. Until 24 hours has passed, client will use cached resource.
  4. After the expiration date, client will perform a validate request (If-None-Match: [etag])
  5. If resource has not changed:
    • server responds with 304 Not Modified
    • client is somehow informed that the existing resource has a new expiration date 24 hours from now
    • return to step 3

Boiled down to its essense... can a 304 response contain a new max-age? Or is the original max-age honored for subsequent requests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

季末如歌 2024-11-22 16:58:36

是的,304 响应可以包含新的 max-age(或 ETag,或与此相关的其他响应标头)。

我使用 Firefox 4 做了一个实验来测试原始 max-age 还是新的 max-age 是否受到尊重,答案是新的 max-age 受到尊重,所以你应该能够实现什么你想做的事。

请务必记住,max-age 是相对于 Date 响应标头,而不是 Last-Modified,因此每当您的服务器设置 >max-age 指令为 24 小时,意思是“从现在起 24 小时”。因此,假设这就是您想要的,您根本不必更改 max-age,只需始终返回 86400 即可。

无论如何,这是我的实验的概述和转储。基本上,我点击了一个设置 ETag 并将 max-age 设置为 120 秒的测试 URL。因此,服务器返回了带有这些响应标头的页面:

HTTP/1.1 200 OK
Date: Tue, 14 Jun 2011 23:48:51 GMT
Cache-Control: max-age=120
Etag: "901ea3d0ac9303ae4855a09676f96701"
Last-Modified: Mon, 13 Jun 2011 22:20:03 GMT

然后我重复点击地址栏中的“enter”来加载页面(但不强制硬重新加载)。由于 Firefox 反复从缓存中重新加载页面,因此没有网络流量。然后,120 秒结束后,当我下一次按回车键时,Firefox 反而向服务器发送了一个条件 GET,正如您所期望的那样。来自服务器的请求和响应是:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:50:54 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

请注意,在 304 响应中,我已将服务器 max-age 从 120 秒更改为 240。

所以,最大的问题是,之后会发生什么120秒? Firefox 会遵循新的 max-age 并继续从缓存加载页面,还是会访问服务器?答案是,它继续从缓存加载页面,并且直到达到 240 秒后才重新请求:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:54:56 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

我重复了另一个 240 秒的周期,事情按照您的预期进行。所以,希望这能回答你的问题。

RFC 解释了年龄计算应该如何实现,以及如何其他缓存控制参数起作用。不能保证每个浏览器和代理都会遵守规则,但此时 HTTP 1.1 已经相当老了,您可能会期望它们中的大多数都会像 Firefox 一样。

注意:为了简洁起见,在这些示例转储中,我删除了不相关的标头,例如主机、连接/保持活动、内容编码/长度/类型、用户代理等。)

Yes, a 304 response can contain a new max-age (or ETag, or other response headers for that matter).

I did an experiment using Firefox 4 to test whether the original max-age or the new one is honored, and the answer was that the new max-age is honored, so you should be able to implement what you want to do.

It's important to remember that max-age is relative to the Date response header, not Last-Modified, so whenever your server sets a max-age directive of 24 hours, it is saying "24 hours from right now." So, assuming that's what you want, you won't have to change your max-age at all, just always return 86400.

Anyway, here's an overview and dump of my experiment. Basically, I hit a test URL that set an ETag and set max-age to 120 seconds. Accordingly, the server returned the page with these response headers:

HTTP/1.1 200 OK
Date: Tue, 14 Jun 2011 23:48:51 GMT
Cache-Control: max-age=120
Etag: "901ea3d0ac9303ae4855a09676f96701"
Last-Modified: Mon, 13 Jun 2011 22:20:03 GMT

I then repeated hitting "enter" in the address bar to load the page (but not force a hard reload). There was no network traffic, since Firefox repeatedly reloaded the page from cache. Then, after 120 seconds were over, the very next time I hit enter, Firefox instead sent a conditional GET to the server, as you would expect. The request and response from the server were:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:50:54 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

Note that in the 304 response, I've had the server change max-age from 120 seconds to 240.

So, the big question is, what would happen after 120 seconds? Would Firefox respect the new max-age and continue loading the page from cache, or would it hit the server? The answer is that it continued loading the page from cache, and did not re-request until after 240 seconds were reached:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:54:56 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

I repeated through another 240-second cycle and things worked as you'd expect. So, hopefully that answers the question for you.

The RFC explains how age computations are supposed to be implemented, and how the other Cache-Control parameters work. There's no guarantee that every browser and proxy will follow the rules, but at this point HTTP 1.1 is pretty old and you'd expect most of them will do as Firefox does.

(Note: For brevity in these example dumps, I've deleted irrelevant headers such as host, connection/keep-alive, content encoding/length/type, user-agent etc.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文