Caching pages with suffix paths in AEM and CQ dispatcher
Adobe CQ’s dispatcher module has a significant weakness when it comes to caching pages with a suffix path: always either the page itself or the suffix page path are not cached.
Out-of-the box, it’s not even possible to control which one is the cached page.
This post shows a simple way to achieve caching of all pages with and without suffix paths.
If we have a page at /content/blog/en/index.html, the dispatcher will cache this page in a file /path2/dispatcher/cache/content/blog/en/index.html
To make things interesting, we also serve this page with a suffix path at /content/blog/en/index.html/my/suffix.html
Dispatcher will try to cache the page with suffix in file /path2/dispatcher/cache/content/blog/en/index.html/my/suffix.html.
But wait, there is a problem: for the first page,
/path2 /dispatcher/cache/content/blog/en/index.html needs to be a file, for the second page /path2 /dispatcher/cache/content/blog/en/index.html/ must be a directory.
The dispatcher solves this out-of-the box by creating the appropriate file or directory for the resource that is requested first.
That resource will be served from cache from then on, while the other resource will be served from CQ.
Of course that is not what we want, but hey, it works, right?
There is one more glitch to it, however: If the page was first requested with the suffix path and the directory /path2/dispatcher/cache/content/blog/en/index.html/ has been created, any subsequent calls to /content/blog/en/index.html will result in a permanent redirect (HTTP 301) to /content/blog/en/index.html/ .
To fix this, we need two things:
- a rewrite rule on the HTTP server which adds a selector
- a Sling Filter which removes the selector again.
The rewrite rule is simple:
RewriteRule ^\.html/ .dir.html/
Of course you need to have the apache mod_rewrite module enabled for this.
Now all requests with suffix pages will have an additional dir selector by the time they hit the dispatcher, so the dispatcher caches them with the dir selector and our caching problems are solved.
We do not want the selector to be visible in our CQ components because that may impact the components and the selector may appear in subsequent links.
To achieve this, what we do in CQ is the following:
- create a high priority Sling-Filter
- check if the request contains the dir selector
- if yes, wrap the request with a custom implementation of the SlingHttpRequestWrapper that does nothing but hide the dir selector
And this is what the final solution looks like: For request with a suffix path, the dir selector is inserted so it is present on the dispatcher, then again it is hidden so it does not confuse CQ.