isMethodCacheable example

    // request is unauthenticated (this 401) versus authenticated (some     // other response)     // 2. Have the 'config:user.role.anonymous' cache tag, because the only     // reason this 401 would no longer be a 401 is if permissions for the     // 'anonymous' role change, causing the cache tag to be invalidated.     // @see \Drupal\Core\EventSubscriber\AuthenticationSubscriber::onExceptionSendChallenge()     // @see \Drupal\Core\EventSubscriber\ClientErrorResponseSubscriber()     // @see \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onAllResponds()     $cacheability = CacheableMetadata::createFromObject($site_config)
      ->addCacheTags(['config:user.role.anonymous'])
      ->addCacheContexts(['user.roles:anonymous']);
    return $request->isMethodCacheable()
      ? new CacheableUnauthorizedHttpException($cacheability(string) $challenge, 'No authentication credentials provided.', $previous)
      : new UnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous);
  }

}
$this->cacheContextsManager = $cache_contexts_manager;
  }

  /** * {@inheritdoc} */
  public function get(array $elements) {
    // Form submissions rely on the form being built during the POST request,     // and render caching of forms prevents this from happening.     // @todo remove the isMethodCacheable() check when     // https://www.drupal.org/node/2367555 lands.     if (!$this->requestStack->getCurrentRequest()->isMethodCacheable() || !$cid = $this->createCacheID($elements)) {
      return FALSE;
    }
    $bin = $elements['#cache']['bin'] ?? 'render';

    if (!empty($cid) && ($cache_bin = $this->cacheFactory->get($bin)) && $cache = $cache_bin->get($cid)) {
      $cached_element = $cache->data;
      // Two-tier caching: redirect to actual (post-bubbling) cache item.       // @see \Drupal\Core\Render\RendererInterface::render()       // @see ::set()       if (isset($cached_element['#cache_redirect'])) {
        return $this->get($cached_element);
      }
