@@ -38,13 +38,15 @@ to implement the validation model: ``ETag`` and ``Last-Modified``.
3838Validation with the ``ETag `` Header
3939-----------------------------------
4040
41- The ``ETag `` header is a string header (called the "entity-tag") that uniquely
42- identifies one representation of the target resource. It's entirely generated
43- and set by your application so that you can tell, for example, if the ``/about ``
44- resource that's stored by the cache is up-to-date with what your application
45- would return. An ``ETag `` is like a fingerprint and is used to quickly compare
46- if two different versions of a resource are equivalent. Like fingerprints,
47- each ``ETag `` must be unique across all representations of the same resource.
41+ The `HTTP ETag `_ ("entity-tag") header is an optional HTTP header whose value is
42+ an arbitrary string that uniquely identifies one representation of the target
43+ resource. It's entirely generated and set by your application so that you can
44+ tell, for example, if the ``/about `` resource that's stored by the cache is
45+ up-to-date with what your application would return.
46+
47+ An ``ETag `` is like a fingerprint and is used to quickly compare if two
48+ different versions of a resource are equivalent. Like fingerprints, each
49+ ``ETag `` must be unique across all representations of the same resource.
4850
4951To see a simple implementation, generate the ETag as the md5 of the content::
5052
@@ -72,6 +74,20 @@ method compares the ``If-None-Match`` header with the ``ETag`` response header.
7274If the two match, the method automatically sets the ``Response `` status code
7375to 304.
7476
77+ .. note ::
78+
79+ When using ``mod_deflate `` or ``mod_brotli `` in Apache 2.4, the original
80+ ``ETag `` value is modified (e.g. if ``ETag `` was ``foo ``, Apache turns it
81+ into ``foo-gzip `` or ``foo-br ``), which breaks the ETag-based validation.
82+
83+ You can control this behavior with the `DeflateAlterETag `_ and `BrotliAlterETag `_
84+ directives. Alternatively, you can use the following Apache configuration to
85+ keep both the original ETag and the modified one when compressing responses:
86+
87+ .. code-block :: apache
88+
89+ RequestHeader edit "If-None-Match" '^"((.*)-(gzip|br))"$' '"$1", "$2"'
90+
7591 .. note ::
7692
7793 The cache sets the ``If-None-Match `` header on the request to the ``ETag ``
@@ -219,3 +235,6 @@ headers that must not be present for ``304`` responses (see
219235:method: `Symfony\\ Component\\ HttpFoundation\\ Response::setNotModified `).
220236
221237.. _`expiration model` : https://tools.ietf.org/html/rfc2616#section-13.2
238+ .. _`HTTP ETag` : https://en.wikipedia.org/wiki/HTTP_ETag
239+ .. _`DeflateAlterETag` : https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag
240+ .. _`BrotliAlterETag` : https://httpd.apache.org/docs/2.4/mod/mod_brotli.html#brotlialteretag
0 commit comments