Verified Commit 19f80f65 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2951814 by wim leers, mxr576, vakulrai, claudiu.cristea, neclimdul,...

Issue #2951814 by wim leers, mxr576, vakulrai, claudiu.cristea, neclimdul, alexpott, sanjayk, joachim, chi, smustgrave: Improve X-Drupal-Cache and X-Drupal-Dynamic-Cache headers, even for responses that are not cacheable
parent 2853cf08
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ public function testBasicAuth(): void {
    $this->assertSession()->pageTextContains($account->getAccountName());
    $this->assertSession()->statusCodeEquals(200);
    $this->mink->resetSessions();
    $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache');
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'UNCACHEABLE (request policy)');
    // Check that Cache-Control is not set to public.
    $this->assertSession()->responseHeaderNotContains('Cache-Control', 'public');

@@ -87,7 +87,7 @@ public function testBasicAuth(): void {
    $this->drupalGet($url);
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'MISS');
    $this->basicAuthGet($url, $account->getAccountName(), $account->pass_raw);
    $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache');
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'UNCACHEABLE (request policy)');
    // Check that Cache-Control is not set to public.
    $this->assertSession()->responseHeaderNotContains('Cache-Control', 'public');
  }
+2 −1
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ public function testWatchdog(): void {
      "The 'restful get dblog' permission is required.",
      $response,
      ['4xx-response', 'http_response'],
      ['user.permissions']
      ['user.permissions'],
      'UNCACHEABLE (request policy)'
    );

    // Create a user account that has the required permissions to read
+14 −2
Original line number Diff line number Diff line
@@ -156,11 +156,18 @@ public function onRequest(RequestEvent $event) {
  public function onResponse(ResponseEvent $event) {
    $response = $event->getResponse();

    // Don't indicate non-cacheability on responses to uncacheable requests.
    // @see https://tools.ietf.org/html/rfc7231#section-4.2.3
    if (!$event->getRequest()->isMethodCacheable()) {
      return;
    }

    // Dynamic Page Cache only works with cacheable responses. It does not work
    // with plain Response objects. (Dynamic Page Cache needs to be able to
    // access and modify the cacheability metadata associated with the
    // response.)
    if (!$response instanceof CacheableResponseInterface) {
      $response->headers->set(self::HEADER, 'UNCACHEABLE (no cacheability)');
      return;
    }

@@ -172,7 +179,7 @@ public function onResponse(ResponseEvent $event) {
    // There's no work left to be done if this is an uncacheable response.
    if (!$this->shouldCacheResponse($response)) {
      // The response is uncacheable, mark it as such.
      $response->headers->set(self::HEADER, 'UNCACHEABLE');
      $response->headers->set(self::HEADER, 'UNCACHEABLE (poor cacheability)');
      return;
    }

@@ -195,7 +202,12 @@ public function onResponse(ResponseEvent $event) {
    // Don't cache the response if the Dynamic Page Cache request & response
    // policies are not met.
    // @see onRequest()
    if ($this->requestPolicyResults[$request] === RequestPolicyInterface::DENY || $this->responsePolicy->check($response, $request) === ResponsePolicyInterface::DENY) {
    if ($this->requestPolicyResults[$request] === RequestPolicyInterface::DENY) {
      $response->headers->set(self::HEADER, 'UNCACHEABLE (request policy)');
      return;
    }
    if ($this->responsePolicy->check($response, $request) === ResponsePolicyInterface::DENY) {
      $response->headers->set(self::HEADER, 'UNCACHEABLE (response policy)');
      return;
    }

+11 −10
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ public function testDynamicPageCache(): void {
    // Cache.
    $url = Url::fromUri('route:dynamic_page_cache_test.response');
    $this->drupalGet($url);
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (no cacheability)');

    // Controllers returning CacheableResponseInterface (cacheable response)
    // objects are handled by Dynamic Page Cache.
@@ -97,27 +97,28 @@ public function testDynamicPageCache(): void {
    // response, are ignored by Dynamic Page Cache (but only because those
    // wrapper formats' responses do not implement CacheableResponseInterface).
    $this->drupalGet('dynamic-page-cache-test/html', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->drupalGet('dynamic-page-cache-test/html', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog']]);
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (no cacheability)');
    $this->drupalGet('dynamic-page-cache-test/html', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]);
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (no cacheability)');

    // Admin routes are ignored by Dynamic Page Cache.
    $this->drupalGet('dynamic-page-cache-test/html/admin');
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (response policy)');
    $this->drupalGet('dynamic-page-cache-test/response/admin');
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    // Even this is an admin route, the lack of cacheability prevails in the
    // header explanation.
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (no cacheability)');
    $this->drupalGet('dynamic-page-cache-test/cacheable-response/admin');
    $this->assertSession()->responseHeaderDoesNotExist(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (response policy)');

    // Max-age = 0 responses are ignored by Dynamic Page Cache.
    $this->drupalGet('dynamic-page-cache-test/html/uncacheable/max-age');
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE');
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (poor cacheability)');

    // 'user' cache context responses are ignored by Dynamic Page Cache.
    $this->drupalGet('dynamic-page-cache-test/html/uncacheable/contexts');
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE');
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (poor cacheability)');

    // 'current-temperature' cache tag responses are ignored by Dynamic Page
    // Cache.
@@ -127,7 +128,7 @@ public function testDynamicPageCache(): void {
    // Route access checkers can also bubble up cacheability data.
    $this->drupalGet('/dynamic-page-cache-test/html/uncacheable/route-access');
    $this->assertSession()->responseHeaderExists(DynamicPageCacheSubscriber::HEADER);
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE');
    $this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'UNCACHEABLE (poor cacheability)');
  }

}
+1 −1
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ public function testPostFileUploadAndUseInSingleRequest(): void {
    // This request fails despite the upload succeeding, because we're not
    // allowed to view the entity we're uploading to.
    $response = $this->fileRequest($uri, $this->testFileData);
    $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('GET'), $uri, $response, FALSE, ['4xx-response', 'http_response'], ['url.query_args', 'url.site', 'user.permissions'], FALSE, 'UNCACHEABLE');
    $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('GET'), $uri, $response, FALSE, ['4xx-response', 'http_response'], ['url.query_args', 'url.site', 'user.permissions']);

    $this->setUpAuthorization('GET');

Loading