Reputation: 6081
If I understand correctly, the flow for using ETags works as described now:
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
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.
Upvotes: 28
Views: 16048
Reputation: 731
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.
Upvotes: 4
Reputation: 481
For anyone else who might land here, note that Chrome does not cache anything if there are any SSL errors (such as if you're using a self-signed certificate).
Original post that clued me in: https://stackoverflow.com/a/55101722/9536265
Chrome bug: https://bugs.chromium.org/p/chromium/issues/detail?id=110649 (and it appears they will never fix it, which seems ridiculous since almost all developers will be developing in that very situation)
I have not been able to confirm with documentation, but the behavior appears to be the same with Edge Chromium. Firefox, on the other hand, will happily follow standard cache practices for sites using "Not secure" certificates such as those with imperfectly-matching site names or self-signed certificates. I have not tested Safari.
Upvotes: 6
Reputation: 419
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.
Upvotes: 3
Reputation: 113232
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.
Upvotes: 8