Search code examples
phphttphttp-headerscache-control

How does HTTP max-age works and how to expire cache after some time?


I manage the HTTP caching in my applications. And it's not working as I think it should. Let's get to an actual example:

With the first serve of my PHP page I serve the following HTTP headers:

HTTP/1.1 200 OK
Date: Mon, 12 Dec 2016 16:39:33 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.12
Expires: Tue, 01 Jan 1980 19:53:00 GMT
Cache-Control: private, max-age=60, pre-check=60
Last-Modified: Mon, 12 Dec 2016 15:57:25 GMT
Etag: "a2883c859ce5c8153d65a4e904c40a79"
Content-Language: en
Content-Length: 326
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

My application manage the validation of Etags and send 304 if nothing has changed and when you refresh the page in the browser (F5) you get (if nothing has changed server side):

HTTP/1.1 304 Not Modified
Date: Mon, 12 Dec 2016 16:43:10 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.12
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100

Since I serve Cache-Control: private with max-age=60 I would expect that after one minute the cache will be considered obsolete by the browser and it will request a fresh copy (equivalent of a Ctrl+F5 reload) but instead the cache is still valid several days after it's max-age.

Do I misunderstood these HTTP mechanism? Do I send something wrong or maybe miss something?


Solution

  • If a cached response is within the max-age, then it is considered fresh.

    If it exceeds the max-age, then it is considered stale.

    If a browser needs a resource and it has a fresh copy in the cache, then it will use that without checking back with the server.

    If the browser has a stale copy then it will validate that against the server (in this case, using Etags) to see if it needs a new copy of it the cached copy is still OK.