Mart has become a complex platform since its humble beginnings. It today handles multi-domain installations enabling multiple diverse sites within a single Drupal site based on domain hosts. To enable multi-domain installations, Mart automatically issues redirects based on a set of rules to send users to correct site / domain for a specific page / node etc.
In a recent instance, we were trying to troubleshoot a scenario where the home page of a domain was being redirected to a specific node, i.e. https://example.com was being redirected to https://example.com/node/96. This was unexpected and the redirect should not have happened.
We checked and confirmed the redirect wasn’t coming from Mart or any of its sub-modules. Now the issue was figuring out who was issuing this redirect in the entire Drupal infrastructure we had. It could have been anything, from Drupal core or the modules shipped with core, the limited set of contrib modules we were using (namely token
, pathauto
, redirect
, metatag
and a handful more).
“Venerable” Drupal 7 had drupal_goto
for redirecting providing a very convenient hook hook_drupal_goto_alter
. The best thing about this hook was it was invoked from within the drupal_goto
call, which meant you could very easily check / log the stack trace if needed from within your hook_drupal_goto_alter
implementation making it a breeze to know who actually issued the redirect.
This change record however mentions using an event listener on kernal.response
for altering a redirect:
https://www.drupal.org/node/2023537
The problem with this approach is its too late to know who issued the redirect as the stack trace of the time when the redirect was issued is lost. Yes, you can still alter the redirect; just can’t know who issued it in the first place.
After going back and forth, I ultimately opened up the RedirectResponse
class from Symfony. It resides here inside your Drupal 8 / 9 installation:~/vendor/symfony/http-foundation/RedirectResponse.php
And added the following inside the constructor:
var_dump(debug_stacktrace());
As ugly as it may seem, it got the job done. I immediately figured the redirect was coming from redirect
module’s RouteNormalizerRequestSubscriber::onKernelRequestRedirect
. And it was because of a caching issue. One of our modules had updated a domain related configuration and did not clear relevant cached data from within Drupal causing a redirect.
Like I said, ugly but functional. Do not try it on production, or accidently leave the code behind. Can mess up your entire Drupal site.
Meanwhile if any of you have any alternate approaches to know the stack trace at the time a redirect was issued in Drupal 8 / 9, I will be all ears. Creating a sub-class for Symfony’s RedirectResponse
class and logging it in the constructor there and then injecting your sub-class would be an overkill imho for this simple debugging scenario. Plus you won’t be able to troubleshoot if some code issues a TrustedRedirectResponse
(or SecuredRedirectResponse
or a CacheableSecuredRedirectResponse
etc) as the same extend RedirectResponse
and your class won’t be involved for them. For unawares, TrustedRedirectResponse
is used to redirect to external urls in Drupal.
Recent Comments