more on $r->finfo()

geoff on 2003-12-04T01:55:32

I forgot to mention last time that one of the main reasons I exposed $r->finfo was because it's required in order to do some 1.0-type manipulations.

in mod_perl 1.0, you could allow Apache's default content handler serve static files as a sort of caching mechanism. one example of this is Apache::CacheContent (which is based on the code here). the trick that makes it all work is that you write out a flat-file version of semi-dynamic content after URI translation then allow Apache to serve it as a flat file via

$r->filename($file);


now, the tricky part to this poor-man's caching is that Apache still thinks it has the result of it's default URI-to-filename translation, so not only does it serve your file up, but it also uses that file in decisions on whether to return HTTP_NOT_MODIFIED, which gives you an extra boost for little cost.



the thing is, Apache's default content handler does this

ap_update_mtime(r, r->finfo.mtime);


do you see it? you've updated $r->filename() but Apache is using $r->finfo->mtime() in it's decision on whether to send HTTP_NOT_MODIFIED.



mod_perl 1.0 adds a bit of magic behind the scenes so that calls to $r->filename() updates the underlying finfo structure as well. in mod_perl 2.0, there is less magic but more API exposure, which means you need to update the finfo data yourself. so, in mod_perl 2.0 the idiom looks like this

$r->filename($file);
$r->finfo->stat($file, APR::FINFO_NORM, $r->pool);


which first sets the filename then updates the file's finfo so that Apache uses the proper data in making its caching (and other) decisions.



I love this stuff.