diff --git a/core/core.services.yml b/core/core.services.yml index 53a2725..ad08aff 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -196,6 +196,10 @@ services: factory_method: get factory_service: cache_factory arguments: [discovery] + cache_router_rebuild_subscriber: + class: Drupal\Core\EventSubscriber\CacheRouterRebuildSubscriber + tags: + - { name: event_subscriber } page_cache_request_policy: class: Drupal\Core\PageCache\DefaultRequestPolicy arguments: ['@session_configuration'] diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 742d361..f268fc3 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -494,7 +494,7 @@ protected function invalidateTagsOnSave($update) { // listing's filtering requirements. A newly created entity may start to // appear in listings because it did not exist before.) $tags = $this->getEntityType()->getListCacheTags(); - if ($this->hasLinkTemplate()) { + if ($this->hasLinkTemplate('canonical')) { // Creating or updating an entity may change a cached 403 or 404 response. $tags = Cache::mergeTags($tags, ['4xx-response']); } diff --git a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php index 4256c16..0b9584b 100644 --- a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php +++ b/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php @@ -10,6 +10,7 @@ use Drupal\Component\Datetime\DateTimePlus; use Drupal\Core\Routing\RequestContext; use Drupal\Core\Url; +use Drupal\entity_test\Entity\EntityTest; use Drupal\simpletest\WebTestBase; use Drupal\Core\Cache\Cache; use Drupal\user\Entity\Role; @@ -29,7 +30,7 @@ class PageCacheTest extends WebTestBase { * * @var array */ - public static $modules = array('test_page_test', 'system_test'); + public static $modules = array('test_page_test', 'system_test', 'entity_test'); protected function setUp() { parent::setUp(); @@ -308,6 +309,57 @@ function testPageCacheAnonymousRolePermissions() { } /** + * Tests the 4xx-response cache tag is added and invalidated. + */ + function testPageCacheAnonymous403404() { + $config = $this->config('system.performance'); + $config->set('cache.page.use_internal', 1); + $config->set('cache.page.max_age', 300); + $config->save(); + $admin_url = Url::fromRoute('system.admin'); + $invalid_url = 'foo/' . $this->randomString(); + $tests = [ + 403 => $admin_url, + 404 => $invalid_url, + ]; + foreach ($tests as $code => $content_url) { + // Anonymous user, without permissions. + $this->drupalGet($content_url); + $this->assertResponse($code); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS'); + $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); + $this->assertTrue(in_array('4xx-response', $cache_tags)); + $this->drupalGet($content_url); + $this->assertResponse($code); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT'); + $entity_values = array( + 'name' => $this->randomMachineName(), + 'user_id' => 1, + 'field_test_text' => array( + 0 => array( + 'value' => $this->randomString(), + 'format' => 'plain_text', + ) + ), + ); + $entity = EntityTest::create($entity_values); + $entity->save(); + // Saving an entity clears 4xx cache tag. + $this->drupalGet($content_url); + $this->assertResponse($code); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS'); + $this->drupalGet($content_url); + $this->assertResponse($code); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT'); + // Rebuilding the router should clear the 4xx cache tag. + $this->container->get('router.builder')->rebuild(); + $this->drupalGet($content_url); + $this->assertResponse($code); + $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS'); + } + } + + /** * Tests the omit_vary_cookie setting. */ public function testPageCacheWithoutVaryCookie() {