KernelEvents :: REQUEST wird nicht auf zwischengespeicherten Seiten ausgelöst

12

Ich versuche, einen KernelEvents :: REQUEST-Ereignisabonnenten zu implementieren, um beim Laden der Seite eine Aktion auszuführen.

Dieses Ereignis muss ausgelöst werden, unabhängig davon, ob die angeforderte Seite im Drupal-Cache vorhanden ist. KernelEvents :: REQUEST wird anscheinend nicht ausgelöst, wenn Drupal etwas aus dem Cache bereitstellt.

Gibt es ein Ereignis, mit dem ich dies erreichen kann, oder muss ich meine Anforderungen als eine Art Middleware implementieren?

kiamlaluno
quelle
1
Das REQUEST-Ereignis MUSS ausgelöst werden, da sonst keine Antwort erfolgt. IMHO Ihr ES hat schlechtes Gewicht und die http_middleware.page_cache (oder die dynamischen Seiten - Cache) Dienst wird die Ausbreitung des Ereignisses zu stoppen weiter, damit Du ES wird nicht ausgelöst werden.
ES Gewicht / Priorität ist auf 20 gesetzt
Wie 4k4 schrieb, ist page_cache für anonyme Benutzer eine Middleware und geschieht lange vor dem REQUEST-Ereignis. Sie könnten Ihre eigene Middleware schreiben, die früher kommt, aber Sie möchten vielleicht Ihren Ansatz überdenken. Was genau muss so früh passieren? Beachten Sie, dass anonymes Seiten-Caching sogar beim Lackieren anderer externer Software oder sogar der Browser selbst auftreten kann. Sehen Sie sich an, wie das Kernstatistikmodul Seitenbesuche verfolgt: Mit Javascript, das den Server anpingt, wenn ein Benutzer ihn ausführt.
Berdir
@Berdir Es geht darum, eine http-Authentifizierung für eine Site bereitzustellen, ähnlich wie beim Shield-Modul. Ich denke, dies ist ein gültiges Beispiel für etwas, das so früh wie möglich in der Anfrage behandelt werden muss. (Mir ist bekannt, dass ein D8 Shield-Modul-Patch als Middleware implementiert ist - ich gehe aufgrund dieser Einschränkung davon aus).

Antworten:

12

Der dynamische Cache abonniert ein Ereignis mit Priorität 27. Wenn Sie möchten, dass Ihr Code zuvor ausgeführt wird, müssen Sie eine Priorität> 27 verwenden:

  public static function getSubscribedEvents() {
    $events = [];

    // Run after AuthenticationSubscriber (necessary for the 'user' cache
    // context; priority 300) and MaintenanceModeSubscriber (Dynamic Page Cache
    // should not be polluted by maintenance mode-specific behavior; priority
    // 30), but before ContentControllerSubscriber (updates _controller, but
    // that is a no-op when Dynamic Page Cache runs; priority 25).
    $events[KernelEvents::REQUEST][] = ['onRequest', 27];

Welches läuft DynamicPageCacheSubscriber :: onRequest ..

4k4
quelle
Die Priorität ist auf 20 gesetzt
Ich denke, das Problem, das Sie haben, ist mit dem Ereignis aus dem dynamischen Cache. Ich habe meine Antwort bearbeitet.
4k4
danke @ 4k4, aber selbst wenn die Priorität auf 30 gesetzt ist, verhält es sich immer noch gleich (ich habe das Modul neu installiert und alle Caches geleert, nachdem ich Änderungen vorgenommen habe). Irgendwelche anderen Ideen?
Es gibt zwei Caches. Jetzt, da Sie Vorrang vor dem dynamischen Cache haben, befindet sich noch der Seiten-Cache. Der Seitencache wird vor dem Hauptkern ausgeführt. Sie können dieses Modul deinstallieren und testen, ob die Leistung ohne dieses Modul in Ordnung ist.
4k4
Ich kann bestätigen, dass dies bei mir funktioniert hat. Ich hatte eine Weiterleitung, die nur einmal stattfinden würde - bevor die Seite zwischengespeichert wurde. Wenn ich eine Priorität hinzugefügt habe, ['checkForRediret', 30];hat es wie erwartet funktioniert.
Cyclonecode
5

Drupal 8 verfügt über einen Cache mit zwei Ebenen, einen Seitencache und einen dynamischen Seitencache.

Ja, Sie können den dynamischen Seitencache wie in @ 4k4 erwähnt abfangen. Es ist wahrscheinlicher, dass das Problem den Seitencache abfängt. Der Schlüssel ist hier drin .

Hierfür gibt es einige Lösungen:

  1. Fügen Sie eine neue Klasse hinzu, die 'HttpKernelInterface' implementiert, und registrieren Sie 'http_middleware' mit einer höheren Priorität als 200 (280 reicht aus). Referenzen finden Sie unter 'PageCache'-Klasse und Implementierungen.

  2. Erstellen Sie eine neue Klasse, um den vorhandenen 'PageCache' durch Erweitern von 'ServiceProviderBase' zu ändern. Überprüfen Sie dies für Referenzen hier . Erstellen Sie dann eine neue Klasse, um den 'PageCache' zu erweitern.

Hier sind Code-Referenzen:

Dies ist StaticCacheServiceProvider.php:

/**
 * Modifies the language manager service.
 */
class StaticCacheServiceProvider extends ServiceProviderBase
{
  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container)
  {
    // Overrides language_manager class to test domain language negotiation.
    $definition = $container->getDefinition('http_middleware.page_cache');
    $definition->setClass('Drupal\your_module\StackMiddleware\StaticCache');
  }
}

Dies ist StaticCache.php:

/**
 * Executes the page caching before the main kernel takes over the request.
 */
class StaticCache extends PageCache
{
  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
  {
    // do special logic here.

    $response = parent::handle($request, $type, $catch);

    return $response;
  }
}

Hoffnung hilft.

kororo
quelle
Dies war sehr hilfreich, danke, ich habe das Problem durch die Implementierung von Lösung 1 gelöst.
Remco Hoeneveld