The Expires directives have two syntaxes. One is fairly unreadable; it expects you to calculate how many seconds until expiry. Fortunately, the module will also read a much more human syntax. This article describes the readable syntax.

If you're using the Expires header in the .htaccess file, you will need to edit httpd.conf to set the AllowOverride header for the relevant directory. Apache will only read .htaccess in directories which have the "Indexes" override set.

# Allow the Indexes override for the directories using .htaccess.
<Directory /whichever/directory/here>
# Everything else you want to add to this section
AllowOverride Indexes
</Directory>

Add the Expires directives to the .htaccess file in the relevant directory. The webmaster can edit the .htaccess file without needing access to httpd.conf.

The main problem with the ".htaccess" method is that the Indexes override and the .htaccess file give the webmaster more configuration options than just the Expires header. This may not be what the system administrator intends.

Alternative method: Cache-Control header

mod_cern_meta allows file-level control, and it also allows the use of Cache-Control headers (or any other header). The headers are put in a subdirectory of the origin directory, with a name based on the origin file's name.

Indicates that the object may be stored in a cache. This is the default.

Cache-Control : private

Cache-Control : private = [field-name]

Indicates that the object (or specified field) must not be stored in a shared cache and is intended for a single user. It may be stored in a private cache.

Cache-Control : no-cache

Cache-Control : no-cache = [field-name]

Indicates that the object (or specified field) may be cached, but may not be served to a client unless revalidated with the origin server.

Cache-Control : no-store

Indicates that the item must not be stored in nonvolatile storage, and should be removed as soon as possible from volatile storage.

Cache-Control : no-transform

Proxies may convert data from one storage system to another. This directive indicates that (most of) the response must not be transformed. (The RFC allows for transformation of some fields, even with this header present.)

Cache-Control : must-revalidate

Cache-Control : proxy-revalidate

Forces the proxy to revalidate the page even if the client will accept a stale response. Read the RFC before using these headers, there are restrictions on their use.

Caveats and gotchas

HTTP/1.0 has minimal cache control and only understands the Pragma: no-cache header. Caches using HTTP/1.0 will ignore the Expires and Cache-Control headers.

None of the Cache-Control directives ensure privacy or security of data. The directives "private" and "no-store" assist in privacy and security, but they are not intended to substitute for authentication and encryption.

This article is not a substitute for the RFC. If your are implementing the Cache-Control headers, do read the RFC for a detailed description of what each header means and what the limits are.

Final words

Caching is a reality of the Internet and enables efficient usage of bandwidth. Your clients probably view your pages through a cache, and sometimes multiple caches. Applying cache headers to your pages protects the page content and allows your clients to save their bandwidth.