it-swarm.com.de

Anonyme Benutzer-Cache-Steuerung

Wir haben einige benutzerdefinierte Blöcke geschrieben, die dynamischen Inhalt rendern. Leider wird beim Caching standardmäßig das erste Rendering dieses Blocks zwischengespeichert (und für anonyme Benutzer nicht aktualisiert). Die Cache-Steuerung scheint nur für authentifizierte Benutzer zu funktionieren. Vermissen wir etwas Offensichtliches? Ist es möglich, anonymes Caching auf Block- (oder Seiten-) Basis zu steuern?

7
gavz

Es gibt zwei verschiedene Seiten-Caches.

Der interne dynamische Seiten-Cache funktioniert mit allen Arten von Elementen wie Blöcken und Knoten und verwendet die von diesen bereitgestellten Cache-Tags, Cache-Kontexte und das maximale Cache-Alter Elemente.

Der interne Seiten-Cache ist für vollständige Seiten für anonyme Benutzer vorgesehen und verwendet nur Cache-Tags.

Sie können den Seitencache für anonyme Benutzer mit einem Parameter steuern.

Gehen Sie zur Leistungskonfiguration:

admin/config/development/performance

Konfigurieren Sie das maximale Alter des Seitencaches mit der Zeit, wie lange Ihre Informationen gültig sind. Dies ist auch für Proxys und den Browser-Cache wichtig, da es nicht hilfreich wäre, den Cache drupal ungültig zu machen, wenn die Seite an anderen Stellen zwischengespeichert wird. Nach dieser Zeit läuft die Seite ab und sollte erstellt werden wieder. Laut Dokumentation:

Konfigurieren des internen Seitencaches Auf der Seite Leistung können Sie konfigurieren, wie lange Browser und Proxys Seiten zwischenspeichern dürfen. Diese Einstellung wird auch vom internen Seiten-Cache-Modul berücksichtigt. Es gibt keine andere Konfiguration.

Aber das ist nicht wahr. Sie sollten diese Zeit für Proxys und den Browser-Cache konfigurieren, der interne Seiten-Cache berücksichtigt jedoch nicht die dort festgelegte Zeit. Die einzige zuverlässige Lösung, die ich gefunden habe, besteht darin, den internen Seiten-Cache des Moduls zu deinstallieren oder eine Ablaufzeit in einem EventSubscriber festzulegen (z. B. 3600 Sekunden in der Zukunft):

/ src/EventSubscriber/SetExpiresSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class SetExpiresSubscriber implements EventSubscriberInterface {

  public function onResponse(FilterResponseEvent $event) {
    $request = $event->getRequest();
    $response = $event->getResponse();
    if ($event->isMasterRequest()) {
      $request_time = $request->server->get('REQUEST_TIME');
      $expires_time = (new \Datetime)->setTimestamp($request_time + 3600);
      $response->setExpires($expires_time);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['onResponse'];
    return $events;
  }

}

mymodule.services.yml

services:
  mymodule.setexpires:
    class: Drupal\mymodule\EventSubscriber\SetExpiresSubscriber
    tags:
      - { name: event_subscriber }
11
4k4

Check out Routenoption 'no_cache' hinzugefügt, um die Antworten einer Route als nicht zwischenspeicherbar zu markieren

In Ihrer routing.yml-Datei:

some.route:
   path: '/some/path'
   defaults:
     _controller: '\Drupal\Some\Controller::response()'
   options:
     no_cache: TRUE
3
joe casey

Wenn der interne Seiten-Cache aktiviert sein muss (dh Sie können Varnish oder eine andere speicherbasierte Lösung nicht verwenden) und der interne Seiten-Cache einfach die unter admin/config/development/performance Eingestellte Zeit einhalten soll, können Sie Ihren hinzufügen Eigener Ereignisabonnent, der den FinishResponseSubscriber ändert, den Drupal bereitstellt. Sie können sogar Drupal Console) verwenden, um den größten Teil des Ereignisabonnenten für Sie zu generieren, und dann den anderen übernehmen Bits von FinishResponseSubscriber. Ihr Ergebnis würde ungefähr so ​​aussehen:

/**
 * Class MyModuleSubscriber.
 *
 * @package Drupal\my_module
 */
class MyModuleSubscriber implements EventSubscriberInterface {

  /**
   * Sets extra headers on successful responses.
   *
   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
   *   The event to process.
   */
  public function onRespond(FilterResponseEvent $event) {
    if (!$event->isMasterRequest()) {
      return;
    }

    $request = $event->getRequest();
    $response = $event->getResponse();

    $this->setExpiresNoCache($response);

    return;

  }

  /**
   * Disable caching in ancient browsers and for HTTP/1.0 proxies and clients.
   *
   * 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).
   *
   * @param \Symfony\Component\HttpFoundation\Response $response
   *   A response object.
   */
  protected function setExpiresNoCache(Response $response) {
    $response->setExpires(REQUEST_TIME + 300);
  }

  /**
   * Registers the methods in this class that should be listeners.
   *
   * @return array
   *   An array of event listener definitions.
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('onRespond');
    return $events;

  }
}

Mit dem obigen Code wird die Cache-Lebensdauer auf 300 Sekunden fest codiert. Sie können jedoch stattdessen problemlos die Benutzereinstellung abrufen.

1
markfullmer

Ich denke, Sie müssen das Modul 'Interner Seiten-Cache' deaktivieren, damit die Cache-Kontexte funktionieren.

Wenn "Interner Seiten-Cache" aktiviert ist, werden Inhalte für anonyme Benutzer standardmäßig zwischengespeichert.

Wenn Sie 'Interner Seiten-Cache' deaktivieren, müssen Sie immer noch Drupal, um nicht für anonyme Benutzer zwischenzuspeichern)

$variables['#cache'] = [
  'contexts' => [
    // The "current user" is used above, which depends on the request,
    // so we tell Drupal to vary by the 'user' cache context.
    'user',
  ],
];

tut es für mich - ist aber wahrscheinlich nicht ganz richtig.

0
bailey86