Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome ignores the ETag header and just uses the in memory cache/disk cache

If I understand correctly, the flow for using ETags works as described now:

  • Browser sends the request to the server. Server sends back the image with an ETag
  • Browser saves the ressource along with the ETag
  • On the next request, the browser sends the request with the header If-None-Match containing the saved ETag.

When returning a response, chrome dev tools tells me these are my headers

Cache-Control:max-age=7200
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 13:42:57 GMT
ETag:"b36f59c868d4678033d318a182658e18371df8f5"
Expires:Thu, 27 Apr 2017 15:42:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:873c8f
X-Debug-Token-Link:http://localhost:8081/_profiler/873c8f

Now, when I reload the page, the new image isn't gathered, though. It's saved through Chrome's in-memory cache or disk cache as you can see here

Chrome dev tab

But why is this happening? I sent an ETag so why does the browser not make another request to the server but instead uses it's own cache?

The reason I'm asking is, that we want to cache our images, but as soon as they change, they should be updated immedietely. Why does Chrome do that?

Update
I just noticed that it works as intendent on Firefox, so this seems to be a chrome "feature" and not a configuration one.

Update 2
After setting my new headers for image like this

Cache-Control:max-age=0, private
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 14:44:57 GMT
ETag:"e5b18bdebe44ed4bba3acb6584d9e6a81692ee27"
Expires:Fri, 27 Oct 2017 14:44:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:3447a6
X-Debug-Token-Link:http://localhost:8081/_profiler/3447a6

Chrome still uses the disk cache to laod the data. This is my nginx now

location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
  access_log off;
  add_header Cache-Control "max-age: 0, must-revalidate";
}

Update 3
I just did some further research. As soon as the Expires tag is set, Chrome uses the in-memory or disk-cache. Same with max-age. Which I don't understand, even when must-revalidate is set, as soon as Expires or max-age=>0 is set, Chrome doesn't reload the ressource.

like image 823
Musterknabe Avatar asked Apr 27 '17 13:04

Musterknabe


People also ask

Does Chrome use ETag?

Chrome ignores the ETag header and just uses the in memory cache/disk cache. Bookmark this question.

What is ETag in caching?

The ETag (or entity tag) HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed.

What is disk cache in Chrome?

Overview. The disk cache stores resources fetched from the web so that they can be accessed quickly at a latter time if needed.


3 Answers

The server is telling chrome that the resource is good for the next 2 hours (7200 seconds). Presumably your second request was sooner than that.

You would be better served with max-age: 0 or perhaps max-age: 0, must-revalidate. Then while you'll never get a fully-cached operation (not even bothering to hit the server) you can still have the server send 304 Not Modified responses to tell the browser that it can use the cached entity (and update any metadata based on headers if applicable) so while you still have a request-response happening only around 300bytes will be sent rather than however many kilobytes or more the entity is.

like image 140
Jon Hanna Avatar answered Oct 16 '22 12:10

Jon Hanna


This is an old post but this is how we solved it.

@Musterknabe Comment on your update 3:

The same thing happened with us, even after setting must-revalidate chrome was not reloading fresh resources. I found out that since resources were already present in clients/browser cache memory they were being served from memory cache and the new request(to get static resources) was not firing resulting. So response headers were not updated with must-revalidate

To fix this problem we used two steps:
1. Changed resource file names - To make sure new request will be fired
2. Added cache-control headers to static files(In startup.cs) - To take care of future static resource file changes. So that going forward we don't have to change the resource file names.

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticFiles(new StaticFileOptions
        {
            OnPrepareResponse = ctx =>
            {
                const int durationInSeconds = 0;
                ctx.Context.Response.Headers[HeaderNames.CacheControl] =
                    "must-revalidate,max-age=" + durationInSeconds;
            }
        });
    }

Hope it helps.

like image 36
S52 Avatar answered Oct 16 '22 12:10

S52


For ETags to be used and the browser to send the If-Modified-Since and If-None-Match headers, the cache control must be set to no-cache.

Either by the server using the Cache-Control: no-cache header or by the browser through the Request.cache = 'no-cache' option.


Read more about the cache options here: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache.

like image 2
enisdenjo Avatar answered Oct 16 '22 13:10

enisdenjo