CherryPy Static Tool with Caching Tool

I wrote a bug report to cherrypy-devel.

Already, I have my own fix inn Unguent.

Here is the report for the recored.

I found that using Static Tool with Caching Tool doesn't work well,
in some situations.

I am using version 3.1.2, and checked the code in the repository
(trunk) as well.

Note that when we use cherrypy.tools.staticdir.handler or staticfile.handler directly, with Caching Tool, it works well.

Suppose we have a configuration like this:
-------------------------
[/]
tools.caching.on = True

[/robots.txt]
tools.staticfile.on = True
tools.staticfile.filename = 'site/robots.txt'
-------------------------

Then, staticfile is always called, even though it cached as well.

That's because both of Static Tool and Caching Tool use
'before_handler' hook.

The logic of Caching Tool is that, it disable request.handler when it
founds a page in cache.  The code is:

-------------------------  root/trunk/py3/cherrypy/_cptools.py
389   class CachingTool(Tool):
390       """Caching Tool for CherryPy."""
391
392       def _wrapper(self, **kwargs):
393           request = cherrypy.serving.request
394           if _caching.get(**kwargs):
395               request.handler = None
396           else:
397               if request.cacheable:
398                   # Note the devious technique here of adding hooks on the fly
399                   request.hooks.attach('before_finalize', _caching.tee_output,
400                                        priority = 90)
-------------------------

(BTW, should _caching.get be self.callable here?)

It doesn't stop Static Tool's 'before_handler' hook to be called.

I think that possible fix would be:

(1) Let staticdir or staticfile check if request.handler == None or not.

(2) Then, modify lib/caching.py:get(), so that it sets request.handler as
    well when it raises HTTPRedirect.  The place is here:

------------------------- root/trunk/py3/cherrypy/lib/caching.py
359           try:
360               # Note that validate_since depends on a Last-Modified header;
361               # this was put into the cached copy, and should have been
362               # resurrected just above (response.headers = cache_data[1]).
363               cptools.validate_since()
364           except cherrypy.HTTPRedirect:
365               x = sys.exc_info()[1]
366               if x.status == 304:
367                   cherrypy._cache.tot_non_modified += 1
+                     request.handler = None
368               raise
-------------------------
--