Incapsula does not obey "Cache-Control: private" directives
We use Incapsula as a reverse proxy for some of our sites, and recently ran into an issue with what appears to be a wilful violation of the HTTP specification by Incapsula.
Incapsula’s documentation says the following about how it handles Cache-Control headers:
Cache-Control - if it's set to no-cache / private / must-revalidate / proxy-revalidate/ no-store – then it'll prevent caching by Incapsula, unless site Acceleration Mode is set to Aggressive.
Unfortunately this isn’t the case. The following response headers from an origin server:
Cache-Control: max-age=86400, private
Content-Encoding: gzip
Content-Length: 2431
Content-Type: text/html; charset=utf-8
...
Get converted into this by Incapsula’s proxy:
Cache-Control: max-age=86398, public
Content-Encoding: gzip
Content-Length: 2431
Content-Type: text/html; charset=utf-8
...
This is a problem because what was meant to be a private resource has been cached and made public by Incapsula.
We contacted Incapsula to report this issue. This was the explanation we received:
private: Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache.
The max-age directive on a response implies that the response is cacheable (i.e., "public") unless some other, more restrictive cache directive is also present.
Since Incapsula is a CDN, which considers as a shared cache, the value of max-age=NUMBER and Cache-Control=private contradict each other and must not configured in this way.
The statement about max-age
implying that a resource is public is false. The HTTP specification explicitly allows private resources to have a max-age:
private
Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache MAY cache the response.
The correct behaviour would be for Incapsula to give the private
directive precendence over max-age
(rather than the other way around). Instead it takes the rather dangerous step of simply removing the private
directive!
In any case, the point is that Incapsula will violate a Cache-Control: private
directive unless you also set max-age=0
.