KernelEvents :: REQUEST não é acionado em páginas em cache

12

Estou tentando implementar um assinante de evento KernelEvents :: REQUEST para executar alguma ação no carregamento da página.

Eu preciso que esse evento seja acionado, independentemente de a página solicitada existir no cache do Drupal - parece que o KernelEvents :: REQUEST não é acionado quando o Drupal serve algo do cache.

Existe um evento que eu possa usar para conseguir isso ou devo implementar meus requisitos como alguma forma de middleware?

kiamlaluno
fonte
1
O evento REQUEST TEM QUE ser acionado, caso contrário não haveria resposta. IMHO seu ES tem um peso ruim e o serviço http_middleware.page_cache (ou o cache dinâmico de páginas) está interrompendo ainda mais a propagação do evento, portanto, seu ES não será acionado.
O peso / prioridade do ES está definido como 20
Como 4k4 escreveu, o page_cache para usuários anônimos é um middleware e acontece muito antes do evento REQUEST. Você pode escrever seu próprio middleware que vem mais cedo, mas pode reconsiderar sua abordagem. O que exatamente precisa acontecer tão cedo? Lembre-se de que o cache de páginas anônimas pode até ocorrer em verniz de outros softwares externos ou mesmo nos próprios navegadores. Veja como o módulo de estatísticas principais rastreia as visitas à página: Com javascript que faz o ping do servidor quando um usuário o executa.
Berdir 17/05
@Berdir É fornecer autenticação http para um site, semelhante ao módulo Shield - então acho que isso representa um exemplo válido de algo que precisa ser tratado o mais cedo possível na solicitação. (Estou ciente de que existe o patch do módulo D8 Shield implementado como middleware - estou assumindo por causa dessa limitação).

Respostas:

12

O cache dinâmico assina um evento com prioridade 27. Se você deseja que seu código seja executado antes disso, use uma prioridade> 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];

Que executa DynamicPageCacheSubscriber :: onRequest ..

4k4
fonte
A prioridade está definida como 20
Acho que o problema que você tem é com o evento do cache dinâmico, editei minha resposta.
4k4 17/05/19
obrigado @ 4k4, mas mesmo com a prioridade definida como 30, ele ainda se comporta da mesma forma (reinstalei o módulo e limpei todos os caches depois de fazer alterações). Alguma outra ideia?
Existem dois caches. Agora que você tem prioridade sobre o cache dinâmico, ainda existe o cache da página. O cache da página é executado antes do kernel principal. Você pode desinstalar este módulo e testar se o desempenho está bom sem ele.
4k4
Eu posso confirmar que isso funcionou para mim. Eu tinha um redirecionamento que só acontecia uma vez - antes da página ser armazenada em cache. Quando adicionei uma prioridade ['checkForRediret', 30];, funcionou como esperado.
precisa saber é o seguinte
5

O Drupal 8 possui cache de dois níveis, cache de página e cache dinâmico de páginas.

Sim, você pode interceptar o cache da página dinâmica conforme mencionado em @ 4k4. O problema que você está tendo é mais provável de interceptar o cache da página. A chave está aqui .

Existem algumas soluções para isso:

  1. Adicione uma nova classe que implemente 'HttpKernelInterface' e registre 'http_middleware' com prioridade mais alta que 200 (o que é o caso de 280). Consulte a classe e implementações 'PageCache' para obter referências.

  2. Crie uma nova classe para alterar o 'PageCache' existente estendendo-se de 'ServiceProviderBase'. Verifique isso para referências aqui . Em seguida, crie uma nova classe para estender o 'PageCache'.

Aqui estão as referências de código:

Este é 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');
  }
}

Este é 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;
  }
}

A esperança ajuda.

kororo
fonte
Este foi thankyou muito útil, eu resolvi o problema através da implementação de solução 1.
Remco Hoeneveld