I _Really_ Don't Know

A low-frequency blog by Rob Styles

Anti-Cache

I got a call from a friend the other day with a little bugette on his secure site. Bits of it kept getting cached by the browser - he'd been through the problem with the team and it turned out that several chunks of code generating pages that should not be cached by the browser were forgetting to set the necessary headers.

We started talking and I suggested that actually the page code was the wrong place and that we should get it into one place - in the webserver.

To do this we slapped together a quick NSAPI SAF to add the headers we wanted - in this case Expires, Cache-Control and Pragma.

Here's a basic version of the code:


/*
* Development Environment:
*      Netscape Enterprise v3.6x
*      Solaris v2.6
*      Sun C++ v5.0
*
* Compile Notes:
* Run the following command in a directory
* containing this file (anticache.c).
*
*   export INC_DIR=/opt/app/netscape/suitespot/include
*   CC -compat=4 -DNET_SSL -DSOLARIS -D_REENTRANT
*                -DMCC_HTTPD -DXP_UNIX -DSPAPI20
*                -I$INC_DIR -I$INC_DIR/base
*                -I$INC_DIR/frame
*                anticache.c -G -o libanticache.so
*
* It is assumed that the Netscape install directory is
* /opt/app/netscape/suitespot/.
*/

#include <nsapi.h>

extern "C"
int anticache(pblock *pb, Session *sn, Request *rq)
{
char *path = pblock_findval("path", rq->vars);

if (shexp_cmp(path, "*.html") == 0) {
param_free(pblock_remove("Expires", rq->srvhdrs));
pblock_nvinsert("Expires",
"Sunday, 31 Dec 2000 23:59:59 GMT",
rq->srvhdrs);

param_free(pblock_remove("Cache-control", rq->srvhdrs));
pblock_nvinsert("Cache-control", "no-cache", rq->srvhdrs);

param_free(pblock_remove("Pragma", rq->srvhdrs));
pblock_nvinsert("Pragma", "no-cache", rq->srvhdrs);
}

return REQ_PROCEED;
}

Update: 2004-03-03 from Iain Hunneybell

This is so complex in comparison with Apache. I setup the same for [***] in Apache using the mod_headers module and all that requires is adding to the httpd.conf...


SetEnvIfNoCase Request_URI "\.gif$" allow-cache
SetEnvIfNoCase Request_URI "\.jpg$" allow-cache
SetEnvIfNoCase Request_URI "\.jpeg$" allow-cache
SetEnvIfNoCase Request_URI "\.pdf$" allow-cache
SetEnvIfNoCase Request_URI "\.doc$" allow-cache
SetEnvIfNoCase Request_URI "\.css$" allow-cache
SetEnvIfNoCase Request_URI "\.js$" allow-cache

Header set Cache-Control: no-cache env=!allow-cache
Header set Pragma: no-cache env=!allow-cache
Header set Expires: "01 Jan 1970 00:00:00 UT" env=!allow-cache

There's been a lot of discussion of the expires setting. -1 is usual but the RFC says it must be a date so we settled on the UNIX epoch date...

Note the exclusion of resource types like .gif, .jpg etc. in a fail safe form...i.e. you must explicitly exclude something else everything is marked no-cache