Im testing how cache-control
header works on Chrome.
My setup in nginx
is quite easy:
server {
listen 80;
server_name localhost;
etag on;
root /usr/share/nginx/html;
location / {
add_header Cache-Control "must-revalidate, private, max-age=10";
}
}
The behaviour I was expecting for the setup would be:
- max-age: Use cache for the specified time in seconds
- etag: Use for validating freshness of data
- private: avoid proxy caches to keep the data
With hard-reloads Im getting the expected behaviour:
1- First download hit the server and returns data with 200
2- Second refresh(ctrl + R) hit the server for validating freshness returning 304 if not modified or 200 if data was modified. (It seems that it's never served from web cache. Why?)
The previous behaviour are mostly expected but using back
and forward
button always retrieved data from web cache. Why is this? Why if I modified data but use the back
/forward
button Im still getting stale data from cache? Even if I wait more than 10 seconds the result is the same. Just hard-reload will get new data.
Caching headers work following way:
If max-age or Expires is set, then resource will be cached for provided time with one exception, if Cache-Control contains must-revalidate then following will happen.
Because a cache MAY be configured to ignore a server's specified expiration time, and because a client request MAY include a max- stale directive (which has a similar effect), the protocol also includes a mechanism for the origin server to require revalidation of a cache entry on any subsequent use. When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry after it becomes stale to respond to a
subsequent request without first revalidating it with the origin server.
or if Cache-Control contains no-cache then following will happen.
If the no-cache directive does not specify a field-name, then a cache MUST NOT use the response to satisfy a subsequent request without successful revalidation with the origin server.
In addition you can combine ETag and max-age/Expires headers to make caching more qualitative. When time expires, browser will send ETag based revalidation request.
Note that max-age and Expires are equivalent, but max-age has higher priority.
One more thing, if you didn't provide any of previous headers, then browser (Chrome for example) can cache your resource for 10% of a time passed since Last-Modified header value, but any way will send revalidation request based on Last-Modified value of cached resource.