<< Back Home UK uk   Donate Donate

Setting up HTTP Cache control + PHP sessions


Properly operaing HTTP cache reduce page load time and server load. Also, it allows efficient use of proxies and web-accelerators (e.g. nginx). Client and transit points of view had already been described in http traffic management and force caching. But as far as we need it working without any intervention on transit or client-side, web-server must be configured properly.

Cache control

Please also read standard for more details: RFC-2616 section 14

Google's manual is also recommended

Understanding HTTP cache control
Server-side cache control headers
Client-side cache control headers
Store rules

Static public - Commonly available static content like images, JS-libraries, etc.

Cache-Control: public, store, cache, no-validate
Etag: <hash>

Static private - availability or content of the object depends on client authorization

Cache-Control: private, store, cache, no-validate
Etag: <hash>

Regular object - object may change, but we can expect that it happens less often than time to live seconds and application logic allows minor inconsistency.

Cache-Control: public/private, store, cache, max-age=<time to live<, must-revalidate
Etag: <hash>

Dynamic object - oftenly updated object or application logic doesn't allow event minor inconsistency

Cache-Control: private, max-age=0, must-revalidate
Etag: <hash>
Last-Modified: <some date>

Non-cacheable object - we can assume that object is always changed and no caching is reasonable

Cache-Control: private, no-store, no-cache, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: <now>
  • Cache-Control: public - content can be cached on both intermediate servers (proxies) and client
  • Cache-Control: private - content can be cached on client side only. Intermediate servers (proxies) must not cache content because it depends on authorization.
  • Cache-Control: cache - caching is allowed
  • Cache-Control: no-cache - caching is denied. It worth using together with no-store, in order to prevent browsers from keeping content in 'history'.
  • Cache-Control: store - object copy is allowed to be stored on non-volatile storege (e.g. hdd)
  • Cache-Control: no-store - prevent keeping object copy on non-volatile storage for security reasons.
  • Cache-Control: max-age - maximum time to live live in cache without validation, may be ignored
  • Cache-Control: must-revalidate - client and intermediate proxies must validate object, cannot be ignored

Object must be revalidated in any of the following cases

  • Cache-Control: no-cache (+ no-store)
  • Expires: <date in the past>
  • Cache-Control: max-age=<time to live< expired
  • Cache-Control: max-age=0
  • Cache-Control: must-revalidate

Web server settings

Each web-server has own default settings for cache-control. These settings may differ between versions. If you need definite behavior, please configure them explicitly.

Note: some modules, e.g. php session (see below), and also several frameworks or libraries may have own cache-control mechanism. Please check documentation before use. Otherwise it may appear that caching doesn't work without visible reason.

Apache settings

Note: php session by default overrides these settings!

httpd.conf, apache.conf
# 5 minutes
ExpiresDefault A300

# 1 YEAR
<FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav)$">
ExpiresDefault A29030400

# 1 WEEK
<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">
ExpiresDefault A604800

# 3 HOUR
<FilesMatch "\.(txt|xml|js|css)$">
ExpiresDefault A10800"

<FilesMatch "\.(ico|gif|jpg|png|pdf|mp3|wav)$">
  ExpiresActive On
  ExpiresDefault "access plus 1 month"
  Header append Cache-Control "public, store, cache, no-validate"
  Header append Pragma "cache"

<FilesMatch "\.(css|js)$">
  ExpiresActive On
  ExpiresDefault "access plus 1 week"
  Header append Cache-Control "public, store, cache, no-validate"
  Header append Pragma "cache"

# 1 YEAR
<Directory "/var/www/date/libs">
  <FilesMatch "\.(js|css)$">
  ExpiresDefault A29030400
  Header set Cache-Control "max-age=290304000, public, store, cache, no-validate"

PHP settings

PHP module session completly disables caching by default. You should change config and manage cache control inside your scripts.

session.cache_limiter =

Alternatively you must use session_cache_limiter()

Cache control handling in PHP-script looks like this (for cacheable pages)

if(function_exists("getallheaders")) {
  $headers = getallheaders();

$hash = get_page_hash();

if(isset($headers) && isset($headers["If-None-Match"])) {
  if(preg_match("/".$hash."/", $headers["If-None-Match"])) {
    header("HTTP/1.1 304 Not Modified");

header("ETag: \"{$hash}\"");
header("Cache-Control: public, store, cache, max-age=$timeout");
header("Expires: ".gmdate ("D, d M Y H:i:s", time()+$timeout)) ;
PHP cache control example 1

// Perform some request processing, determine caching level
// For example it can be CACHE_NEVER for all POST requests and CACHE_PRIVATE/CACHE_NORMAL for
// GET (depending on request subtype).
// Calculate hash for reply (this can be md5($reply_data), md5($obj_change_time) or smth. other
// identifying version of object.

cache_ctl_if_match($hash); // return 304 Not modified if necessary
cache_ctl($level, $timeout, hash); // set cache control headers

// do request output

PHP cache control example 2

// Perform some preliminary request processing, determine caching level
// and hash, e.g. md5(<reply part 1>)

cache_ctl_preset($level, $timeout, $hash);

// Continue request processing, may be generate one more
// part of reply (and build hash for it) or detect some special condition
// (and adjust caching level and/or timeout).

cache_ctl_preset($level, $timeout, $hash);

// Now we know enough to say, if the request can be cached or if data was changed.
// Build corresponding headers, but check if cerrent page has matches client-specified one.

cache_ctl_if_match(); // return 304 Not modified if necessary
cache_ctl(); // set cache control headers

// do request output


See also:

FB or mail (remove X)   Share
<< Back designed by Alter aka Alexander A. Telyatnikov powered by Apache+PHP under FBSD © 2002-2024