1

I need to display custom logic in 404 pages so I have overridden the route controller of the system.404 route like this:

class RouteSubscriber extends RouteSubscriberBase {

  protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('system.404')) {
      $route->setDefault('_controller', '\Drupal\mymodule\Controller\myController::on404');
    }
  }
}

So let's say I am currently at the path /non-existing-path and the on404 callback renders my custom content just fine. Problem is I am also rendering a form that contains an Ajax element (a button), which doesn't work because apparently the Ajax request is made towards the following path:

/system/404?q=non-existing-path&destination=non-existing-path&_exception_statuscode=404&ajax_form=1&_wrapper_format=drupal_ajax

which, not unexpectedly, returns a Status Code: 404 Not Found

What am I missing?

--

So far I've tried intercepting the NotFoundHttpException with my own listener and changing it to a HttpException(200) in hopes I could turn a 404 page into a 200 but I am at a loss after that and it seems like an overkill.

7
  • If you want to try to change the 404 to a 200 set a redirect response in the event listener.
    – 4k4
    Aug 3 '21 at 6:34
  • thanks but this will redirect me to another path, I want to stay at the current path (that doesn't exist) and render my content together with the ajax form Aug 3 '21 at 10:30
  • OK, then I misread your last sentence. Concerning the main topic. /system/404 doesn't return a 404 status code when used outside of an exception. It returns the content of system.404 in a 200 response and it works with Ajax. Just tested it by setting a form as 404 content.
    – 4k4
    Aug 3 '21 at 11:32
  • Thanks for looking into it but to make it more clear, I am trying to render a form (with an ajax button in it), in the default 404 page. So whenever someone hits a non existent page, the "Page not found" message appears and below it the form. Problem is the ajax button doesnt work. Aug 3 '21 at 22:30
  • As explained, I can't reproduce the issue. The system/404 route returns a 200 (not a 404 as you've mentioned) and Ajax actions over this route work without problems in my tests with two different forms, a custom form and a core form (node edit form).
    – 4k4
    Aug 4 '21 at 6:17
0

Ajax form inside custom system.404 route controller does work

For example a node form returned from the controller:

<?php

namespace Drupal\mymodule\Controller;    

use Drupal\node\Entity\Node;

class MyController extends ControllerBase {

  public function on404() {
    $node = Node::create(['type' => 'article']);
    return $this->entityFormBuilder()->getForm($node);
  }

}

The node form is fully functional including complex Ajax operations like opening the media browser.

Status code 404 or 200

Problem is I am also rendering a form that contains an Ajax element (a button), which doesn't work because apparently the Ajax request is made towards the following path:

/system/404?q=non-existing-path&destination=non-existing-path&_exception_statuscode=404&ajax_form=1&_wrapper_format=drupal_ajax

which, not unexpectedly, returns a Status Code: 404 Not Found

This is not true, a request for /system/404 returns a 200 status code when called outside of an exception handler, for example in an ajax request. The system.404 route is a normal route which is executed by the exception handler in a sub-request. The 404 status is added later and not part of this route.

1
  • "The system.404 route is a normal route which is executed by the exception handler in a sub-request" this helped point me in the right direction. Thanks for all the help! Aug 4 '21 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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