Il y a ce module Splash Redirect dans lequel src/EventSubscriber/SplashRedirectEventSubscriber.php
est censé vérifier si le cookie $config_cookie
existe ou non, s'il existe déjà, l'utilisateur continue sur le nœud demandé ($config_source
), mais s'il n'existe pas , l'utilisateur est envoyé à $config_destination
et il crée le cookie ($config_cookie
).
Il réussit à créer le $config_cookie
et la redirection vers $config_destination
mais il ne semble jamais reconnaître l'existence du cookie une fois créé et continue de rediriger l'utilisateur vers $config_destination
.
Des indices? On Drupal 8.6
<?php
namespace Drupal\splash_redirect\EventSubscriber;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Routing\TrustedRedirectResponse;
/**
* Splash redirect Event Subscriber.
*/
class SplashRedirectEventSubscriber implements EventSubscriberInterface {
/**
* Triggered when system sends response.
*/
public function modifyIntercept(GetResponseEvent $event) {
$config = \Drupal::config('splash_redirect.settings');
$config_enabled = $config->get('splash_redirect.is_enabled');
$config_source = $config->get('splash_redirect.source');
$config_destination = $config->get('splash_redirect.destination');
$config_cookie = $config->get('splash_redirect.cookie_name');
$config_duration = $config->get('splash_redirect.duration');
// If splash config is not enabled then we don't need to do any of this.
if ($config_enabled == 1) {
// Current request from client.
$request = \Drupal::request();
$current_uri = $request->getRequestUri();
$http_Host = $request->getHost();
// Current response from system.
$response = $event->getResponse();
$route = (\Drupal::routeMatch()->getParameter('node')) ? \Drupal::routeMatch()->getParameter('node')->id() : null;
$has_cookie = $request->cookies->has($config_cookie);
// If splash-cookie has not been set, and user requesting 'source' page,
// set cookie and redirect to splash page.
if ($config_source == $route) {
// Kill cache on this route or else cookie might not be read with VCL.
\Drupal::service('page_cache_kill_switch')->trigger();
if (!$has_cookie) {
// Set redirect response with cookie and redirect location.
$redir = new TrustedRedirectResponse($config_destination, '302');
$cookie = new Cookie($config_cookie, 'true', strtotime('now + ' . $config_duration . 'days'), '/', '.' . $http_Host, false, true);
$redir->headers->setCookie($cookie);
$redir->headers->set('Cache-Control', 'public, max-age=0');
$redir->addCacheableDependency($config_destination);
$event->setResponse($redir);
}
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Listen for response event from system and intercept.
$events[KernelEvents::REQUEST][] = ['modifyIntercept'];
return $events;
}
}
Quelques idées:
Comme pour la configuration, vous devez également ajouter une dépendance de cache pour le cookie:
$response->getCacheableMetadata()->addCacheContexts(['cookies:' . $config_cookie]);
Ou utilisez un RedirectResponse
non mis en cache pour simplifier les choses.
Et essayez de définir une priorité pour l'abonné à l'événement, par exemple 31, car votre code dépend uniquement du routage, qui en a 32:
$events[KernelEvents::REQUEST][] = ['modifyIntercept', 31];
Vous n'avez pas besoin d'obtenir une réponse dans un abonné de demande, car il n'y en a pas encore. Obtenez la demande à la place et assurez-vous que vous êtes dans une demande principale. Voici donc comment l'abonné démarre la plupart du temps:
public function onKernelRequest(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
...
Simplifier un peu plus et utiliser des valeurs fictives pour les tests:
public function onKernelRequest(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$route_match = \Drupal::routeMatch();
if (!$route_match->getRouteName() == 'entity.node.canonical') {
return;
}
$request = $event->getRequest();
if ($route_match->getRawParameter('node') == '1') {
\Drupal::service('page_cache_kill_switch')->trigger();
if (!$request->cookies->has('foo')) {
$redirect = new RedirectResponse($request->getBasePath() . '/node/2', 302);
$redirect->headers->setCookie(new Cookie('foo', '123', '+30 seconds'));
$event->setResponse($redirect);
}
}
}
Cela fonctionne sur mon environnement de développement local.
Code complet (y compris l'injection de dépendance):
/ src/EventSubscriber/MymoduleSubscriber.php
<?php
namespace Drupal\mymodule\EventSubscriber;
use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Cookie;
/**
* mymodule event subscriber.
*/
class MymoduleSubscriber implements EventSubscriberInterface {
/**
* The route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* Constructs event subscriber.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*/
public function __construct(RouteMatchInterface $route_match) {
$this->routeMatch = $route_match;
}
/**
* Kernel request event handler.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* Response event.
*/
public function onKernelRequest(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
if (!$this->routeMatch->getRouteName() == 'entity.node.canonical') {
return;
}
$request = $event->getRequest();
if ($this->routeMatch->getRawParameter('node') == '1') {
\Drupal::service('page_cache_kill_switch')->trigger();
if (!$request->cookies->has('foo')) {
$redirect = new RedirectResponse($request->getBasePath() .'/node/2', 302);
$redirect->headers->setCookie(new Cookie('foo', '123', '+30 seconds'));
$event->setResponse($redirect);
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
KernelEvents::REQUEST => ['onKernelRequest', 31],
];
}
}
mymodule.services.yml
services:
mymodule.event_subscriber:
class: Drupal\mymodule\EventSubscriber\MymoduleSubscriber
arguments: ['@current_route_match']
tags:
- { name: event_subscriber }
Original splash_redirect module dev ici. Merci de m'avoir rejoint dans le trou du lapin en cache! (Désolé, je ne peux pas encore faire de "commentaires", je dois donc mettre cela dans une réponse)
Merci à @ 4k4 pour les excellentes suggestions, j'en implémenterai probablement certaines dans la prochaine version, mais le problème d'OP semble être spécifique au CDN mondial de Panthéon, qui définit le Vary: cookie
header et met en cache la redirection source.
* Donc, si vous utilisez splash_redirect sur Pantheon, veuillez préfixer votre nom de cookie Splash avec "SESS" , par exemple SESSsplash
*