4

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!

1 Answer 1

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 called as in the following code.

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 had was the Drupal session cookie which I could use to check. This cookie is set or unset whether the user is authenticated. This may not be the most robust solution so others are welcome.

I found Replacing hook_boot() and hook_init() Functionality in Drupal 8, which was great to get the code working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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