ETags#

ETags are used in to determine whether pages need to be re-calculated or can be served from cache. An ETag generated by plone.app.caching is a string of tokens separated by pipe characters that hold values like a user ID, the current skin name, or a counter indicating how many objects have been added to the site. This technique is used to quickly calculate the current ETag for the requested resource. The browser sends a request with the ETag included in an If-None-Match header. If the ETag is the same, then Plone responds with a 304 NOT MODIFIED message, indicating that the browser should use its cached copy. If the ETag is different, then Plone renders the page and returns it as usual.

Many caching operations use ETags. The tokens to include are typically listed in an etags tuple in the operation's options.

Default tokens#

The ETag token names supported by default are:

etag

description

userid

The current user's ID.

roles

A list of the current user's roles in the given context.

language

The language(s) accepted by the browser, in the ACCEPT_LANGUAGE header.

userLanguage

The current user's preferred language.

lastModified

A timestamp indicating the last-modified date of the given context.

catalogCounter

A counter that is incremented each time the catalog is updated, such as when content in the site is changed.

locked

Whether or not the given context is locked for editing.

skin

The name of the current skin (theme).

resourceRegistries

A timestamp indicating the last-modified timestamp for the Resource Registries. This is useful for avoiding requests for expired resources from cached pages.

Additional tokens#

It is possible to provide additional tokens by registering an IETagValue adapter.

This should be a named adapter on the published object (typically a view, file resource, or Zope page template object) and request, with a unique name.

The name is used to look up the component. Thus you can override one of the tokens above for a particular type of context or request, including via a browser layer, by registering a more specific adapter with the same name.

As an example, here is the language adapter.

from plone.app.caching.interfaces import IETagValue
from zope.component import adapter
from zope.interface import implementer
from zope.interface import Interface

@implementer(IETagValue)
@adapter(Interface, Interface)
class Language:
    """The `language` etag component, returning the value of the
    HTTP_ACCEPT_LANGUAGE request key.
    """

    def __init__(self, published, request):
        self.published = published
        self.request = request

    def __call__(self):
        return self.request.get('HTTP_ACCEPT_LANGUAGE', '')

This is registered in ZCML as shown below.

<adapter factory=".etags.Language" name="language" />