/** * Determines if the Response validators (ETag, Last-Modified) match * a conditional value specified in the Request. * * If the Response is not modified, it sets the status code to 304 and * removes the actual content by calling the setNotModified() method. * * @final */
    public function isNotModified(Request $request): bool
    {
        if (!$request->isMethodCacheable()) {
            return false;
        }

        $notModified = false;
        $lastModified = $this->headers->get('Last-Modified');
        $modifiedSince = $request->headers->get('If-Modified-Since');

        if (($ifNoneMatchEtags = $request->getETags()) && (null !== $etag = $this->getEtag())) {
            if (0 == strncmp($etag, 'W/', 2)) {
                $etag = substr($etag, 2);
            }

            


    public function getListeners(): iterable
    {
        return [$this];
    }

    public function __invoke(RequestEvent $event): void
    {
        $listeners = [];
        $request = $event->getRequest();
        $lazy = $request->isMethodCacheable();

        foreach (parent::getListeners() as $listener) {
            if (!$lazy || !$listener instanceof FirewallListenerInterface) {
                $listeners[] = $listener;
                $lazy = $lazy && $listener instanceof FirewallListenerInterface;
            } elseif (false !== $supports = $listener->supports($request)) {
                $listeners[] = [$listener, 'authenticate'];
                $lazy = null === $supports;
            }
        }

        
/** * Determines if the Response validators (ETag, Last-Modified) match * a conditional value specified in the Request. * * If the Response is not modified, it sets the status code to 304 and * removes the actual content by calling the setNotModified() method. * * @final */
    public function isNotModified(Request $request): bool
    {
        if (!$request->isMethodCacheable()) {
            return false;
        }

        $notModified = false;
        $lastModified = $this->headers->get('Last-Modified');
        $modifiedSince = $request->headers->get('If-Modified-Since');

        if (($ifNoneMatchEtags = $request->getETags()) && (null !== $etag = $this->getEtag())) {
            if (0 == strncmp($etag, 'W/', 2)) {
                $etag = substr($etag, 2);
            }

            
assert($defaults['entity'] instanceof EntityInterface);
      $defaults['entity']->addCacheContexts([static::CACHE_CONTEXT]);
    }

    // If no version was specified, nothing is left to enhance.     if (!$has_version_param) {
      return $defaults;
    }

    // Provide a helpful error when a version is specified with an unsafe     // method.     if (!$request->isMethodCacheable()) {
      throw new BadRequestHttpException(sprintf('%s requests with a `%s` query parameter are not supported.', $request->getMethod()static::RESOURCE_VERSION_QUERY_PARAMETER));
    }

    $resource_version_identifier = $request->query->get(static::RESOURCE_VERSION_QUERY_PARAMETER);

    if (!static::isValidVersionIdentifier($resource_version_identifier)) {
      $cacheability = (new CacheableMetadata())->addCacheContexts([static::CACHE_CONTEXT]);
      $message = sprintf('A resource version identifier was provided in an invalid format: `%s`', $resource_version_identifier);
      throw new CacheableBadRequestHttpException($cacheability$message);
    }

    

  protected function checkAccess(Request $request) {
    // The cacheability (if any) of this request's access check result must be     // applied to the response.     $access_result = $this->accessManager->checkRequest($request$this->account, TRUE);
    // Allow a master request to set the access result for a subrequest: if an     // access result attribute is already set, don't overwrite it.     if (!$request->attributes->has(AccessAwareRouterInterface::ACCESS_RESULT)) {
      $request->attributes->set(AccessAwareRouterInterface::ACCESS_RESULT, $access_result);
    }
    if (!$access_result->isAllowed()) {
      if ($access_result instanceof CacheableDependencyInterface && $request->isMethodCacheable()) {
        throw new CacheableAccessDeniedHttpException($access_result$access_result instanceof AccessResultReasonInterface ? $access_result->getReason() : '');
      }
      else {
        throw new AccessDeniedHttpException($access_result instanceof AccessResultReasonInterface ? $access_result->getReason() : '');
      }
    }
  }

  /** * {@inheritdoc} */
  
$this->setEventResponse($event$exception->getStatusCode());
  }

  /** * {@inheritdoc} */
  protected function setEventResponse(ExceptionEvent $event$status) {
    /** @var \Symfony\Component\HttpKernel\Exception\HttpException $exception */
    $exception = $event->getThrowable();
    $document = new JsonApiDocumentTopLevel(new ErrorCollection([$exception])new NullIncludedData()new LinkCollection([]));
    if ($event->getRequest()->isMethodCacheable()) {
      $response = new CacheableResourceResponse($document$exception->getStatusCode()$exception->getHeaders());
      $response->addCacheableDependency($exception);
    }
    else {
      $response = new ResourceResponse($document$exception->getStatusCode()$exception->getHeaders());
    }
    $event->setResponse($response);
  }

  /** * Check if the error should be formatted using JSON:API. * * The JSON:API format is supported if the format is explicitly set or the * request is for a known JSON:API route. * * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $exception_event * The exception event. * * @return bool * TRUE if it needs to be formatted using JSON:API. FALSE otherwise. */


    // @todo Remove this in https://www.drupal.org/node/2524408, because form     // cache immutability is no longer necessary, because we no longer cache     // forms during safe HTTP methods. In the meantime, because     // Drupal\system\Tests\Form still has test coverage for a poisoned form     // cache following a GET request, trick $form_state into caching the form     // to keep that test working until we either remove it or change it in     // that issue.     if ($this->getRequest()->get('immutable')) {
      $form_state->addBuildInfo('immutable', TRUE);
      if ($this->getRequest()->get('cache') && $this->getRequest()->isMethodCacheable()) {
        $form_state->setRequestMethod('FAKE');
        $form_state->setCached();
      }
    }

    return $form;
  }

  /** * {@inheritdoc} */
  

  public function getResponseFormat(RouteMatchInterface $route_match, Request $request) {
    $route = $route_match->getRouteObject();
    $acceptable_response_formats = $route->hasRequirement('_format') ? explode('|', $route->getRequirement('_format')) : [];
    $acceptable_request_formats = $route->hasRequirement('_content_type_format') ? explode('|', $route->getRequirement('_content_type_format')) : [];
    $acceptable_formats = $request->isMethodCacheable() ? $acceptable_response_formats : $acceptable_request_formats;

    $requested_format = $request->getRequestFormat();
    $content_type_format = $request->getContentTypeFormat();

    // If an acceptable response format is requested, then use that. Otherwise,     // including and particularly when the client forgot to specify a response     // format, then use heuristics to select the format that is most likely     // expected.     if (in_array($requested_format$acceptable_response_formats, TRUE)) {
      return $requested_format;
    }

    

  protected function buildWrappedResponse(TopLevelDataInterface $data, Request $request, IncludedData $includes$response_code = 200, array $headers = [], LinkCollection $links = NULL, array $meta = []) {
    $links = ($links ?: new LinkCollection([]));
    if (!$links->hasLinkWithKey('self')) {
      $self_link = new Link(new CacheableMetadata(), self::getRequestLink($request), 'self');
      $links = $links->withLink('self', $self_link);
    }
    $document = new JsonApiDocumentTopLevel($data$includes$links$meta);
    if (!$request->isMethodCacheable()) {
      return new ResourceResponse($document$response_code$headers);
    }
    $response = new CacheableResourceResponse($document$response_code$headers);
    $cacheability = (new CacheableMetadata())->addCacheContexts([
      // Make sure that different sparse fieldsets are cached differently.       'url.query_args:fields',
      // Make sure that different sets of includes are cached differently.       'url.query_args:include',
    ]);
    $response->addCacheableDependency($cacheability);
    return $response;
  }

  public function __construct(RequestStack $request_stack, CacheFactoryInterface $cache_factory, CacheContextsManager $cache_contexts_manager, PlaceholderGeneratorInterface $placeholder_generator) {
    parent::__construct($request_stack$cache_factory$cache_contexts_manager);
    $this->placeholderGenerator = $placeholder_generator;
  }

  /** * {@inheritdoc} */
  public function get(array $elements) {
    // @todo remove this check when https://www.drupal.org/node/2367555 lands.     if (!$this->requestStack->getCurrentRequest()->isMethodCacheable()) {
      return FALSE;
    }

    // When rendering placeholders, special case auto-placeholdered elements:     // avoid retrieving them from cache again, or rendering them again.     if (isset($elements['#create_placeholder']) && $elements['#create_placeholder'] === FALSE) {
      $cached_placeholder_result = $this->getFromPlaceholderResultsCache($elements);
      if ($cached_placeholder_result !== FALSE) {
        return $cached_placeholder_result;
      }
    }

    
