Skip to content

Reviewed Cache cookbook articles #5096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cookbook/cache/form_csrf_caching.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ validation when submitting the form.

In fact, many reverse proxies (like Varnish) will refuse to cache a page
with a CSRF token. This is because a cookie is sent in order to preserve
the PHP session open and Varnish's default behaviour is to not cache HTTP
the PHP session open and Varnish's default behavior is to not cache HTTP
requests with cookies.

How to Cache Most of the Page and still be able to Use CSRF Protection
Expand Down
68 changes: 30 additions & 38 deletions cookbook/cache/varnish.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,31 @@ cached content fast and including support for :ref:`Edge Side Includes <edge-sid
Make Symfony Trust the Reverse Proxy
------------------------------------

For ESI to work correctly and for the :ref:`X-FORWARDED <varnish-x-forwarded-headers>`
headers to be used, you need to configure Varnish as a
:doc:`trusted proxy </cookbook/request/load_balancer_reverse_proxy>`.
Varnish automatically forwards the IP as ``X-Forwarded-For`` and leaves the
``X-Forwarded-Proto`` header in the request. If you do not configure Varnish as
trusted proxy, Symfony will see all requests as coming through insecure HTTP
connections from the Varnish host instead of the real client.

Remember to configure :ref:`framework.trusted_proxies <reference-framework-trusted-proxies>`
in the Symfony configuration so that Varnish is seen as a trusted proxy and the
:ref:`X-Forwarded <varnish-x-forwarded-headers>` headers are used.

.. _varnish-x-forwarded-headers:

Routing and X-FORWARDED Headers
-------------------------------

To ensure that the Symfony Router generates URLs correctly with Varnish,
a ``X-Forwarded-Port`` header must be present for Symfony to use the
correct port number.
If the ``X-Forwarded-Port`` header is not set correctly, Symfony will append
the port where the PHP application is running when generating absolute URLs,
e.g. ``http://example.com:8080/my/path``. To ensure that the Symfony router
generates URLs correctly with Varnish, add the correct port number in the
``X-Forwarded-Port`` header. This port depends on your setup.

This port depends on your setup. Lets say that external connections come in
on the default HTTP port 80. For HTTPS connections, there is another proxy
(as Varnish does not do HTTPS itself) on the default HTTPS port 443 that
handles the SSL termination and forwards the requests as HTTP requests to
Varnish with a ``X-Forwarded-Proto`` header. In this case, you need to add
the following configuration snippet:
Suppose that external connections come in on the default HTTP port 80. For HTTPS
connections, there is another proxy (as Varnish does not do HTTPS itself) on the
default HTTPS port 443 that handles the SSL termination and forwards the requests
as HTTP requests to Varnish with a ``X-Forwarded-Proto`` header. In this case,
add the following to your Varnish configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should first say that the terminator should set this header, and varnish will forward the headers to the application. that would be the right place for this. and only if the proxy in front of varnish can not be made to set the headers, one can hack them into varnish.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbu You're referring specifically to the X-Forwarded-Port, correct? In other words, the proxy that is terminating the SSL should set the X-Forwarded-Proto AND the X-Forwarded-Port headers. But in case X-Forwarded-Port is not set by that layer for some reason, you can add the below hack to Varnish so that it adds it.

Am I correct? Thx :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weaverryan yep, exactly, that is what i mean.


.. code-block:: varnish4

Expand All @@ -45,45 +51,30 @@ the following configuration snippet:
}
}

.. note::

Remember to configure :ref:`framework.trusted_proxies <reference-framework-trusted-proxies>`
in the Symfony configuration so that Varnish is seen as a trusted proxy
and the ``X-Forwarded-*`` headers are used.

Varnish automatically forwards the IP as ``X-Forwarded-For`` and leaves
the ``X-Forwarded-Proto`` header in the request. If you do not configure
Varnish as trusted proxy, Symfony will see all requests as coming through
insecure HTTP connections from the Varnish host instead of the real client.

If the ``X-Forwarded-Port`` header is not set correctly, Symfony will append
the port where the PHP application is running when generating absolute URLs,
e.g. ``http://example.com:8080/my/path``.

Cookies and Caching
-------------------

By default, a sane caching proxy does not cache anything when a request is sent
with :ref:`cookies or a basic authentication header<http-cache-introduction>`.
with :ref:`cookies or a basic authentication header <http-cache-introduction>`.
This is because the content of the page is supposed to depend on the cookie
value or authentication header.

If you know for sure that the backend never uses sessions or basic
authentication, have varnish remove the corresponding header from requests to
authentication, have Varnish remove the corresponding header from requests to
prevent clients from bypassing the cache. In practice, you will need sessions
at least for some parts of the site, e.g. when using forms with
:ref:`CSRF Protection <forms-csrf>`. In this situation, make sure to
:doc:`only start a session when actually needed </cookbook/session/avoid_session_start>`
and clear the session when it is no longer needed. Alternatively, you can look
into :doc:`/cookbook/cache/form_csrf_caching`.

Cookies created in Javascript and used only in the frontend, e.g. when using
Google analytics are nonetheless sent to the server. These cookies are not
Cookies created in JavaScript and used only in the frontend, e.g. when using
Google Analytics, are nonetheless sent to the server. These cookies are not
relevant for the backend and should not affect the caching decision. Configure
your Varnish cache to `clean the cookies header`_. You want to keep the
session cookie, if there is one, and get rid of all other cookies so that pages
are cached if there is no active session. Unless you changed the default
configuration of PHP, your session cookie has the name PHPSESSID:
configuration of PHP, your session cookie has the name ``PHPSESSID``:

.. code-block:: varnish4

Expand All @@ -110,8 +101,8 @@ configuration of PHP, your session cookie has the name PHPSESSID:
implemented and explained by the FOSHttpCacheBundle_ under the name
`User Context`_.

Ensure Consistent Caching Behaviour
-----------------------------------
Ensure Consistent Caching Behavior
----------------------------------

Varnish uses the cache headers sent by your application to determine how
to cache content. However, versions prior to Varnish 4 did not respect
Expand Down Expand Up @@ -143,7 +134,7 @@ using Varnish 3:
Enable Edge Side Includes (ESI)
-------------------------------

As explained in the :ref:`Edge Side Includes section<edge-side-includes>`,
As explained in the :ref:`Edge Side Includes section <edge-side-includes>`,
Symfony detects whether it talks to a reverse proxy that understands ESI or
not. When you use the Symfony reverse proxy, you don't need to do anything.
But to make Varnish instead of Symfony resolve the ESI tags, you need some
Expand All @@ -168,10 +159,11 @@ application:

.. note::

The ``abc`` part of the header isn't important unless you have multiple "surrogates"
that need to advertise their capabilities. See `Surrogate-Capability Header`_ for details.
The ``abc`` part of the header isn't important unless you have multiple
"surrogates" that need to advertise their capabilities. See
`Surrogate-Capability Header`_ for details.

Then, optimize Varnish so that it only parses the Response contents when there
Then, optimize Varnish so that it only parses the response contents when there
is at least one ESI tag by checking the ``Surrogate-Control`` header that
Symfony adds automatically:

Expand Down