diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php index b07f3e68c20..2c5eea96d4c 100644 --- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php @@ -54,7 +54,8 @@ class EntityResource extends ResourceBase { unset($entity->{$field_name}); } } - return new ResourceResponse($entity); + + return new ResourceResponse($entity, 200, ['X-Drupal-Cache-Tags' => implode(' ', $entity->getCacheTags())]); } /** diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index e2056692a1f..b962b3266f1 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -7,6 +7,7 @@ namespace Drupal\rest; +use Drupal\Core\Cache\Cache; use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; @@ -108,6 +109,14 @@ class RequestHandler implements ContainerAwareInterface { $output = $serializer->serialize($data, $format); $response->setContent($output); $response->headers->set('Content-Type', $request->getMimeType($format)); + // Add cache tags, but do not overwrite any that exist already on the + // response object. + $cache_tags = $this->container->get('config.factory')->get('rest.settings')->getCacheTags(); + if ($response->headers->has('X-Drupal-Cache-Tags')) { + $existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags')); + $cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags); + } + $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags)); } return $response; } diff --git a/core/modules/rest/src/Tests/PageCacheTest.php b/core/modules/rest/src/Tests/PageCacheTest.php new file mode 100644 index 00000000000..9cf2859ec37 --- /dev/null +++ b/core/modules/rest/src/Tests/PageCacheTest.php @@ -0,0 +1,61 @@ +enableService('entity:entity_test', 'GET'); + // Allow anonymous users to issue GET requests. + $permissions = $this->entityPermissions('entity_test', 'view'); + $permissions[] = 'restful get entity:entity_test'; + user_role_grant_permissions('anonymous', $permissions); + + // Create an entity programmatically. + $entity = $this->entityCreate('entity_test'); + $entity->save(); + // Read it over the REST API. + $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType); + $this->assertResponse(200, 'HTTP response code is correct.'); + $this->assertHeader('x-drupal-cache', 'MISS'); + $this->assertCacheTag('config:rest.settings'); + $this->assertCacheTag('entity_test:1'); + + // Read it again, should be page-cached now. + $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType); + $this->assertResponse(200, 'HTTP response code is correct.'); + $this->assertHeader('x-drupal-cache', 'HIT'); + $this->assertCacheTag('config:rest.settings'); + $this->assertCacheTag('entity_test:1'); + + // Trigger a config save which should clear the page cache, so we should get + // a cache miss now for the same request. + $this->config('rest.settings')->save(); + $this->httpRequest($entity->urlInfo(), 'GET', NULL, $this->defaultMimeType); + $this->assertResponse(200, 'HTTP response code is correct.'); + $this->assertHeader('x-drupal-cache', 'MISS'); + $this->assertCacheTag('config:rest.settings'); + $this->assertCacheTag('entity_test:1'); + } + +} diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php index e8e10803acd..ff382d5fd7a 100644 --- a/core/modules/rest/src/Tests/RESTTestBase.php +++ b/core/modules/rest/src/Tests/RESTTestBase.php @@ -154,12 +154,15 @@ abstract class RESTTestBase extends WebTestBase { } $response = $this->curlExec($curl_options); + + // Ensure that any changes to variables in the other thread are picked up. + $this->refreshVariables(); + $headers = $this->drupalGetHeaders(); - $headers = implode("\n", $headers); $this->verbose($method . ' request to: ' . $url . '