You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":".symfony","path":".symfony","contentType":"directory"},{"name":"_build","path":"_build","contentType":"directory"},{"name":"_images","path":"_images","contentType":"directory"},{"name":"_includes","path":"_includes","contentType":"directory"},{"name":"bundles","path":"bundles","contentType":"directory"},{"name":"components","path":"components","contentType":"directory"},{"name":"configuration","path":"configuration","contentType":"directory"},{"name":"console","path":"console","contentType":"directory"},{"name":"contributing","path":"contributing","contentType":"directory"},{"name":"controller","path":"controller","contentType":"directory"},{"name":"create_framework","path":"create_framework","contentType":"directory"},{"name":"deployment","path":"deployment","contentType":"directory"},{"name":"doctrine","path":"doctrine","contentType":"directory"},{"name":"event_dispatcher","path":"event_dispatcher","contentType":"directory"},{"name":"form","path":"form","contentType":"directory"},{"name":"frontend","path":"frontend","contentType":"directory"},{"name":"getting_started","path":"getting_started","contentType":"directory"},{"name":"http_cache","path":"http_cache","contentType":"directory"},{"name":"introduction","path":"introduction","contentType":"directory"},{"name":"logging","path":"logging","contentType":"directory"},{"name":"messenger","path":"messenger","contentType":"directory"},{"name":"notifier","path":"notifier","contentType":"directory"},{"name":"profiler","path":"profiler","contentType":"directory"},{"name":"quick_tour","path":"quick_tour","contentType":"directory"},{"name":"reference","path":"reference","contentType":"directory"},{"name":"routing","path":"routing","contentType":"directory"},{"name":"security","path":"security","contentType":"directory"},{"name":"serializer","path":"serializer","contentType":"directory"},{"name":"service_container","path":"service_container","contentType":"directory"},{"name":"session","path":"session","contentType":"directory"},{"name":"setup","path":"setup","contentType":"directory"},{"name":"templating","path":"templating","contentType":"directory"},{"name":"testing","path":"testing","contentType":"directory"},{"name":"translation","path":"translation","contentType":"directory"},{"name":"validation","path":"validation","contentType":"directory"},{"name":"workflow","path":"workflow","contentType":"directory"},{"name":".doctor-rst.yaml","path":".doctor-rst.yaml","contentType":"file"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".symfony.cloud.yaml","path":".symfony.cloud.yaml","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"Dockerfile","path":"Dockerfile","contentType":"file"},{"name":"LICENSE.md","path":"LICENSE.md","contentType":"file"},{"name":"README.markdown","path":"README.markdown","contentType":"file"},{"name":"best_practices.rst","path":"best_practices.rst","contentType":"file"},{"name":"bundles.rst","path":"bundles.rst","contentType":"file"},{"name":"cache.rst","path":"cache.rst","contentType":"file"},{"name":"configuration.rst","path":"configuration.rst","contentType":"file"},{"name":"console.rst","path":"console.rst","contentType":"file"},{"name":"controller.rst","path":"controller.rst","contentType":"file"},{"name":"deployment.rst","path":"deployment.rst","contentType":"file"},{"name":"doctrine.rst","path":"doctrine.rst","contentType":"file"},{"name":"email.rst","path":"email.rst","contentType":"file"},{"name":"event_dispatcher.rst","path":"event_dispatcher.rst","contentType":"file"},{"name":"forms.rst","path":"forms.rst","contentType":"file"},{"name":"frontend.rst","path":"frontend.rst","contentType":"file"},{"name":"http_cache.rst","path":"http_cache.rst","contentType":"file"},{"name":"http_client.rst","path":"http_client.rst","contentType":"file"},{"name":"index.rst","path":"index.rst","contentType":"file"},{"name":"logging.rst","path":"logging.rst","contentType":"file"},{"name":"mailer.rst","path":"mailer.rst","contentType":"file"},{"name":"mercure.rst","path":"mercure.rst","contentType":"file"},{"name":"messenger.rst","path":"messenger.rst","contentType":"file"},{"name":"migration.rst","path":"migration.rst","contentType":"file"},{"name":"notifier.rst","path":"notifier.rst","contentType":"file"},{"name":"page_creation.rst","path":"page_creation.rst","contentType":"file"},{"name":"performance.rst","path":"performance.rst","contentType":"file"},{"name":"profiler.rst","path":"profiler.rst","contentType":"file"},{"name":"routing.rst","path":"routing.rst","contentType":"file"},{"name":"security.rst","path":"security.rst","contentType":"file"},{"name":"serializer.rst","path":"serializer.rst","contentType":"file"},{"name":"service_container.rst","path":"service_container.rst","contentType":"file"},{"name":"session.rst","path":"session.rst","contentType":"file"},{"name":"setup.rst","path":"setup.rst","contentType":"file"},{"name":"templates.rst","path":"templates.rst","contentType":"file"},{"name":"testing.rst","path":"testing.rst","contentType":"file"},{"name":"translation.rst","path":"translation.rst","contentType":"file"},{"name":"validation.rst","path":"validation.rst","contentType":"file"},{"name":"web_link.rst","path":"web_link.rst","contentType":"file"},{"name":"workflow.rst","path":"workflow.rst","contentType":"file"}],"totalCount":81}},"fileTreeProcessingTime":3.9356599999999995,"foldersToFetch":[],"incompleteFileTree":false,"repo":{"id":521583,"defaultBranch":"7.3","name":"symfony-docs","ownerLogin":"symfony","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2010-02-17T08:43:51.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/143937?v=4","public":true,"private":false,"isOrgOwned":true},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"5.0","listCacheKey":"v0:1751870253.0","canEdit":false,"refType":"branch","currentOid":"480669b460d0ed2d0d0a7222505111587d8ab24c"},"path":"http_cache.rst","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/symfony/symfony-docs/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"http_cache.rst","displayUrl":"https://github.com/symfony/symfony-docs/blob/5.0/http_cache.rst?raw=true","headerInfo":{"blobSize":"14.7 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"22b503d","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fsymfony%2Fsymfony-docs%2Fblob%2F5.0%2Fhttp_cache.rst","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"HTTP Cache","anchor":"http-cache","htmlText":"HTTP Cache"},{"level":3,"text":"Caching on the Shoulders of Giants","anchor":"caching-on-the-shoulders-of-giants","htmlText":"Caching on the Shoulders of Giants"},{"level":3,"text":"Caching with a Gateway Cache","anchor":"caching-with-a-gateway-cache","htmlText":"Caching with a Gateway Cache"},{"level":4,"text":"Symfony Reverse Proxy","anchor":"symfony-reverse-proxy","htmlText":"Symfony Reverse Proxy"},{"level":3,"text":"Making your Responses HTTP Cacheable","anchor":"making-your-responses-http-cacheable","htmlText":"Making your Responses HTTP Cacheable"},{"level":4,"text":"Expiration Caching","anchor":"expiration-caching","htmlText":"Expiration Caching"},{"level":4,"text":"Validation Caching","anchor":"validation-caching","htmlText":"Validation Caching"},{"level":4,"text":"Safe Methods: Only caching GET or HEAD requests","anchor":"safe-methods-only-caching-get-or-head-requests","htmlText":"Safe Methods: Only caching GET or HEAD requests"},{"level":4,"text":"More Response Methods","anchor":"more-response-methods","htmlText":"More Response Methods"},{"level":3,"text":"Cache Invalidation","anchor":"cache-invalidation","htmlText":"Cache Invalidation"},{"level":3,"text":"Using Edge Side Includes","anchor":"using-edge-side-includes","htmlText":"Using Edge Side Includes"},{"level":3,"text":"HTTP Caching and User Sessions","anchor":"http-caching-and-user-sessions","htmlText":"HTTP Caching and User Sessions"},{"level":3,"text":"Summary","anchor":"summary","htmlText":"Summary"},{"level":3,"text":"Learn more","anchor":"learn-more","htmlText":"Learn more"}],"lineInfo":{"truncatedLoc":"420","truncatedSloc":"301"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"reStructuredText","languageID":419,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/symfony/symfony-docs/blob/5.0/http_cache.rst","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/symfony/symfony-docs/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/symfony/symfony-docs/raw/refs/heads/5.0/http_cache.rst","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cpre\u003e.. index::\n single: Cache\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-http-cache\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHTTP Cache\u003c/h2\u003e\u003ca id=\"user-content-http-cache\" class=\"anchor\" aria-label=\"Permalink: HTTP Cache\" href=\"#http-cache\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe nature of rich web applications means that they're dynamic. No matter\nhow efficient your application, each request will always contain more overhead\nthan serving a static file. Usually, that's fine. But when you need your requests\nto be lightning fast, you need HTTP caching.\u003c/p\u003e\n\u003ca name=\"user-content-caching-on-the-shoulders-of-giants\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCaching on the Shoulders of Giants\u003c/h3\u003e\u003ca id=\"user-content-caching-on-the-shoulders-of-giants\" class=\"anchor\" aria-label=\"Permalink: Caching on the Shoulders of Giants\" href=\"#caching-on-the-shoulders-of-giants\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWith HTTP Caching, you cache the full output of a page (i.e. the response) and bypass\nyour application \u003cem\u003eentirely\u003c/em\u003e on subsequent requests. Caching entire responses\nisn't always possible for highly dynamic sites, or is it? With\n\u003ca href=\"#id1\"\u003e\u003cspan id=\"user-content-id2\"\u003e:doc:`Edge Side Includes (ESI) \u0026lt;/http_cache/esi\u0026gt;`\u003c/span\u003e\u003c/a\u003e, you can use the power of HTTP caching\non only \u003cem\u003efragments\u003c/em\u003e of your site.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe Symfony cache system is different because it relies on the simplicity\nand power of the HTTP cache as defined in \u003ca href=\"https://tools.ietf.org/html/rfc7234\" rel=\"nofollow\"\u003eRFC 7234 - Caching\u003c/a\u003e. Instead of\nreinventing a caching methodology, Symfony embraces the standard that defines\nbasic communication on the Web. Once you understand the fundamental HTTP\nvalidation and expiration caching models, you'll be ready to master the Symfony\ncache system.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSince caching with HTTP isn't unique to Symfony, many articles already exist\non the topic. If you're new to HTTP caching, Ryan Tomayko's article\n\u003ca href=\"https://2ndscale.com/writings/things-caches-do\" rel=\"nofollow\"\u003eThings Caches Do\u003c/a\u003e is \u003cem\u003ehighly\u003c/em\u003e recommended. Another in-depth resource is Mark\nNottingham's \u003ca href=\"https://www.mnot.net/cache_docs/\" rel=\"nofollow\"\u003eCache Tutorial\u003c/a\u003e.\u003c/p\u003e\n\u003cpre\u003e.. index::\n single: Cache; Proxy\n single: Cache; Reverse proxy\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-caching-with-a-gateway-cache\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCaching with a Gateway Cache\u003c/h3\u003e\u003ca id=\"user-content-caching-with-a-gateway-cache\" class=\"anchor\" aria-label=\"Permalink: Caching with a Gateway Cache\" href=\"#caching-with-a-gateway-cache\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen caching with HTTP, the \u003cem\u003ecache\u003c/em\u003e is separated from your application entirely\nand sits between your application and the client making the request.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe job of the cache is to accept requests from the client and pass them\nback to your application. The cache will also receive responses back from\nyour application and forward them on to the client. The cache is the \"middle-man\"\nof the request-response communication between the client and your application.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAlong the way, the cache will store each response that is deemed \"cacheable\"\n(See \u003ca href=\"#id3\"\u003e\u003cspan id=\"user-content-id4\"\u003e:ref:`http-cache-introduction`\u003c/span\u003e\u003c/a\u003e). If the same resource is requested again,\nthe cache sends the cached response to the client, ignoring your application\nentirely.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis type of cache is known as an HTTP gateway cache and many exist such\nas \u003ca href=\"https://varnish-cache.org/\" rel=\"nofollow\"\u003eVarnish\u003c/a\u003e, \u003ca href=\"https://wiki.squid-cache.org/SquidFaq/ReverseProxy\" rel=\"nofollow\"\u003eSquid in reverse proxy mode\u003c/a\u003e, and the Symfony reverse proxy.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eGateway caches are sometimes referred to as reverse proxy caches,\nsurrogate caches, or even HTTP accelerators.\u003c/p\u003e\n\u003c/div\u003e\n\u003cpre\u003e.. index::\n single: Cache; Symfony reverse proxy\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-symfony-reverse-proxy\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSymfony Reverse Proxy\u003c/h4\u003e\u003ca id=\"user-content-symfony-reverse-proxy\" class=\"anchor\" aria-label=\"Permalink: Symfony Reverse Proxy\" href=\"#symfony-reverse-proxy\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSymfony comes with a reverse proxy (i.e. gateway cache) written in PHP.\n\u003ca href=\"#id5\"\u003e\u003cspan id=\"user-content-id6\"\u003e:ref:`It's not a fully-featured reverse proxy cache like Varnish \u0026lt;http-cache-symfony-versus-varnish\u0026gt;`\u003c/span\u003e\u003c/a\u003e,\nbut is a great way to start.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor details on setting up Varnish, see \u003ca href=\"#id7\"\u003e\u003cspan id=\"user-content-id8\"\u003e:doc:`/http_cache/varnish`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo enable the proxy, first create a caching kernel:\u003c/p\u003e\n\u003cpre\u003e// src/CacheKernel.php\nnamespace App;\n\nuse Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache;\n\nclass CacheKernel extends HttpCache\n{\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eModify the code of your front controller to wrap the default kernel into the\ncaching kernel:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// public/index.php\n\n+ use App\\CacheKernel;\nuse App\\Kernel;\n\n// ...\n$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);\n+ // Wrap the default Kernel with the CacheKernel one in 'prod' environment\n+ if ('prod' === $kernel-\u0026gt;getEnvironment()) {\n+ $kernel = new CacheKernel($kernel);\n+ }\n\n$request = Request::createFromGlobals();\n// ...\"\u003e\u003cpre\u003e// public/index.php\n\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003e use App\\CacheKernel;\u003c/span\u003e\nuse App\\Kernel;\n\n// ...\n$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003e // Wrap the default Kernel with the CacheKernel one in 'prod' environment\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003e if ('prod' === $kernel-\u0026gt;getEnvironment()) {\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003e $kernel = new CacheKernel($kernel);\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003e }\u003c/span\u003e\n\n$request = Request::createFromGlobals();\n// ...\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe caching kernel will immediately act as a reverse proxy: caching responses\nfrom your application and returning them to the client.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you're using the \u003ca href=\"#id9\"\u003e\u003cspan id=\"user-content-id10\"\u003e:ref:`framework.http_method_override \u0026lt;configuration-framework-http_method_override\u0026gt;`\u003c/span\u003e\u003c/a\u003e\noption to read the HTTP method from a \u003ccode\u003e_method\u003c/code\u003e parameter, see the\nabove link for a tweak you need to make.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe cache kernel has a special \u003ccode\u003egetLog()\u003c/code\u003e method that returns a string\nrepresentation of what happened in the cache layer. In the development\nenvironment, use it to debug and validate your cache strategy:\u003c/p\u003e\n\u003cpre\u003eerror_log($kernel-\u0026gt;getLog());\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eCacheKernel\u003c/code\u003e object has a sensible default configuration, but it can be\nfinely tuned via a set of options you can set by overriding the\n\u003ca href=\"#id11\"\u003e\u003cspan id=\"user-content-id12\"\u003e:method:`Symfony\\\\Bundle\\\\FrameworkBundle\\\\HttpCache\\\\HttpCache::getOptions`\u003c/span\u003e\u003c/a\u003e\nmethod:\u003c/p\u003e\n\u003cpre\u003e// src/CacheKernel.php\nnamespace App;\n\nuse Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache;\n\nclass CacheKernel extends HttpCache\n{\n protected function getOptions(): array\n {\n return [\n 'default_ttl' =\u0026gt; 0,\n // ...\n ];\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eFor a full list of the options and their meaning, see the\n\u003ca href=\"#id13\"\u003e\u003cspan id=\"user-content-id14\"\u003e:method:`HttpCache::__construct() documentation \u0026lt;Symfony\\\\Component\\\\HttpKernel\\\\HttpCache\\\\HttpCache::__construct\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhen you're in debug mode (the second argument of \u003ccode\u003eKernel\u003c/code\u003e constructor in the\nfront controller is \u003ccode\u003etrue\u003c/code\u003e), Symfony automatically adds an \u003ccode\u003eX-Symfony-Cache\u003c/code\u003e\nheader to the response. You can also use the \u003ccode\u003etrace_level\u003c/code\u003e config\noption and set it to either \u003ccode\u003enone\u003c/code\u003e, \u003ccode\u003eshort\u003c/code\u003e or \u003ccode\u003efull\u003c/code\u003e to\nadd this information.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eshort\u003c/code\u003e will add the information for the master request only.\nIt's written in a concise way that makes it easy to record the\ninformation in your server log files. For example, in Apache you can\nuse \u003ccode\u003e%{X-Symfony-Cache}o\u003c/code\u003e in \u003ccode\u003eLogFormat\u003c/code\u003e format statements.\nThis information can be used to extract general information about\ncache efficiency of your routes.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can change the name of the header used for the trace\ninformation using the \u003ccode\u003etrace_header\u003c/code\u003e config option.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv id=\"user-content-http-cache-symfony-versus-varnish\" dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eChanging from one Reverse Proxy to another\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe Symfony reverse proxy is a great tool to use when developing your\nwebsite or when you deploy your website to a shared host where you cannot\ninstall anything beyond PHP code. But being written in PHP, it cannot\nbe as fast as a proxy written in C.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFortunately, since all reverse proxies are effectively the same, you should\nbe able to switch to something more robust - like Varnish - without any problems.\nSee \u003ca href=\"#id15\"\u003e\u003cspan id=\"user-content-id16\"\u003e:doc:`How to use Varnish \u0026lt;/http_cache/varnish\u0026gt;`\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cpre\u003e.. index::\n single: Cache; HTTP\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-making-your-responses-http-cacheable\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMaking your Responses HTTP Cacheable\u003c/h3\u003e\u003ca id=\"user-content-making-your-responses-http-cacheable\" class=\"anchor\" aria-label=\"Permalink: Making your Responses HTTP Cacheable\" href=\"#making-your-responses-http-cacheable\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOnce you've added a reverse proxy cache (e.g. like the Symfony reverse proxy or Varnish),\nyou're ready to cache your responses. To do that, you need to \u003cem\u003ecommunicate\u003c/em\u003e to your\ncache \u003cem\u003ewhich\u003c/em\u003e responses are cacheable and for how long. This is done by setting HTTP\ncache headers on the response.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eHTTP specifies four response cache headers that you can set to enable caching:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eCache-Control\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eExpires\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eETag\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eLast-Modified\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eThese four headers are used to help cache your responses via \u003cem\u003etwo\u003c/em\u003e different models:\u003c/p\u003e\n\u003cspan id=\"user-content-http-expiration-validation\"\u003e\u003c/span\u003e\u003col id=\"user-content-http-expiration-and-validation\" dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#id17\"\u003e\u003cspan id=\"user-content-id18\"\u003e:ref:`Expiration Caching \u0026lt;http-cache-expiration-intro\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nUsed to cache your entire response for a specific amount of time (e.g. 24 hours).\nSimple, but cache invalidation is more difficult.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id19\"\u003e\u003cspan id=\"user-content-id20\"\u003e:ref:`Validation Caching \u0026lt;http-cache-validation-intro\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nMore complex: used to cache your response, but allows you to dynamically invalidate\nit as soon as your content changes.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eReading the HTTP Specification\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll of the HTTP headers you'll read about are \u003cem\u003enot\u003c/em\u003e invented by Symfony! They're\npart of an HTTP specification that's used by sites all over the web. To dig deeper\ninto HTTP Caching, check out the documents \u003ca href=\"https://tools.ietf.org/html/rfc7234\" rel=\"nofollow\"\u003eRFC 7234 - Caching\u003c/a\u003e and\n\u003ca href=\"https://tools.ietf.org/html/rfc7232\" rel=\"nofollow\"\u003eRFC 7232 - Conditional Requests\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAs a web developer, you are strongly urged to read the specification. Its\nclarity and power - even more than fifteen years after its creation - is\ninvaluable. Don't be put-off by the appearance of the spec - its contents\nare much more beautiful than its cover!\u003c/p\u003e\n\u003c/div\u003e\n\u003cpre\u003e.. index::\n single: Cache; Expiration\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-expiration-caching\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eExpiration Caching\u003c/h4\u003e\u003ca id=\"user-content-expiration-caching\" class=\"anchor\" aria-label=\"Permalink: Expiration Caching\" href=\"#expiration-caching\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003cem\u003eeasiest\u003c/em\u003e way to cache a response is by caching it for a specific amount of time:\u003c/p\u003e\n\u003cpre\u003e// src/Controller/BlogController.php\nuse Symfony\\Component\\HttpFoundation\\Response;\n// ...\n\npublic function index()\n{\n // somehow create a Response object, like by rendering a template\n $response = $this-\u0026gt;render('blog/index.html.twig', []);\n\n // cache publicly for 3600 seconds\n $response-\u0026gt;setPublic();\n $response-\u0026gt;setMaxAge(3600);\n\n // (optional) set a custom Cache-Control directive\n $response-\u0026gt;headers-\u0026gt;addCacheControlDirective('must-revalidate', true);\n\n return $response;\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThanks to this new code, your HTTP response will have the following header:\u003c/p\u003e\n\u003cpre lang=\"text\"\u003eCache-Control: public, maxage=3600, must-revalidate\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThis tells your HTTP reverse proxy to cache this response for 3600 seconds. If \u003cem\u003eanyone\u003c/em\u003e\nrequests this URL again before 3600 seconds, your application \u003cem\u003ewon't\u003c/em\u003e be hit at all.\nIf you're using the Symfony reverse proxy, look at the \u003ccode\u003eX-Symfony-Cache\u003c/code\u003e header\nfor debugging information about cache hits and misses.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe URI of the request is used as the cache key (unless you \u003ca href=\"#id21\"\u003e\u003cspan id=\"user-content-id22\"\u003e:doc:`vary \u0026lt;/http_cache/cache_vary\u0026gt;`\u003c/span\u003e\u003c/a\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis provides great performance and is simple to use. But, cache \u003cem\u003einvalidation\u003c/em\u003e\nis not supported. If your content change, you'll need to wait until your cache\nexpires for the page to update.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eActually, you \u003cem\u003ecan\u003c/em\u003e manually invalidate your cache, but it's not part of the\nHTTP Caching spec. See \u003ca href=\"#id23\"\u003e\u003cspan id=\"user-content-id24\"\u003e:ref:`http-cache-invalidation`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you need to set cache headers for many different controller actions, check out\n\u003ca href=\"https://foshttpcachebundle.readthedocs.org/\" rel=\"nofollow\"\u003eFOSHttpCacheBundle\u003c/a\u003e. It provides a way to define cache headers based on the URL\npattern and other request properties.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFinally, for more information about expiration caching, see \u003ca href=\"#id25\"\u003e\u003cspan id=\"user-content-id26\"\u003e:doc:`/http_cache/expiration`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-validation-caching\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eValidation Caching\u003c/h4\u003e\u003ca id=\"user-content-validation-caching\" class=\"anchor\" aria-label=\"Permalink: Validation Caching\" href=\"#validation-caching\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. index::\n single: Cache; Cache-Control header\n single: HTTP headers; Cache-Control\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWith expiration caching, you say \"cache for 3600 seconds!\". But, when someone\nupdates cached content, you won't see that content on your site until the cache\nexpires.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you need to see updated content \u003cem\u003eimmediately\u003c/em\u003e, you either need to\n\u003ca href=\"#id27\"\u003e\u003cspan id=\"user-content-id28\"\u003e:ref:`invalidate \u0026lt;http-cache-invalidation\u0026gt;`\u003c/span\u003e\u003c/a\u003e your cache \u003cem\u003eor\u003c/em\u003e use the validation\ncaching model.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor details, see \u003ca href=\"#id29\"\u003e\u003cspan id=\"user-content-id30\"\u003e:doc:`/http_cache/validation`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cpre\u003e.. index::\n single: Cache; Safe methods\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-safe-methods-only-caching-get-or-head-requests\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSafe Methods: Only caching GET or HEAD requests\u003c/h4\u003e\u003ca id=\"user-content-safe-methods-only-caching-get-or-head-requests\" class=\"anchor\" aria-label=\"Permalink: Safe Methods: Only caching GET or HEAD requests\" href=\"#safe-methods-only-caching-get-or-head-requests\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eHTTP caching only works for \"safe\" HTTP methods (like GET and HEAD). This means\ntwo things:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eDon't try to cache PUT or DELETE requests. It won't work and with good reason.\nThese methods are meant to be used when mutating the state of your application\n(e.g. deleting a blog post). Caching them would prevent certain requests from hitting\nand mutating your application.\u003c/li\u003e\n\u003cli\u003ePOST requests are generally considered uncacheable, but \u003ca href=\"https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-20#section-2.3.4\" rel=\"nofollow\"\u003ethey can be cached\u003c/a\u003e\nwhen they include explicit freshness information. However, POST caching is not\nwidely implemented, so you should avoid it if possible.\u003c/li\u003e\n\u003cli\u003eYou should \u003cem\u003enever\u003c/em\u003e change the state of your application (e.g. update a blog post)\nwhen responding to a GET or HEAD request. If those requests are cached, future\nrequests may not actually hit your server.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre\u003e.. index::\n pair: Cache; Configuration\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-more-response-methods\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMore Response Methods\u003c/h4\u003e\u003ca id=\"user-content-more-response-methods\" class=\"anchor\" aria-label=\"Permalink: More Response Methods\" href=\"#more-response-methods\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe Response class provides many more methods related to the cache. Here are\nthe most useful ones:\u003c/p\u003e\n\u003cpre\u003e// marks the Response stale\n$response-\u0026gt;expire();\n\n// forces the response to return a proper 304 response with no content\n$response-\u0026gt;setNotModified();\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAdditionally, most cache-related HTTP headers can be set via the single\n\u003ca href=\"#id31\"\u003e\u003cspan id=\"user-content-id32\"\u003e:method:`Symfony\\\\Component\\\\HttpFoundation\\\\Response::setCache`\u003c/span\u003e\u003c/a\u003e method:\u003c/p\u003e\n\u003cpre\u003e// sets cache settings in one call\n$response-\u0026gt;setCache([\n 'etag' =\u0026gt; $etag,\n 'last_modified' =\u0026gt; $date,\n 'max_age' =\u0026gt; 10,\n 's_maxage' =\u0026gt; 10,\n 'public' =\u0026gt; true,\n // 'private' =\u0026gt; true,\n]);\n\u003c/pre\u003e\n\u003ca name=\"user-content-cache-invalidation\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCache Invalidation\u003c/h3\u003e\u003ca id=\"user-content-cache-invalidation\" class=\"anchor\" aria-label=\"Permalink: Cache Invalidation\" href=\"#cache-invalidation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eCache invalidation is \u003cem\u003enot\u003c/em\u003e part of the HTTP specification. Still, it can be really\nuseful to delete various HTTP cache entries as soon as some content on your site\nis updated.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor details, see \u003ca href=\"#id33\"\u003e\u003cspan id=\"user-content-id34\"\u003e:doc:`/http_cache/cache_invalidation`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-using-edge-side-includes\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUsing Edge Side Includes\u003c/h3\u003e\u003ca id=\"user-content-using-edge-side-includes\" class=\"anchor\" aria-label=\"Permalink: Using Edge Side Includes\" href=\"#using-edge-side-includes\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen pages contain dynamic parts, you may not be able to cache entire pages,\nbut only parts of it. Read \u003ca href=\"#id35\"\u003e\u003cspan id=\"user-content-id36\"\u003e:doc:`/http_cache/esi`\u003c/span\u003e\u003c/a\u003e to find out how to configure\ndifferent cache strategies for specific parts of your page.\u003c/p\u003e\n\u003ca name=\"user-content-http-caching-and-user-sessions\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHTTP Caching and User Sessions\u003c/h3\u003e\u003ca id=\"user-content-http-caching-and-user-sessions\" class=\"anchor\" aria-label=\"Permalink: HTTP Caching and User Sessions\" href=\"#http-caching-and-user-sessions\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhenever the session is started during a request, Symfony turns the response\ninto a private non-cacheable response. This is the best default behavior to not\ncache private user information (e.g. a shopping cart, a user profile details,\netc.) and expose it to other visitors.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eHowever, even requests making use of the session can be cached under some\ncircumstances. For example, information related to some user group could be\ncached for all the users belonging to that group. Handling these advanced\ncaching scenarios is out of the scope of Symfony, but they can be solved with\nthe \u003ca href=\"https://foshttpcachebundle.readthedocs.org/\" rel=\"nofollow\"\u003eFOSHttpCacheBundle\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn order to disable the default Symfony behavior that makes requests using the\nsession uncacheable, add the following internal header to your response and\nSymfony won't modify it:\u003c/p\u003e\n\u003cpre\u003euse Symfony\\Component\\HttpKernel\\EventListener\\AbstractSessionListener;\n\n$response-\u0026gt;headers-\u0026gt;set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');\n\u003c/pre\u003e\n\u003ca name=\"user-content-summary\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSummary\u003c/h3\u003e\u003ca id=\"user-content-summary\" class=\"anchor\" aria-label=\"Permalink: Summary\" href=\"#summary\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSymfony was designed to follow the proven rules of the road: HTTP. Caching\nis no exception. Mastering the Symfony cache system means becoming familiar\nwith the HTTP cache models and using them effectively. This means that, instead\nof relying only on Symfony documentation and code examples, you have access\nto a world of knowledge related to HTTP caching and gateway caches such as\nVarnish.\u003c/p\u003e\n\u003ca name=\"user-content-learn-more\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLearn more\u003c/h3\u003e\u003ca id=\"user-content-learn-more\" class=\"anchor\" aria-label=\"Permalink: Learn more\" href=\"#learn-more\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. toctree::\n :maxdepth: 1\n :glob:\n\n http_cache/*\n\n\u003c/pre\u003e\n\n\u003c/article\u003e","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":8,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":"/symfony/.github/blob/6f2ca452c856184a28812bb364b4e34ed50309da/FUNDING.yml","showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":null},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"csrf_tokens":{"/symfony/symfony-docs/branches":{"post":"taeQltNpNPLwg3P-XA2ledfumwr5OKeYEvKM0Ad64tsRouSCzXLr4B4IeJvvJBFb36pGlp61jdujTVfdA5Zkkw"},"/repos/preferences":{"post":"hWxFNIUYwpTm26yi_5a3n1tyJU8oEVFnDpt23KPSl7zVK8-Eh1GA2D3DRjV0nefzDbz9npBgQ3pLEg7--QzwTA"}}},"title":"symfony-docs/http_cache.rst at 5.0 · symfony/symfony-docs","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-263cab1760dd.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-b84e9496fc59.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"react_blob_overlay":false,"accessible_code_button":true}}}