'CONNECT', false],
        ];
    }

    /** * @dataProvider methodCacheableProvider */
    public function testMethodCacheable($method$cacheable)
    {
        $request = new Request();
        $request->setMethod($method);
        $this->assertEquals($cacheable$request->isMethodCacheable());
    }

    public static function methodCacheableProvider()
    {
        return [
            ['HEAD', true],
            ['GET', true],
            ['POST', false],
            ['PUT', false],
            ['PATCH', false],
            ['DELETE', false],
            [

class CommandLineOrUnsafeMethod implements RequestPolicyInterface {

  /** * {@inheritdoc} */
  public function check(Request $request) {
    if ($this->isCli() || !$request->isMethodCacheable()) {
      return static::DENY;
    }
  }

  /** * Indicates whether this is a CLI request. */
  protected function isCli() {
    return PHP_SAPI === 'cli';
  }

}

  protected static function flattenResponse(ResourceResponse $response, Request $request) {
    $final_response = ($response instanceof CacheableResponseInterface && $request->isMethodCacheable()) ? new CacheableResponse() : new Response();
    $final_response->setContent($response->getContent());
    $final_response->setStatusCode($response->getStatusCode());
    $final_response->setProtocolVersion($response->getProtocolVersion());
    if ($charset = $response->getCharset()) {
      $final_response->setCharset($charset);
    }
    $final_response->headers = clone $response->headers;
    if ($final_response instanceof CacheableResponseInterface) {
      $final_response->addCacheableDependency($response->getCacheableMetadata());
    }
    return $final_response;
  }
Home | Imprint | This part of the site doesn't use cookies.