Skip to content

Commit 0463ef0

Browse files
authored
Merge pull request #93 from sensiolabs/issue-10-cache
split the HTTP cache chapter
2 parents b3f6289 + 303f343 commit 0463ef0

File tree

8 files changed

+891
-1033
lines changed

8 files changed

+891
-1033
lines changed

cache/cache_invalidation.rst

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
.. index::
2+
single: Cache; Invalidation
3+
4+
.. _http-cache-invalidation:
5+
6+
Cache Invalidation
7+
~~~~~~~~~~~~~~~~~~
8+
9+
"There are only two hard things in Computer Science: cache invalidation
10+
and naming things." -- Phil Karlton
11+
12+
Once an URL is cached by a gateway cache, the cache will not ask the
13+
application for that content anymore. This allows the cache to provide fast
14+
responses and reduces the load on your application. However, you risk
15+
delivering outdated content. A way out of this dilemma is to use long
16+
cache lifetimes, but to actively notify the gateway cache when content
17+
changes. Reverse proxies usually provide a channel to receive such
18+
notifications, typically through special HTTP requests.
19+
20+
.. caution::
21+
22+
While cache invalidation is powerful, avoid it when possible. If you fail
23+
to invalidate something, outdated caches will be served for a potentially
24+
long time. Instead, use short cache lifetimes or use the validation model,
25+
and adjust your controllers to perform efficient validation checks as
26+
explained in :ref:`optimizing-cache-validation`.
27+
28+
Furthermore, since invalidation is a topic specific to each type of reverse
29+
proxy, using this concept will tie you to a specific reverse proxy or need
30+
additional efforts to support different proxies.
31+
32+
Sometimes, however, you need that extra performance you can get when
33+
explicitly invalidating. For invalidation, your application needs to detect
34+
when content changes and tell the cache to remove the URLs which contain
35+
that data from its cache.
36+
37+
.. tip::
38+
39+
If you want to use cache invalidation, have a look at the
40+
`FOSHttpCacheBundle`_. This bundle provides services to help with various
41+
cache invalidation concepts and also documents the configuration for a
42+
couple of common caching proxies.
43+
44+
If one content corresponds to one URL, the ``PURGE`` model works well.
45+
You send a request to the cache proxy with the HTTP method ``PURGE`` (using
46+
the word "PURGE" is a convention, technically this can be any string) instead
47+
of ``GET`` and make the cache proxy detect this and remove the data from the
48+
cache instead of going to the application to get a response.
49+
50+
Here is how you can configure the Symfony reverse proxy to support the
51+
``PURGE`` HTTP method::
52+
53+
// app/AppCache.php
54+
55+
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
56+
use Symfony\Component\HttpFoundation\Request;
57+
use Symfony\Component\HttpFoundation\Response;
58+
// ...
59+
60+
class AppCache extends HttpCache
61+
{
62+
protected function invalidate(Request $request, $catch = false)
63+
{
64+
if ('PURGE' !== $request->getMethod()) {
65+
return parent::invalidate($request, $catch);
66+
}
67+
68+
if ('127.0.0.1' !== $request->getClientIp()) {
69+
return new Response(
70+
'Invalid HTTP method',
71+
Response::HTTP_BAD_REQUEST
72+
);
73+
}
74+
75+
$response = new Response();
76+
if ($this->getStore()->purge($request->getUri())) {
77+
$response->setStatusCode(200, 'Purged');
78+
} else {
79+
$response->setStatusCode(404, 'Not found');
80+
}
81+
82+
return $response;
83+
}
84+
}
85+
86+
.. caution::
87+
88+
You must protect the ``PURGE`` HTTP method somehow to avoid random people
89+
purging your cached data.
90+
91+
**Purge** instructs the cache to drop a resource in *all its variants*
92+
(according to the ``Vary`` header, see above). An alternative to purging is
93+
**refreshing** a content. Refreshing means that the caching proxy is
94+
instructed to discard its local cache and fetch the content again. This way,
95+
the new content is already available in the cache. The drawback of refreshing
96+
is that variants are not invalidated.
97+
98+
In many applications, the same content bit is used on various pages with
99+
different URLs. More flexible concepts exist for those cases:
100+
101+
* **Banning** invalidates responses matching regular expressions on the
102+
URL or other criteria;
103+
* **Cache tagging** lets you add a tag for each content used in a response
104+
so that you can invalidate all URLs containing a certain content.

cache/cache_vary.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
.. index::
2+
single: Cache; Vary
3+
single: HTTP headers; Vary
4+
5+
Varying the Response for HTTP Cache
6+
===================================
7+
8+
So far, it's been assumed that each URI has exactly one representation of the
9+
target resource. By default, HTTP caching is done by using the URI of the
10+
resource as the cache key. If two people request the same URI of a cacheable
11+
resource, the second person will receive the cached version.
12+
13+
Sometimes this isn't enough and different versions of the same URI need to
14+
be cached based on one or more request header values. For instance, if you
15+
compress pages when the client supports it, any given URI has two representations:
16+
one when the client supports compression, and one when it does not. This
17+
determination is done by the value of the ``Accept-Encoding`` request header.
18+
19+
In this case, you need the cache to store both a compressed and uncompressed
20+
version of the response for the particular URI and return them based on the
21+
request's ``Accept-Encoding`` value. This is done by using the ``Vary`` response
22+
header, which is a comma-separated list of different headers whose values
23+
trigger a different representation of the requested resource:
24+
25+
.. code-block:: text
26+
27+
Vary: Accept-Encoding, User-Agent
28+
29+
.. tip::
30+
31+
This particular ``Vary`` header would cache different versions of each
32+
resource based on the URI and the value of the ``Accept-Encoding`` and
33+
``User-Agent`` request header.
34+
35+
The ``Response`` object offers a clean interface for managing the ``Vary``
36+
header::
37+
38+
// set one vary header
39+
$response->setVary('Accept-Encoding');
40+
41+
// set multiple vary headers
42+
$response->setVary(array('Accept-Encoding', 'User-Agent'));
43+
44+
The ``setVary()`` method takes a header name or an array of header names for
45+
which the response varies.

0 commit comments

Comments
 (0)