Preventing redirects from being cached for anonymous users I have a content type that needs to redirect only when it is tagged as "External". All of these "External" items have a field where a URL is supplied for the redirect.

During initial setup of the content type the redirection was being done in the .theme file in preprocess_html but we discovered that after the first time someone was redirected when accessing one of these nodes, it would get cached and the redirection would not longer happen.

I then built a module to do the redirection with and event subscriber and this fixed the problem when logged in as an admin but not for anonymous users.

For the third iteration, I built a module to set up middleware that implements HttpKernelInterface in order to do the redirection there.
This particular content type had a url pattern so I used that to determine when the middleware should run based on the $request-&gt;getPathInfo(); and then testing for the node type and the "External" tag being applied to it.
That solved all of the redirection problems, but other started to pop up. For example, the edit form for all of the nodes started displaying on the the title field and nothing else and views using the content type would start displaying as empty as well.

Is there a more effective way of doing this redirection and avoiding the page cache than doing it with middleware or has anyone experienced an issue like this when implementing HttpKernelInterface?

handle function being used in the middleware:

public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {


$newsPrefix = "/news";

$current_uri = $request-&gt;getPathInfo();
if(substr($current_uri, 0, strlen($newsPrefix)) === $newsPrefix){
  $path = \Drupal::service('path.alias_manager')-&gt;getPathByAlias($current_uri);

  if(preg_match('/node\/(\d+)/', $path, $matches)) {
    $node = \Drupal\node\Entity\Node::load($matches[1]);

    if (isset($node)) {

      $nodeType = $node-&gt;getType();
      if($nodeType === 'news'){

        if(isset($node-&gt;news_type_of_content) &amp;&amp; isset($node-&gt;news_type_of_content-&gt;target_id)){
          $typeID = $node-&gt;news_type_of_content-&gt;target_id;

          if(isset($typeID)){
            $term = \Drupal::entityTypeManager()-&gt;getStorage('taxonomy_term')-&gt;load($typeID);
            $name = $term-&gt;getName();
          }

          if(isset($name) &amp;&amp; $name === "External" &amp;&amp; isset($node-&gt;news_source_url-&gt;value)){

            $response = new RedirectResponse($node-&gt;news_source_url-&gt;value, 302);
            $response-&gt;send();
            exit;
          }
        }
      }
    }
  }
}
return $this-&gt;httpKernel-&gt;handle($request, $type, $catch);


}
Solution ended up being an event subscriber with a cacheable response:


&lt;?php


namespace Drupal\news_redirect\EventSubscriber;

use Drupal\Core\Routing\TrustedRedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;


class NewsRedirectSubscriber implements EventSubscriberInterface {

  public function redirectMediaCoverage(GetResponseEvent $event) {

    $node = \Drupal::routeMatch()-&gt;getParameter('node');
    if (isset($node) &amp;&amp; $node instanceof \Drupal\node\NodeInterface) {

      $nodeType = $node-&gt;getType();

      if($nodeType === 'news'){

        $typeID = $node-&gt;news_type_of_content-&gt;target_id;

        if(isset($typeID)){

          $term = \Drupal::entityTypeManager()-&gt;getStorage('taxonomy_term')-&gt;load($typeID);
          $name = $term-&gt;getName();

        }

        if(isset($name) &amp;&amp; $name === "Media Coverage" &amp;&amp; isset($node-&gt;news_source_url-&gt;value)){

          $url = $node-&gt;news_source_url-&gt;value;

          if(isset($url)){

            $response_headers = [
              'Cache-Control' =&gt; 'no-cache, no-store, must-revalidate',
            ];

            $response = new TrustedRedirectResponse($url, '302', $response_headers);
            $response-&gt;addCacheableDependency($node);
            $event-&gt;setResponse($response);
          }

        }

      }

    }

  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['redirectMediaCoverage',30];
    return $events;
  }

}