Drupal - Can't find cookie for validation in EventSubscriber
Some ideas:
Like for the config you have to add a cache dependency for the cookie, too:
$response->getCacheableMetadata()->addCacheContexts(['cookies:' . $config_cookie]);
Or use an uncacheable RedirectResponse
to simplify things.
And try to set a priority for the event subscriber, for example 31, because your code depends only on routing, which has 32:
$events[KernelEvents::REQUEST][] = ['modifyIntercept', 31];
You don't need to get a response in an request subscriber, because there isn't one yet. Get the request instead and make sure that you are in a master request. So this would be how the subscriber starts most times:
public function onKernelRequest(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
...
Simplifying a bit more and using dummy values for testing:
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);
}
}
}
This is working on my local dev environment.
Complete code (including dependency injection):
/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 here. Thanks for joining me in the caching rabbit hole! (Sorry, can't make 'comments' yet so I have to put this in an answer)
Thanks to @4k4 for the great suggestions, I will likely implement some of those in the next release, but OP's issue looks to be specific to Pantheon's global CDN, which sets the Vary: cookie
header, and caches the source redirect.
*So, if you're using splash_redirect on Pantheon, please prefix your Splash Cookie name with "SESS", e.g. SESSsplash
*