3

I do understand how Cache-Control header works. However, I noticed that the browser treats the document request differently from other requests. The document request here is the first request that the browser makes when the user types the domain on the address bar and hits enter.

I tested an HTML page with the response header as follows:

Cache-Control: public, max-age=31536000, immutable

The header tells that the browser should cache the response for 1 year. But in the case document request, both Chrome and Firefox will revalidate it anyway. The evidence for it is the 304 response status.

enter image description here

Here is the test URL: https://test-http-cache-2exijs7pxj7x.runkit.sh/

I can not find an official document for this behavior. So it would be nice if someone could explain how the browser caches the document request and refers to an official document.

Thanks in advance!

Edit

The outcome mentioned above is the result of a soft reload (when the user hits the reload button or re-enters the same address). For navigation requests, the browser respects the Cache-Control and serves the response from the cache

11
  • can it be that your Dev Tools have disabled the cache? In general there is no guarantee I guess, that a simple header from the server will force the user agent to respect the header. Commented Mar 20, 2024 at 12:49
  • @d.k I did not disable the cache for sure. Added the test URL so you can play with it Commented Mar 20, 2024 at 16:12
  • @KevinChristopherHenry I guess so. I just want to know the exact behavior to deal with it. Commented Mar 20, 2024 at 16:13
  • @Duannx if you are using google chrome, is the 'disable cache' checkbox set in the network tab? It might be disabled by default, w/o your explicit intervention Commented Mar 21, 2024 at 4:48
  • 1
    Looking even more closely at this question, the nuances @Kaiido and Kevin Christopher Henry bring up in comments to my answer are not really asked by the OP. What you two are asking is related to Chrome only revalidating the top level resource on soft reloads (which users really don’t do) and using the cache for sub-resources (which the test url does not have) based on heuristics. Article explaining the reworking of how chrome handles reloads: blog.chromium.org/2017/01/… Commented Mar 28, 2024 at 12:39

2 Answers 2

3
+100

According to the spec, the immutable extension to the Cache-Control header:

Clients SHOULD NOT issue a conditional request during the response’s freshness lifetime (e.g., upon a reload) unless explicitly overridden by the user (e.g., a force reload).

The immutable extension only applies during the freshness lifetime of the stored response. Stale responses SHOULD be revalidated as they normally would be in the absence of the immutable extension.

The freshness of a response is determined by its age, which in HTTP is the time elapsed since the response was generated. You can read more about how a cache calculates the age on MDN, but it is essentially the difference between when the object was stored by the cache and it's max-age (or the value of an Expires header), which in your case is one year, so any cache following the spec, should not attempt a conditional request to validate the stored object.

I have confirmed on my Ubuntu laptop using Chrome and Firefox that Firefox will not issue a conditional validation request upon caching the response, but Chrome will. If you inspect the Browser compatibility table on MDN for the Cache-Control header, you will see that Chrome does not support the immutable extension, but Firefox does.

In short, according to the spec, clients should not issue a conditional request to validate a cached object that included the immutable extension to a response's Cache-Control header while the object is still fresh.

Chrome is not honoring the immutable extension, and therefore issuing a conditional request in the form of an If-None-Match request header due to the Etag on the returned resource.

Addendum:

The comments to this answer add an additional question not readily apparent in the original question. Namely, why is Chrome validating a cached resource that is fresh when a user reloads the page, but not during navigation?

Chrome has decided to not support immutable because they seem to feel their heuristic at handling reloads is sufficient and not worth the overhead of supporting another extension to Cache-Control with little observed value. It has been available to work on for years, but nobody has bothered.

In short, their heuristic will only validate a cached top level resource on reloads (which real end users really don't do), and use the cache for sub-resources. You can read about how Chrome revamped their heuristic in this article: https://blog.chromium.org/2017/01/reload-reloaded-faster-and-leaner-page_26.html

Note, the test URL provided in the question does not have any sub-resouces. Not only that, it appears to be serving plain text as text/html where text/plain might be more appropriate.

Sign up to request clarification or add additional context in comments.

16 Comments

The question, though, is why does Chrome send a conditional request at all when the cached response is still fresh? The OP is asking why the browser behaves differently when you type the URL in the URL bar (which is behaving like a soft reload) versus following a link, say.
I’d rather the OP speak for themselves and bring up any nuances in the question/answer they see as relevant. However, to satisfy your curiosity Chrome may be performing the conditional request despite the freshness due to content negotiation and the lack of a Vary response header so the client can determine what request headers were used to determine the returned representation of the cached resource. Try using curl or removing the Accept-Encoding request headers to test this.
For soft reloads they do revalidate. And indeed, hitting the reload button will 304. However typing in the address bar from another page does hit the 200 from cache for me. Which does corroborate what's said in that issue, but not what's said in the question... (Typing in the address bar from the same page does hit 304 though, which is kinda expected I guess, since that would be a soft reload). [2/2]
The question stands on its own, even without a clear motivation from the OP, they expected something to work in a certain way and it doesn't, the simple curiosity should be enough. Saying that Chrome doesn't follow the immutable specs might explain why sometimes they do revalidate, but that doesn't explain why other times they don't. That explanation is inside the bug report. A good answer would dig that up and explain clearly why they revalidate in that case, and when they don't. The status of the bug is irrelevant here, the information it contains is what matters.
Then edit it as you see fit. I share the sentiment on the bug ticket, this is trivial and the OP has what they need. I’ve already gotten what I personally wanted from the question. People should read the rfcs for http caching anyway for a deeper understanding, and not a SO answer.
|
0

Your browser will still send a request to the server this is called a "conditional GET"

as you can see on the initial request there is a header on your request which is the "If-None-Match"

This header is used to perform conditional GET requests based on entity tags (ETags) assigned to the requested resource.

The browser sends the ETag it has for the resource, and if the resource on the server has the same ETag, the server responds with a 304 Not Modified status code. indicating that the browser should use its cached copy of the document. If the document has been modified, the server responds with the updated document.

This process is known as revalidation...

I was wondering if you expected something different from the browser?

even if your browser already has a cached-copy of the page, it will still need to check if the cached-copy it has is an updated one...

if you want to bypass the revalidation entirely then you can disable ETAG... (which is what I think is the main issue)

if it does still sends a revalidation request maybe do things like make sure that your response have a Last-Modified and Expires Headers (I think this is a fix, if still revalidating, maybe you can update the test site you have so I can do some more investigations)

I hope that helps...

Documentations that might help:

1 Comment

Thanks for your answer but I'm expecting that if the browser respects the Cache-Control header, it should not make revalidation requests at all and the page should be always served from the cache

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.