KernelEvents :: REQUEST не запускается на кэшированных страницах

13

Я пытаюсь реализовать подписчик события KernelEvents :: REQUEST для выполнения некоторых действий при загрузке страницы.

Мне нужно, чтобы это событие запускалось независимо от того, существует ли запрашиваемая страница в кэше Drupal - кажется, что KernelEvents :: REQUEST не запускается, когда Drupal обслуживает что-то из кэша.

Есть ли событие, которое я могу использовать для достижения этой цели, или я должен реализовать свои требования в качестве некоторого промежуточного программного обеспечения?

киамлалуно
источник
1
Событие REQUEST должно быть запущено, иначе ответа не будет. ИМХО, ваш ES имеет плохой вес, а служба http_middleware.page_cache (или динамический кэш страниц) останавливает распространение события дальше, поэтому ваш ES не будет запущен.
Вес / приоритет ES установлены на 20
Как пишет 4k4, page_cache для анонимных пользователей является промежуточным ПО и происходит задолго до события REQUEST. Вы можете написать свое собственное промежуточное программное обеспечение, которое приходит раньше, но вы можете пересмотреть свою оценку. Что именно должно произойти так рано? Имейте в виду, что кеширование анонимных страниц может происходить даже при использовании другого внешнего программного обеспечения или даже самих браузеров. Посмотрите, как основной модуль статистики отслеживает посещения страниц: с помощью javascript, который отправляет эхо-запрос на сервер, когда его выполняет пользователь.
Бердир
@Berdir Он предназначен для обеспечения http-аутентификации для сайта, похожего на модуль Shield - поэтому я думаю, что это действительно верный пример того, что должно быть обработано как можно раньше в запросе. (Я знаю, что патч для модуля D8 Shield реализован как промежуточное ПО - я полагаю, из-за этого ограничения).

Ответы:

14

Динамический кеш подписывается на событие с приоритетом 27. Если вы хотите, чтобы ваш код выполнялся до этого, вы должны использовать приоритет> 27:

  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];

Который запускает DynamicPageCacheSubscriber :: onRequest ..

4k4
источник
Приоритет установлен на 20
Я думаю, что у вас проблема с событием из динамического кэша, я отредактировал свой ответ.
4k4
спасибо @ 4k4, но даже с приоритетом 30 он все равно ведет себя (я переустановил модуль и очистил все кеши после внесения изменений). Есть еще идеи?
Есть два кеша. Теперь, когда у вас есть приоритет над динамическим кешем, все еще есть кеш страниц. Кеш страниц выполняется перед основным ядром. Вы можете удалить этот модуль и проверить, в порядке ли производительность без него.
4k4
Я могу подтвердить, что это сработало для меня. У меня был редирект, который мог произойти только один раз - до того, как страница была кэширована. Когда я добавил приоритет, ['checkForRediret', 30];он работал как ожидалось.
Циклон-код
6

Drupal 8 имеет двухуровневый кеш, кеш страниц и динамический кеш страниц.

Да, вы можете перехватить динамический кеш страниц как упомянутое @ 4k4. Проблема, с которой вы столкнулись, скорее всего перехватит кеш страниц. Ключ здесь .

Есть несколько решений для этого:

  1. Добавьте новый класс, который реализует 'HttpKernelInterface' и зарегистрируйте 'http_middleware' с более высоким приоритетом, чем 200 (280 будет делать). См. Класс 'PageCache' и реализации для ссылок.

  2. Создайте новый класс для изменения существующего «PageCache» путем расширения из «ServiceProviderBase». Проверьте это для ссылок здесь . Затем создайте новый класс для расширения «PageCache».

Вот ссылки на код:

Это 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');
  }
}

Это 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;
  }
}

Надежда помогает.

kororo
источник
Это было очень полезно, спасибо, я решил проблему, внедрив решение 1.
Remco Hoeneveld