httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nicholas Sherlock <>
Subject mod_cache sends 200 code instead of 304
Date Sat, 25 Jul 2009 06:56:08 GMT
Hi everyone,

If you make a conditional request for a cached document, but the 
document is expired in the cache, mod_cache currently passes on the 
conditional request to the backend. If the backend responds with a "304 
Not Modified" response that indicates that the cached copy is still up 
to date, mod_cache serves the contents of the cache to the client with a 
200 code.

But couldn't it just send a 304 Not Modified code instead? At the moment 
it ends up wasting large amounts of bandwidth on my website in the case 
where you press refresh on an unmodified object in Firefox, which sends 
these request headers:

If-None-Match="My ETag"

I do not want the behaviour given by "CacheIgnoreCacheControl yes". I 
still want mod_cache to validate the request against the backend, but I 
don't want it to waste bandwidth by sending a 200 response code.

To test it, I have these cache-related lines in my virtual host definition:

CacheRoot C:/temp
CacheEnable disk /

And this PHP file called index.php in /:


/* Generate our ETag. Assume that generating the ETag is
  * a whole lot less expensive than generating the content
  * (e.g. it could be based on revision counts for documents
  * from a database).

header("Etag: $etag");
//Expires ages away
header("Expires: " . gmdate("D, d M Y H:i:s", time()
	+ 60 * 60 * 24 * 30) . " GMT");

if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
	$_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {

	/* At a users' request, the cache has been bypassed, but the
	 * document is still the same. Avoid costly response generation
	 * and waste of bandwidth by just sending not-modified.
	header('HTTP/1.0 304 Not Modified');
	error_log(date('r')." - Response: 304 Not Modified\n");
	exit(); //Don't generate or send the body

error_log(date('r')." - Response: 200. Generated document.\n");

echo "Document body goes here";


My web browser requests the document the first time, the (trimmed) 
response is:

Status=OK - 200
Date=Mon, 20 Jul 2009 07:16:05 GMT
Expires=Wed, 19 Aug 2009 07:16:05 GMT

The log performed by index.php indicates:

Mon, 20 Jul 2009 19:16:05 +1200 - Response: 200. Generated document.

So far so good. But now I press refresh in my web browser. This makes a 
conditional request for the document:


With the max-age of 0, the cache will be bypassed, which is the desired 
behaviour. The cache passes this conditional request onto the backend, 
and the backend logs it:

Mon, 20 Jul 2009 19:16:12 +1200 - Response: 304 Not Modified

So the backend is trying to tell the client that it already has an 
up-to-date body. But the response sent to the browser by the caching 
system is:

Status=OK - 200
Date=Mon, 20 Jul 2009 07:16:12 GMT
Expires=Wed, 19 Aug 2009 07:16:12 GMT

My Apache is:

Apache/2.2.11 (Win32) DAV/2 mod_ssl/2.2.11 OpenSSL/0.9.8i SVN/1.6.3 

I found that I correctly got the 304 response code in my situation if I 
changed these lines (mod_cache.c:741):

/* We found a stale entry which wasn't really stale. */
if (cache->stale_handle) {
    /* Load in the saved status and clear the status line. */
    r->status = info->status;
    r->status_line = NULL;


/* We found a stale entry which wasn't really stale. */
if (cache->stale_handle) {
    /* Load in the saved status and clear the status line. */
    r->status = 304;
    r->status_line = NULL;

But that clearly doesn't work, even if the client sends an unconditional 
request it can end up getting a 304 response as a reply. I don't 
understand what is happening because this is the first time I've looked 
at the Apache codebase, let alone the mod_cache module. Can anyone who 
is more experienced with this module (and Apache in general) comment?

Nicholas Sherlock

View raw message