Skip to content

Commit c88ad32

Browse files
committed
explain how to work with cookies and sessions when caching
1 parent 9fee9ee commit c88ad32

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

book/http_cache.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ This has two very reasonable consequences:
383383
blog post). Caching them would prevent certain requests from hitting and
384384
mutating your application.
385385

386+
.. _http-cache-defaults:
387+
386388
Caching Rules and Defaults
387389
~~~~~~~~~~~~~~~~~~~~~~~~~~
388390

cookbook/cache/varnish.rst

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,87 @@ If the ``X-Forwarded-Port`` header is not set correctly, Symfony will append
6060
the port where the PHP application is running when generating absolute URLs,
6161
e.g. ``http://example.com:8080/my/path``.
6262

63+
Session Cookies and Caching
64+
---------------------------
65+
66+
By default, a sane caching proxy does not cache anything when a request is sent
67+
with :ref:`cookies or a basic authentication header<http-cache-introduction>`.
68+
This is because the content of the page is supposed to depend on the cookie
69+
value or authentication header.
70+
71+
If you know for sure that the backend never uses sessions or basic
72+
authentication, have varnish remove the corresponding header from requests to
73+
prevent clients from bypassing the cache. In practice, you will need sessions
74+
at least for some parts of the site, e.g. when using forms with
75+
:ref:`CSRF Protection <forms-csrf>`. In this situation, make sure to only
76+
start a session when actually needed, and clear the session when it is no
77+
longer needed.
78+
79+
.. todo link to cookbook/session/avoid_session_start once https://github.com/symfony/symfony-docs/pull/4661 is merged
80+
81+
Cookies can also be created in Javascript and used only in the frontend, e.g.
82+
Google analytics. These cookies do not matter for the backend and should not
83+
affect the caching decision. Configure your Varnish cache to
84+
`clean the cookies header`_. Unless you changed the PHP configuration, your session
85+
cookie has the name PHPSESSID:
86+
87+
.. code-block:: varnish4
88+
89+
sub vcl_recv {
90+
if (req.http.Cookie) {
91+
set req.http.Cookie = ";" + req.http.Cookie;
92+
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
93+
set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1=");
94+
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
95+
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
96+
97+
if (req.http.Cookie == "") {
98+
remove req.http.Cookie;
99+
}
100+
}
101+
}
102+
103+
If only small parts of your application depend on cookies (e.g. you display the
104+
username in the header), you can use :ref:`ESI <edge-side-includes>` for those
105+
fragments. Configure Varnish to store and look up requests in its cache even if
106+
Cookies are present in the request:
107+
108+
.. code-block:: varnish4
109+
110+
sub vcl_recv() {
111+
if (req.http.Cookie) {
112+
/* Force cache lookup for requests with cookies */
113+
return (lookup);
114+
}
115+
}
116+
117+
You need to make sure that your backend correctly sets the ``Vary`` header to
118+
tell which responses vary on the cookie and which are the same::
119+
120+
public function loginAction()
121+
{
122+
// ...
123+
$response->setVary('Cookie');
124+
// ...
125+
}
126+
127+
Only set the ``Vary: Cookie`` header on actions that actually depend on whether
128+
the user is logged in, but not on any other actions.
129+
130+
.. caution::
131+
132+
Be sure to test your setup. If you do not ``Vary`` content that depends on
133+
the session, users will see content from somebody else. If you ``Vary`` too
134+
much, the Varnish cache will be filled with duplicate content for every
135+
user, rendering the cache pointless as cache hits will become rare.
136+
137+
.. tip::
138+
139+
If content is not different for every user, but depends on the roles of a
140+
user, a solution is to separate the cache per group. This pattern is
141+
implemented and explained by the FOSHttpCacheBundle_ under the name
142+
*User Context*.
143+
63144
Ensure Consistent Caching Behaviour
64145
-----------------------------------
65146

@@ -169,6 +250,7 @@ proxy before it has expired, it adds complexity to your caching setup.
169250
.. _`Varnish`: https://www.varnish-cache.org
170251
.. _`Edge Architecture`: http://www.w3.org/TR/edge-arch
171252
.. _`GZIP and Varnish`: https://www.varnish-cache.org/docs/3.0/phk/gzip.html
253+
.. _`Clean the cookies header`: https://www.varnish-cache.org/trac/wiki/VCLExampleRemovingSomeCookies
172254
.. _`Surrogate-Capability Header`: http://www.w3.org/TR/edge-arch
173255
.. _`cache invalidation`: http://tools.ietf.org/html/rfc2616#section-13.10
174256
.. _`FOSHttpCacheBundle`: http://foshttpcachebundle.readthedocs.org/

0 commit comments

Comments
 (0)