3

I'm looking for a way to handle 404's on images in Drupal. I have created several subscribers, but none seem to get triggered. My first try was to create subscriber that extends RouteSubscriberBase. The alterRoutes method looked like:

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

This works perfectly for all 404's except for images (ending in .jpg or .png). This will still generate a default 404 page. It's actually a light-weight version, not the same as a 404 on a non-image non-existing page. When I debug through the Drupal code (starting in index.php) I see it goes through many steps before generating that light 404. So it does reach the Drupal code.

I found one particular interesting bit of code (which is reached when visiting a non-existing image):

$this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);

This can be found in the handle method of Symfony\Component\HttpKernel\HttpKernel. With that knowledge I managed to find this page: https://www.drupal.org/node/2331613 . Again, it doesn't seem to work. What I have now:

my_module.services.yml:

my_module.exception_image_subscriber:
    class: Drupal\my_module\EventSubscriber\ExceptionImageSubscriber
    tags:
      - { name: event_subscriber }

src\EventSubscriber\ExceptionImageSubscriber.php (removed comments):

<?php
namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;

class ExceptionImageSubscriber extends HttpExceptionSubscriberBase {

  /**
   * {@inheritDoc}
   */
  protected function getHandledFormats() {
    return ['svg','jpg','gif','png','webp'];
  }

  /**
   * {@inheritdoc}
   */
  protected static function getPriority() {
    return 0;
  }

  /**
   * Handles a 404 error for images
   */
  public function on404(GetResponseForExceptionEvent $event) {
     dd('test'); // <- not firing?!
  }
}

This doesn't seem to do anything, not for non-images or for images.

I start to believe the problem is that modules are not loaded when images are requested. Is there any way around this issue?

5

The light-weight version are fast 404 pages. They are configurable in system.performance.yml. The configuration can be overridden in settings.php. The default is:

$config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i';

If you want to override this 404 handling in code your exception subscriber needs a priority >200:

  protected static function getPriority() {
    return 300;
  }

and the format has to be html, not the file extensions:

  protected function getHandledFormats() {
    return ['html'];
  }

For reference https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21EventSubscriber%21Fast404ExceptionHtmlSubscriber.php/class/Fast404ExceptionHtmlSubscriber

1
  • So close, yet so far away :). I did come across the fast_404 option, but didn't find the solution. Thanks a lot!
    – Frank
    Dec 24 '21 at 11:52

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.