このモジュールがあります Splash Redirect ここで、src/EventSubscriber/SplashRedirectEventSubscriber.php
はCookie $config_cookie
が存在するかどうかを確認することになっています。すでに存在する場合、ユーザーは要求されたノード($config_source
)が存在する場合notが存在する場合、ユーザーは$config_destination
に送信され、Cookie($config_cookie
)。
$config_cookie
の作成と$config_destination
へのリダイレクトは成功しますが、一度作成されたCookieの存在を確認することはなく、ユーザーを$config_destination
にリダイレクトし続けます。
手がかりはありますか? 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;
}
}
いくつかのアイデア:
設定と同様に、Cookieのキャッシュ依存関係も追加する必要があります。
$response->getCacheableMetadata()->addCacheContexts(['cookies:' . $config_cookie]);
または、キャッシュできないRedirectResponse
を使用して物事を簡略化します。
また、コードが32を持つルーティングにのみ依存するため、イベントサブスクライバーの優先度(31など)を設定してみてください。
$events[KernelEvents::REQUEST][] = ['modifyIntercept', 31];
リクエストサブスクライバーではまだ応答がないため、応答を取得する必要はありません。代わりにリクエストを取得し、マスターリクエストであることを確認してください。したがって、これはサブスクライバーが最も頻繁に開始する方法です。
public function onKernelRequest(GetResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
...
テストのためにもう少し単純化し、ダミー値を使用します:
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);
}
}
}
これは私のローカル開発環境で動作しています。
完全なコード(依存関係の挿入を含む):
/ 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 }
オリジナル splash_redirect module dev here。キャッシングラビットホールにご参加いただきありがとうございます。 (申し訳ありませんが、まだ「コメント」を作成することはできませんので、これを回答に入れなければなりません)
素晴らしい提案をしてくれた@ 4k4のおかげで、次のリリースでそれらのいくつかを実装する可能性がありますが、OPの問題はVary: cookie
ヘッダーを設定し、ソースリダイレクトをキャッシュするPantheonのグローバルCDNに固有のようです。
*したがって、パンテオンでsplash_redirectを使用している場合、 スプラッシュCookie名の前に「SESS」を付けてください 、たとえばSESSsplash
*