3

I'm working on a redirection (for unauthenticated users) for my Drupal 8 site. Currently, the redirection works however, the redirection persists even after user is authenticated. I found this article piece helpful to point me in the right direction:

"Drupal 8 has two level cache, page cache and dynamic page cache. The issue you are having is more likely to intercept the page cache. Add new class which implements 'HttpKernelInterface' and register 'http_middleware' with higher priority than 200 (280 will do)."

My problem is related to intercepting the page cache, so I am currently trying to implement the 'HttpKernelInterface' and register 'http_middleware' but unsuccessfully. I created a custom module (example_module for example sake). My example_module.services.yml file:

services:
  example_module.event_subscriber:
    class: Drupal\example_module\EventSubscriber\RedirectAnonymousSubscriber
    tags:
      - { name: event_subscriber }
  example_module.stack_middleware:
    class: Drupal\example_module\EventSubscriber\StackMiddleware
    tags:
      - { name: http_middleware, priority: 210, responder: true }

Then in the same module I have a src/EventSubscriber/RedirectAnonymousSubscriber.php file like so:

<?php

namespace Drupal\example_module\EventSubscriber;
namespace Drupal\example_module\StackMiddleware;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;


/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface,HttpKernelInterface {
  private $redirectCode = 301;

    /**
  * The wrapped HTTP kernel.
  *
  * @var \Symfony\Component\HttpKernel\HttpKernelInterface
  */
  protected $httpKernel;

  /**
  * Creates a HTTP middleware handler.
  *
  * @param \Symfony\Component\HttpKernel\HttpKernelInterface $kernel
  *   The HTTP kernel.
  */
  public function __construct(HttpKernelInterface $kernel) {
    $this->httpKernel = $kernel;
  }

  /**
  * {@inheritdoc}
  */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
    // Only allow page caching on master request.
    if ($type === static::MASTER_REQUEST && $this->requestPolicy
      ->check($request) === RequestPolicyInterface::ALLOW) {
      $response = $this
        ->lookup($request, $type, $catch);
    } else {
      $response = $this
        ->pass($request, $type, $catch);
    }

    return $response;
  }

  public function checkForRedirection(GetResponseEvent $event) {
    $is_authenticated = \Drupal::currentUser()->isAuthenticated();
    $route_name = \Drupal::routeMatch()->getRouteName();

    if (!$is_authenticated && $route_name !== 'user.login') {
      $response = new RedirectResponse('https://google.com', $this->redirectCode);
      $response->send();
      exit(0);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection',30);
    return $events;
  }
}

Do I need both an EventSubcriber and StackMiddleware to accomplish this redirection and intercepting of page caching? Do I have to create a separate custom module to implement my StackMiddleware class? How do I use my redirection code (which I know works) with this StackMiddleware class so I can intercept the page cache and have it run on every page(so it always checks to see if user is authenticated)? Any help appreciated. Thanks!

0

I recently implemented this myself and had to do a fair bit of research and experimenting to get it to work. I too had many of the same questions you have so I've tried to answer them from what I've discovered.


Do I need both an EventSubcriber and StackMiddleware to accomplish this redirection and intercepting of page caching?

  • You will only need the "StackMiddleware" to intercept the page caching. It should replace "EventSubcriber" if that already exists.

Do I have to create a separate custom module to implement my StackMiddleware class?

  • This can be achieved in the same module.

How do I use my redirection code (which I know works) with this StackMiddleware class so I can intercept the page cache

  • The redirection function should be a called like so...
public function handle(...) {
  ...
  $this->checkForRedirection();
  ...
}

Have it run on every page(so it always checks to see if user is authenticated)?

  • In my case the user object wasn't available because the middleware runs prior to any user data being set. What I did have was the Drupal session cookie which I could check against. This cookie is set and unset depending if the user is authenticated or not. This may not be the most robust solution so others are welcome.

--

I found this article which was great for getting some of the foundations working: https://chromatichq.com/blog/replacing-hookboot-and-hookinit-functionality-drupal-8

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.