We're running Plone 4.1 with plone.app.caching behind Apache 2.2 with mod_cache and mod_disk_cache.
The pre-defined operations that are available with plone.app.c开发者_JS百科aching aren't quite suitable for this configuration as Apache won't cache responses if max-age=0, no matter what values you have set for Expires and s-max-age (I think this is contrary to the HTTP 1.1 specification). With Plone 3.3 and CacheFu it was a straight forward configuration change to get round this: set max-age=1 for the relevant header set. See this CacheFu issue
I'm looking for some advice to achieve the same thing with plone.app.caching. What's the simplest way to override the plone.app.caching.moderateCaching operation such that its maxage is set to 1 rather than 0?
We're not considering adding Squid or Varnish to our stack at this moment in time.
What you are requesting is actually strongCaching (but with a short expire) so use that instead. By definition, moderateCaching is designed to "cache in browser but expire immediately" -- in other words, max-age=0.
The three default caching operations -- strongCaching, moderateCaching, and weakCaching -- are just useful abstractions designed to make the choices involved in assigning caching policies easier to understand. If the abstractions don't help you, you can pretty much do mostly anything you need by just using strongCaching and changing the settings.
This is discussed in more detail in the plone.app.caching docs, http://pypi.python.org/pypi/plone.app.caching
That's all configurable policy. You can set it in the control panel, or (as I prefer) in a generic setup registry.xml. See the example policies in plone.app.caching.
Update:
The control panel attempts to simplify things by restricting what is set on the default caching policies. It's still possible to change these directly in the registry though, so you could use the following in your registry.xml:
<record name="plone.app.caching.moderateCaching.maxage">
<field type="plone.registry.field.Int">
<title>Maximum age</title>
<description>Time (in seconds) to cache the response in the browser or caching proxy</description>
<required>False</required>
</field>
<value>1</value>
</record>
Laurence located the relevant Apache bug for me https://issues.apache.org/bugzilla/show_bug.cgi?id=35247
As we build Apache ourselves we've decided to patch Apache instead and leave Plone alone although the patch is for trunk and so applying to the 2.2 code is a little tricky.
After much deliberation we've solved this with some Apache configuration. We modified the response headers to set max-age to be 1 if max-age = 0 and s-maxage is positive and then remove the expires header:
Header edit Cache-Control max-age=0(.*s-maxage=[1-9].*) max-age=1$1
Header unset Expires
This does the trick although HTTP 1.0 clients now won't know have Expires to base their caching on.
I guess the real answer here is probably that there's no easy way to do this at the moment. I've raised a Plone bug to allow max-age to be overriden with moderateCaching
So here's my solution, that works, but seems a lot of work compared to being able to override the default max age on moderate caching. I define my own caching operation, that extends plone.app.caching.operations.default.moderateCaching:
class CacheInApache(ModerateCaching):
""" Apache won't cache a response if max-age cache control is 0. Override ModerateCaching
and set it to 1 second.
"""
classProvides(ICachingOperationType)
title = _(u"Cache in Apache")
description = _(u"Moderate caching for Plone behind Apache. max-age set to 1")
prefix = 'cacheInApache'
maxage = 1
Register this in configure.zcml
<adapter factory=".operation.CacheInApache"
name="cacheInApache" />
<utility component=".operation.CacheInApache"
name="cacheInApache" />
Then in my generic setup profile registry.xml I configure my types to use it and define its fields.
<record name="plone.caching.interfaces.ICacheSettings.operationMapping">
<value purge="False">
<element key="plone.resource">plone.app.caching.strongCaching</element>
<element key="plone.stableResource">plone.app.caching.strongCaching</element>
<element key="plone.content.itemView">cacheInApache</element>
<element key="plone.content.feed">cacheInApache</element>
<element key="plone.content.folderView">cacheInApache</element>
<element key="plone.content.file">cacheInApache</element>
</value>
</record>
<record name="cacheInApache.smaxage">
<field type="plone.registry.field.Int">
<title>Shared maximum age</title>
<description>Time (in seconds) to cache the response in the caching proxy</description>
<required>False</required>
</field>
<value>86400</value>
</record>
<record name="cacheInApache.etags">
<field type="plone.registry.field.Tuple">
<title>ETags</title>
<description>A list of ETag component names to include</description>
<value_type type="plone.registry.field.ASCIILine" />
<required>False</required>
</field>
<value>
</value>
</record>
<record name="cacheInApache.lastModified">
<field type="plone.registry.field.Bool">
<title>Last-modified validation</title>
<description>Turn on Last-Modified headers</description>
<required>False</required>
</field>
<value>False</value>
</record>
<record name="cacheInApache.ramCache">
<field type="plone.registry.field.Bool">
<title>RAM cache</title>
<description>Turn on caching in Zope memory</description>
<required>False</required>
</field>
<value>False</value>
</record>
<record name="cacheInApache.vary">
<field type="plone.registry.field.ASCIILine">
<title>Vary</title>
<description>Name(s) of HTTP headers that must match for the caching proxy to return a cached response</description>
<required>False</required>
</field>
<value></value>
</record>
<record name="cacheInApache.anonOnly">
<field type="plone.registry.field.Bool">
<title>Only cache for anonymous users</title>
<description>Ensure logging users always get a fresh page. Note that if you are caching pages in a proxy cache, you'll still need to use a Vary response header to keep anonymous and authenticated content separate.</description>
<required>False</required>
</field>
<value>False</value>
</record>
You can also define some type specific overrides.
If anyone can suggest a simpler way to achieve this then please let me know
精彩评论