You are here

public function FinishResponseSubscriber::onRespond in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()

Sets extra headers on successful responses.

Parameters

\Symfony\Component\HttpKernel\Event\ResponseEvent $event: The event to process.

File

core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php, line 112

Class

FinishResponseSubscriber
Response subscriber to handle finished responses.

Namespace

Drupal\Core\EventSubscriber

Code

public function onRespond(ResponseEvent $event) {
  if (!$event
    ->isMainRequest()) {
    return;
  }
  $request = $event
    ->getRequest();
  $response = $event
    ->getResponse();

  // Set the X-UA-Compatible HTTP header to force IE to use the most recent
  // rendering engine.
  $response->headers
    ->set('X-UA-Compatible', 'IE=edge', FALSE);

  // Set the Content-language header.
  $response->headers
    ->set('Content-language', $this->languageManager
    ->getCurrentLanguage()
    ->getId());

  // Prevent browsers from sniffing a response and picking a MIME type
  // different from the declared content-type, since that can lead to
  // XSS and other vulnerabilities.
  // https://www.owasp.org/index.php/List_of_useful_HTTP_headers
  $response->headers
    ->set('X-Content-Type-Options', 'nosniff', FALSE);
  $response->headers
    ->set('X-Frame-Options', 'SAMEORIGIN', FALSE);

  // Add a Permissions-Policy header to block Federated Learning of Cohorts.
  if (Settings::get('block_interest_cohort', TRUE) && !$response->headers
    ->has('Permissions-Policy')) {
    $response->headers
      ->set('Permissions-Policy', 'interest-cohort=()');
  }

  // If the current response isn't an implementation of the
  // CacheableResponseInterface, we assume that a Response is either
  // explicitly not cacheable or that caching headers are already set in
  // another place.
  if (!$response instanceof CacheableResponseInterface) {
    if (!$this
      ->isCacheControlCustomized($response)) {
      $this
        ->setResponseNotCacheable($response, $request);
    }

    // HTTP/1.0 proxies do not support the Vary header, so prevent any caching
    // by sending an Expires date in the past. HTTP/1.1 clients ignore the
    // Expires header if a Cache-Control: max-age directive is specified (see
    // RFC 2616, section 14.9.3).
    if (!$response->headers
      ->has('Expires')) {
      $this
        ->setExpiresNoCache($response);
    }
    return;
  }
  if ($this->debugCacheabilityHeaders) {

    // 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();
    $cache_tags = $response_cacheability
      ->getCacheTags();
    sort($cache_tags);
    $response->headers
      ->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
    $cache_contexts = $this->cacheContextsManager
      ->optimizeTokens($response_cacheability
      ->getCacheContexts());
    sort($cache_contexts);
    $response->headers
      ->set('X-Drupal-Cache-Contexts', implode(' ', $cache_contexts));
    $max_age_message = $response_cacheability
      ->getCacheMaxAge();
    if ($max_age_message === 0) {
      $max_age_message = '0 (Uncacheable)';
    }
    elseif ($max_age_message === -1) {
      $max_age_message = '-1 (Permanent)';
    }
    $response->headers
      ->set('X-Drupal-Cache-Max-Age', $max_age_message);
  }
  $is_cacheable = $this->requestPolicy
    ->check($request) === RequestPolicyInterface::ALLOW && $this->responsePolicy
    ->check($response, $request) !== ResponsePolicyInterface::DENY;

  // Add headers necessary to specify whether the response should be cached by
  // proxies and/or the browser.
  if ($is_cacheable && $this->config
    ->get('cache.page.max_age') > 0) {
    if (!$this
      ->isCacheControlCustomized($response)) {

      // Only add the default Cache-Control header if the controller did not
      // specify one on the response.
      $this
        ->setResponseCacheable($response, $request);
    }
  }
  else {

    // If either the policy forbids caching or the sites configuration does
    // not allow to add a max-age directive, then enforce a Cache-Control
    // header declaring the response as not cacheable.
    $this
      ->setResponseNotCacheable($response, $request);
  }
}