Question

I have a custom module named rsc.

My Default 404 (not found) page is set to /page-not-found in Basic site settings.

My rsc.routing.yml file contains

  rsc.pageNotFound:
    path: '/page-not-found'
    defaults:
      _controller: 'Drupal\rsc\Controller\rscController::pageNotFound'
      _title: ''
    requirements:
      _permission: 'access content'

My rscController.php file contains:

  class rscController extends ControllerBase
  {
    public function pageNotFound()
    {
      $path = '/test-page'; // Just for testing

      if (($url = \Drupal::service('path.validator')->getUrlIfValid($path))) {
        $route = $url->getRouteName();
        $param = $url->getRouteParameters();
        error_log("route=$route param=" . print_r($param, true));
        return $this->redirect($route, $param);
      }
      else {
        return
        [
          '#markup' => 'No such page'
        ];
      }
    }
  }

/test-page is the alias for /node/125.

If I type mywebsite.com/junk in the address bar (to force the not found page to be invoked) and press Enter, I am always redirected to the home page, even though the error log contains the result

route=entity.node.canonical param=Array ( [node] => 125 )

What am I doing wrong? Why doesn't $this->redirect() take me to the node?

Was it helpful?

Solution

When you call a controller as error page via the basic site settings this is not the controller of the main request, this controller is executed in a subrequest to get a themed output of the otherwise simple text message you see for non 4xx exceptions like a 500 error.

Better place the redirect in the main request, before the rendering of the exception is delegated to a subrequest by CustomPageExceptionHtmlSubscriber. You can use the default priority 0, because the core exception handler has -50.

@MarshallMorrise has posted the working code at https://drupal.stackexchange.com/a/290659/47547

Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top