PHP, Web and Mobile development

php: howto control page caching header

Working with cached pages

Controlling how web pages are cached is basically done using 2 kind of headers: Expires and Cache-Control

Using the Expire header is really simple. It tells when the page the browser or the proxy downloaded should be fetched again from the web server. In order to use it in your CGI or PHP page, just after theContent-type, you can add the the expire header as shown below:

 // calc an offset of 24 hours
 $offset = 3600 * 24;
 // calc the string in GMT not localtime and add the offset
 $expire = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
 //output the HTTP header
 Header($expire);

The Cache-Control HTTP Headers is part of the HTTP 1.1 standard. Here you are an example:

 Cache-Control: max-age=3600, must-revalidate

It has a certain number of parameters that can be used:

  • max-age=seconds – the number of seconds from the time of the request you wish this object to be keep into the cache;
  • s-maxage=seconds – like max-age but it only applies to proxy;
  • public – tell to handle the content has cacheable even if it would normally be uncacheable, it is used for example for authenticated pages;
  • no-cache – force both proxy and browser to validate the document before to provide a cached copy;
  • must-revalidate – tell the browser to obey to any information you give them about a webpage;
  • proxy-revalidate – like must-revalidate but applies to proxy;

More Headers

But that’s not all, you have to consider other 2 headers: Content-Length and Last-Modified.

The Last-Modified is the easier, you just have to output a date in GMT for example:

 $gmt_mtime = gmdate('D, d M Y H:i:s', time() ) . ' GMT';
 header("Last-Modified: " . $gmt_mtime );

Content-Lenght is the harder because you don’t know how long is a php page before processing it. If you output a file, for example and image or a PDF, it is simple because before of starting the output you can read the filesize. With dynamic page you have to use the special OB library, see the example:

 ob_start();
 ... your php code ...
 ... your php code ...
 ... your php code ...
 header('Content-Length: ' . ob_get_length());
 ob_end_flush();

The advantage is that you can use: ob_start('ob_gzhandler'); to have automatically compressed pages in output for faster downloading.

Usefull Links

Finally if you want to check the cacheability of your pages there are some urls available:

Important Notes

Remember that page caching is possible only for HTTP and not HTTPS because browsers never cache the results of crypted navigation to disks. This is the reason behind many websites keeping the images, flash and stuffs onto an HTTP server while they still provide crypted content via HTTPS.