A similar question was posted here: EventSubscriber endless redirect
But I haven't quite been able to implement a workable solution.
On Drupal 8.73: Basically we have a custom module that is redirecting to clean urls (so that /node/42 doesn't get indexed by google). I didn't write the module and I'm a little fuzzy on what it's doing and why. The module works fine except that urls with ?
in them endlessly redirect and get caught in a redirect loop. The browser eventually returns an error that the page is redirecting and will never load properly. Here is the module:
<?php
/**
* @file
* Contains \Drupal\mymodule\EventSubscriber\MyModuleSubscriber.
*/
namespace Drupal\sjwc_tweaks\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Event subscriptions for events dispatched by SimpleFbConnect.
*/
class TweaksSubscriber implements EventSubscriberInterface {
public function onRequest(GetResponseEvent $event) {
$baseUrl = $event->getRequest()->getBaseUrl();
$attr = $event->getRequest()->attributes;
if (null !== $attr && null !== $attr->get('node') && $attr->get('_controller') == '\Drupal\node\Controller\NodeViewController::view') {
$node = $attr->get('node');
$nid = $node->id();
$current_uri = \Drupal::request()->getRequestUri();
if (\Drupal::service('path.matcher')->isFrontPage()) {
$redirect_uri = '/';
} else {
$url = Url::fromRoute('entity.node.canonical', ['node' => $nid]);
$redirect_uri = $url->toString();
}
if ($redirect_uri != $current_uri) {
$event->setResponse(new RedirectResponse($redirect_uri));
}
}
}
static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = ['onRequest'];
return $events;
}
}
I believe this line is the issue:
$event->setResponse(new RedirectResponse($redirect_uri));
At the issue linked above, a kind user suggested a solution that I do not quite understand, they said:
The problem is, you should never send a response inside of a StackPHP application. Drupal continues to build its own response (the real frontpage) and stores this in the cache. Set the response in the event instead: $event->setResponse($response);
I'm not sure exactly where he means by setting the response "in the event" instead.
Now, as this issue only is a problem on urls with ?
in them, I did find I could correct the issue by wrapping the line above, line 37 thusly:
if (strpos($current_uri, '?') != TRUE) {
$event->setResponse(new RedirectResponse($redirect_uri));
}
However I worry this might cause unpredictable behavior and I prefer to fix this the right way the first time. Can someone tell me what I'm doing wrong or overlooking or explain how I can "set the response in the event" instead?
$response->send();
Your code is correct in this point. By the way, what you are trying to do is a route normalizer, which is planned to be included in core, see drupal.org/project/drupal/issues/2641118. In the meantime you can use the contrib module Redirect.