You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs@cocoon.apache.org by do...@cocoon.apache.org on 2004/11/06 16:40:56 UTC

[Cocoon Wiki] New: ControllingModCache

   Date: 2004-11-06T07:40:56
   Editor: BertrandDelacretaz <bd...@codeconsult.ch>
   Wiki: Cocoon Wiki
   Page: ControllingModCache
   URL: http://wiki.apache.org/cocoon/ControllingModCache

   ControllingModCache explains how to control mod_cache from Cocoon

New Page:

= How to control the caching of pages by mod_cache via HTTP headers =

Apache httpd mod_cache is a wonderful tool to dramatically enhance the performance of your Cocoon-based site.

For this we assume that httpd is configured to act as a reverse proxy, with mod_cache enabled (see ApacheModProxy).

This page explains how to generate the required HTTP headers for mod_cache to store the pages in its front-end cache, with some example code.

Mod_cache uses the standard HTTP protocol definitions to determine if and how long to cache pages, see the official mod_cache and HTTP protocol specs for more information.

== HTTP headers ==
For mod_cache to put a page in cache, Cocoon must generate the following HTTP headers:

 * Last-Modified
 * Expires
 * Cache-Control
 * Content-length

Except for Content-length, these must be generated by your Cocoon application, for example using an Action as shown below.

To generate Content-length, you must currently create your own serializer, to set the buffering flag, as it is not yet configurable.

Simply inherit from HTMLSerializer (for example) and add the following method:
{{{public boolean shouldSetContentLength() {
        return true;
    }
}}}

== Invalidating the cache ==
According to the HTTP caching specs, a POST on an URL must cause the cache to invalidate the page. This seems to work well with mod_cache, but I haven't used this function extensively.

== Example code ==
Here's some java code to set the required HTTP headers (except Content-Length, see above):
{{{
    public static final String LAST_MOD_HEADER = "Last-Modified";
    public static final String EXPIRES_HEADER = "Expires";
    public static final String CACHE_CONTROL_HEADER = "Cache-Control";

    /** set headers so that the response is cached for nSeconds
     *  @param lastModified if null, now - 2 seconds is used */
    public void setCacheHeaders(Response resp,Date lastModified,int cacheForHowMaySeconds) {

        final long lastModTime = (lastModified == null ? System.currentTimeMillis() - 2000L : lastModified.getTime());
        final long expires = System.currentTimeMillis() + (cacheForHowMaySeconds * 1000L);

        resp.addDateHeader(LAST_MOD_HEADER,lastModTime);
        resp.addDateHeader(EXPIRES_HEADER,expires);
        resp.addHeader(CACHE_CONTROL_HEADER,"max-age="+ cacheForHowMaySeconds);
    }
}}}

And here's code for a Cocoon Action through a helper which contains the above code:
{{{    
    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters)
            throws Exception {
        // parameters tell us how long to cache
        final int nSec = parameters.getParameterAsInteger("cache-validity-seconds",0);
        final String cacheInfo = parameters.getParameter("cache-info","NO-CACHE-INFO");
        final String pageInfo = parameters.getParameter("page-info","NO-PAGE-INFO");

        final HttpCacheHeadersHelper helper = new HttpCacheHeadersHelper(cacheInfo,getLogger());
        helper.setCacheHeaders(ObjectModelHelper.getResponse(objectModel),null,nSec,pageInfo);

        // don't execute what's inside this action, it's just here to set headers
        return null;
    }

}}}

Then, you only need to use the Action like this in a sitemap to setup page caching:
{{{<map:act type="http-cache-headers">
  <map:parameter name="cache-validity-seconds" value="30"/>
  <map:parameter name="cache-info" value="cache-name-for-logging"/>
  <map:parameter name="page-info" value="page-info-for-logging"/>
</map:act>
}}}