diff --git a/book/forms.rst b/book/forms.rst index 10c2efa43aa..b16a4751b4e 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -175,7 +175,7 @@ That's it! Just three lines are needed to render the complete form: Renders all the fields, which includes the field element itself, a label and any validation error messages for the field. -``form_end()`` +``form_end(form)`` Renders the end tag of the form and any fields that have not yet been rendered, in case you rendered each field yourself. This is useful for rendering hidden fields and taking advantage of the automatic diff --git a/book/http_cache.rst b/book/http_cache.rst index afe4ecf6e21..5cae7a710e2 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -383,6 +383,8 @@ This has two very reasonable consequences: blog post). Caching them would prevent certain requests from hitting and mutating your application. +.. _http-cache-defaults: + Caching Rules and Defaults ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/book/internals.rst b/book/internals.rst index e49b844635d..f0c1a86c2fd 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -375,7 +375,7 @@ The FrameworkBundle registers several listeners: *Event Class*: :class:`Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent` -The purpose of this event is to to handle tasks that should be performed after +The purpose of this event is to handle tasks that should be performed after the request has been handled but that do not need to modify the response. Event listeners for the ``kernel.finish_request`` event are called in both successful and exception cases. diff --git a/components/filesystem/introduction.rst b/components/filesystem/introduction.rst index 66e93c51263..fa7c0afbf06 100644 --- a/components/filesystem/introduction.rst +++ b/components/filesystem/introduction.rst @@ -31,7 +31,7 @@ endpoint for filesystem operations:: $fs = new Filesystem(); try { - $fs->mkdir('/tmp/random/dir/' . mt_rand()); + $fs->mkdir('/tmp/random/dir/'.mt_rand()); } catch (IOExceptionInterface $e) { echo "An error occurred while creating your directory at ".$e->getPath(); } @@ -52,7 +52,7 @@ mkdir ~~~~~ :method:`Symfony\\Component\\Filesystem\\Filesystem::mkdir` creates a directory. -On posix filesystems, directories are created with a default mode value +On POSIX filesystems, directories are created with a default mode value `0777`. You can use the second argument to set your own mode:: $fs->mkdir('/tmp/photos', 0700); diff --git a/cookbook/cache/varnish.rst b/cookbook/cache/varnish.rst index fc786329129..6e1ac0c32b7 100644 --- a/cookbook/cache/varnish.rst +++ b/cookbook/cache/varnish.rst @@ -60,6 +60,57 @@ 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`. +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 +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 `. In this situation, make sure to only +start a session when actually needed, and clear the session when it is no +longer needed. Alternatively, you can look into :doc:`../cache/form_csrf_caching`. + +.. todo link "only start a session when actually needed" to cookbook/session/avoid_session_start once https://github.com/symfony/symfony-docs/pull/4661 is merged + +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: + +.. code-block:: varnish4 + + sub vcl_recv { + // Remove all cookies except the session ID. + if (req.http.Cookie) { + set req.http.Cookie = ";" + req.http.Cookie; + set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); + set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1="); + set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); + set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); + + if (req.http.Cookie == "") { + // If there are no more cookies, remove the header to get page cached. + remove req.http.Cookie; + } + } + } + +.. tip:: + + If content is not different for every user, but depends on the roles of a + user, a solution is to separate the cache per group. This pattern is + implemented and explained by the FOSHttpCacheBundle_ under the name + `User Context`_. + Ensure Consistent Caching Behaviour ----------------------------------- @@ -176,8 +227,10 @@ proxy before it has expired, it adds complexity to your caching setup. .. _`Varnish`: https://www.varnish-cache.org .. _`Edge Architecture`: http://www.w3.org/TR/edge-arch .. _`GZIP and Varnish`: https://www.varnish-cache.org/docs/3.0/phk/gzip.html +.. _`Clean the cookies header`: https://www.varnish-cache.org/trac/wiki/VCLExampleRemovingSomeCookies .. _`Surrogate-Capability Header`: http://www.w3.org/TR/edge-arch .. _`cache invalidation`: http://tools.ietf.org/html/rfc2616#section-13.10 .. _`FOSHttpCacheBundle`: http://foshttpcachebundle.readthedocs.org/ .. _`default.vcl`: https://www.varnish-cache.org/trac/browser/bin/varnishd/default.vcl?rev=3.0 .. _`builtin.vcl`: https://www.varnish-cache.org/trac/browser/bin/varnishd/builtin.vcl?rev=4.0 +.. _`User Context`: http://foshttpcachebundle.readthedocs.org/en/latest/features/user-context.html