diff --git a/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php index fa844ae..8e8e885 100644 --- a/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php @@ -17,18 +17,8 @@ class CacheRouterRebuildSubscriber implements EventSubscriberInterface { */ public function onRouterFinished() { // Requested URLs that formerly gave a 403/404 may now be valid. - // Also invalidate all cached routing. - Cache::invalidateTags(['4xx-response', 'route_match']); - - // Invalidate full response caches. - // @todo Bubble up route_match to all responses. This though requires - // significant changes of various test coverage. - if ($cache = \Drupal::getContainer()->get('cache.dynamic_page_cache', ContainerInterface::NULL_ON_INVALID_REFERENCE)) { - $cache->invalidateAll(); - } - if ($cache = \Drupal::getContainer()->get('cache.render', ContainerInterface::NULL_ON_INVALID_REFERENCE)) { - $cache->invalidateAll(); - } + // Also invalidate all cached routing as well as every HTTP response. + Cache::invalidateTags(['4xx-response', 'route_match', 'http_response']); } /** diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 3db181a..418cb59 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -139,7 +139,12 @@ public function onRespond(FilterResponseEvent $event) { // Expose the cache contexts and cache tags associated with this page in a // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. $response_cacheability = $response->getCacheableMetadata(); - $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $response_cacheability->getCacheTags())); + $tags = $response_cacheability->getCacheTags(); + // Always add the 'http_response' cache tag to be able to invalidate every + // response. + $tags[] = 'http_response'; + + $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $tags)); $response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $this->cacheContextsManager->optimizeTokens($response_cacheability->getCacheContexts()))); } diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index 7471875..17e9091 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -248,6 +248,7 @@ protected function getNormalizedPatchEntity() { protected function getExpectedCacheTags() { $expected_cache_tags = [ 'config:rest.resource.entity.' . static::$entityTypeId, + 'http_response', ]; if (!static::$auth) { $expected_cache_tags[] = 'config:user.role.anonymous'; diff --git a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php index 3a7bc67..8dabbc7 100644 --- a/core/modules/search/src/Tests/SearchPageCacheTagsTest.php +++ b/core/modules/search/src/Tests/SearchPageCacheTagsTest.php @@ -190,10 +190,8 @@ public function testSearchTagsBubbling() { 'node:2', 'user:3', 'node_view', - 'config:filter.format.plain_text', ]); - $cache_tags = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertEqual(explode(' ', $cache_tags), $expected_cache_tags); + $this->assertCacheTags($expected_cache_tags); // Only get the new node in the search results, should result in node:1, // node:2 and user:3 as cache tags even though only node:1 is shown. This is @@ -208,8 +206,7 @@ public function testSearchTagsBubbling() { 'user:3', 'node_view', ]); - $cache_tags = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertEqual(explode(' ', $cache_tags), $expected_cache_tags); + $this->assertCacheTags($expected_cache_tags); } } diff --git a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php index 94ea1ac..2cad744 100644 --- a/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php +++ b/core/modules/system/src/Tests/Cache/AssertPageCacheContextsAndTagsTrait.php @@ -124,6 +124,7 @@ protected function assertCacheTags(array $expected_tags, $include_default_tags = // The anonymous role cache tag is only added if the user is anonymous. if ($include_default_tags && \Drupal::currentUser()->isAnonymous()) { $expected_tags = Cache::mergeTags($expected_tags, ['config:user.role.anonymous']); + $expected_tags[] = 'http_response'; } $actual_tags = $this->getCacheHeaderValues('X-Drupal-Cache-Tags'); sort($expected_tags); diff --git a/core/modules/system/src/Tests/Routing/RouterTest.php b/core/modules/system/src/Tests/Routing/RouterTest.php index 1b33baf..49300c0 100644 --- a/core/modules/system/src/Tests/Routing/RouterTest.php +++ b/core/modules/system/src/Tests/Routing/RouterTest.php @@ -45,7 +45,7 @@ public function testFinishResponseSubscriber() { // Check expected headers from FinishResponseSubscriber. $headers = $this->drupalGetHeaders(); $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', $expected_cache_contexts)); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous rendered'); + $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous rendered http_response'); // Confirm that the page wrapping is being added, so we're not getting a // raw body returned. $this->assertRaw('', 'Page markup was found.'); @@ -60,12 +60,12 @@ public function testFinishResponseSubscriber() { $this->drupalGet('router_test/test18'); $headers = $this->drupalGetHeaders(); $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url']))); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered'); + $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered http_response'); // 2. controller result: render array, per-role cacheable route access. $this->drupalGet('router_test/test19'); $headers = $this->drupalGetHeaders(); $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url', 'user.roles']))); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered'); + $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo rendered http_response'); // 3. controller result: Response object, globally cacheable route access. $this->drupalGet('router_test/test1'); $headers = $this->drupalGetHeaders();