logo

Extra Block Types (EBT) - Nuova esperienza con Layout Builder❗

Extra Block Types (EBT) - tipi di blocchi stilizzati e personalizzabili: Slideshows, Tabs, Cards, Accordion e molti altri. Impostazioni integrate per sfondo, DOM Box, plugin javascript. Vivi oggi il futuro della costruzione dei layout.

Demo moduli EBT Scarica moduli EBT

❗Extra Paragraph Types (EPT) - Nuova esperienza con Paragraphs

Extra Paragraph Types (EPT) - insieme di moduli basati su paragrafi in modo analogo.

Demo moduli EPT Scarica moduli EPT

Scorri

Aggiunta della pagina di errore 500 in Drupal utilizzando un Event Subscriber

02/09/2025, by Ivan

Menu

Spesso ci troviamo di fronte alla pagina di errore 500 quando Drupal, i servizi o altri siti non sono disponibili. Quando vediamo una pagina di errore 500 (o 501-504). In Drupal usiamo le Exception per controllare che un certo codice critico sia stato eseguito. Se riceviamo un errore, ad esempio in una richiesta HTTP a un altro sito, allora Drupal mostrerà questo errore: "Il sito ha riscontrato un errore imprevisto. Riprova più tardi":

Drupal default 500 error page
Drupal default 500 error page

Non è una buona pratica avere la WSOD (white screen of death) sul tuo sito, quindi miglioriamola e mostriamo invece una pagina HTML stilizzata.

Ho una pagina 500.html stilizzata nella root del mio sito, per motivi di performance. Possiamo usare una pagina Drupal stilizzata per l'errore 500, ma io userò la stessa pagina anche per gli errori 503/504 in Apache/Nginx ed è più semplice mantenere questa pagina in un unico file HTML.

500 HTML page
500 HTML error page

Ora dobbiamo aggiungere codice nel nostro modulo personalizzato DrupalBook Custom (drupalbook_custom). In drupalbook_custom.services.yml dobbiamo aggiungere un Event Subscriber:

services:
  drupalbook_custom.exception_subscriber:
    class: Drupal\drupalbook_custom\EventSubscriber\SeoExceptionSubscriber
    arguments: ['@config.factory']
    tags:
      - { name: event_subscriber, priority: -250 }

Ecco il codice per drupalbook_custom/src/EventSubscriber/SeoExceptionSubscriber:

<?php

namespace Drupal\drupalbook_custom\EventSubscriber;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Utility\Error;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Sostituisce il 500 error di Drupal\Core\EventSubscriber\FinalExceptionSubscriber.
 */
class SeoExceptionSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * Configurazioni delle impostazioni.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $configFactory;

  public function __construct(ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;
  }

  /**
   * Gestisce qualsiasi eccezione non intercettata e restituisce una risposta HTML personalizzata.
   */
  public function onException(ExceptionEvent $event): void {
    // Mostra il normale stack trace di Drupal quando il sito è in modalità VERBOSE.
    if ($this->isErrorLevelVerbose()) {
      return;
    }

    $exception = $event->getThrowable();

    // Messaggio di base (estendibile in modalità verbose se necessario).
    $error = Error::decodeException($exception);
    $message = new FormattableMarkup('@message', [
      '@message' => $error['!message'] ?? $this->t('Il sito ha riscontrato un errore imprevisto.'),
    ]);

    $html = $this->buildHtml((string) $message);
    $status = $exception instanceof HttpExceptionInterface
      ? $exception->getStatusCode()
      : Response::HTTP_INTERNAL_SERVER_ERROR;

    $response = new Response($html, $status, ['Content-Type' => 'text/html']);

    // Mantieni header extra come Retry-After se presenti.
    if ($exception instanceof HttpExceptionInterface) {
      $response->headers->add($exception->getHeaders());
    }

    // Invia la risposta e interrompi altri subscriber (incluso quello core).
    $event->setResponse($response);
    $event->stopPropagation();
  }

  /**
   * Legge web/500.html e sostituisce il token {{ message }} se presente.
   */
  protected function buildHtml(string $message): string {
    $template = DRUPAL_ROOT . '/500.html';

    if (is_readable($template)) {
      $html = file_get_contents($template);
      return str_replace('{{ message }}', Markup::create($message), $html);
    }

    // Fallback sicuro se il template è mancante.
    return '<html><head><title>500</title></head><body>'
      . Markup::create($message)
      . '</body></html>';
  }

  /**
   * TRUE quando il livello di errore è impostato su “Verbose”.
   *
   * Replica \Drupal\Core\EventSubscriber\FinalExceptionSubscriber::isErrorLevelVerbose().
   */
  protected function isErrorLevelVerbose(): bool {
    return $this->configFactory
      ->get('system.logging')
      ->get('error_level') === ERROR_REPORTING_DISPLAY_VERBOSE;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // Priorità -250 → viene eseguito appena prima di FinalExceptionSubscriber del core (-256).
    $events[KernelEvents::EXCEPTION][] = ['onException', -250];
    return $events;
  }

}

Questa classe subscriber, SeoExceptionSubscriber, intercetta tutte le eccezioni non gestite in Drupal. Controlla se il tuo sito Drupal è impostato sulla modalità di report degli errori "verbose" e, in tal caso, permette a Drupal di mostrare i suoi normali messaggi di errore dettagliati. Tuttavia, se il sito non è in modalità verbose (tipico in ambiente di produzione), cattura l'eccezione e prepara invece un messaggio di errore più user-friendly.

Nello specifico, legge il tuo file personalizzato 500.html posizionato nella root dell'installazione Drupal. Inserisce dinamicamente il messaggio di errore nel contenuto HTML sostituendo il token {{ message }}, garantendo che la pagina mostrata sia sia informativa che visivamente coerente.

Inoltre, lo subscriber interrompe esplicitamente il gestore di errori predefinito di Drupal. Questo assicura che la pagina di errore interna di Drupal non sovrascriva la tua pagina HTML personalizzata. Definendo lo subscriber con una priorità di -250, viene eseguito appena prima dello subscriber integrato di Drupal core, sovrascrivendo efficacemente il comportamento predefinito di Drupal.

Per il tuo ambiente locale puoi inserire impostazioni per mostrare gli errori invece della pagina di errore 500.
settings.php:

$config['system.logging']['error_level'] = 'verbose';

error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

A volte Drupal non è raggiungibile, quindi sarà necessario impostare configurazioni aggiuntive per il tuo web server o Cloud.

Aggiungere la pagina di errore 500 in Apache

Per servire la tua pagina di errore 500.html esistente dalla root del tuo sito ogni volta che si verificano errori HTTP 500–504, devi configurare Apache di conseguenza. Ecco due modi semplici per farlo:

1. Utilizzando la configurazione Virtual Host di Apache (raccomandato)

Modifica il file di configurazione del virtual host del tuo sito (tipicamente situato in /etc/apache2/sites-available/your-site.conf) e aggiungi le seguenti direttive all’interno del blocco <VirtualHost>:

ErrorDocument 500 /500.html
ErrorDocument 501 /500.html
ErrorDocument 502 /500.html
ErrorDocument 503 /500.html
ErrorDocument 504 /500.html

Poi ricarica Apache per applicare i cambiamenti:

sudo systemctl reload apache2

2. Utilizzando il file .htaccess

Se preferisci usare il file .htaccess (posizionato nella root del tuo sito), inserisci semplicemente queste righe:

ErrorDocument 500 /500.html
ErrorDocument 501 /500.html
ErrorDocument 502 /500.html
ErrorDocument 503 /500.html
ErrorDocument 504 /500.html

Assicurati che il file 500.html sia collocato nella directory root del tuo sito, accessibile e leggibile da Apache. Dopo aver applicato queste impostazioni, Apache mostrerà in modo coerente la tua pagina HTML stilizzata per gli errori dal 500 al 504.

Aggiungere la pagina di errore 500 in Nginx

Per configurare Nginx in modo che serva la tua pagina di errore personalizzata 500.html posizionata nella root del sito per errori HTTP (500–504), aggiorna la configurazione del tuo server Nginx come segue:

Modifica il file di configurazione del tuo sito Nginx (tipicamente in /etc/nginx/sites-available/your-site.conf) e inserisci le seguenti direttive all’interno del blocco server {}:

error_page 500 501 502 503 504 /500.html;
location = /500.html {
    root /var/www/html;
    internal;
}

Assicurati che il percorso (/var/www/html) punti correttamente alla root del tuo sito che contiene il file 500.html. Dopo la modifica, ricarica la configurazione di Nginx per applicare le modifiche:

sudo nginx -s reload

Ora Nginx mostrerà la tua pagina di errore HTML personalizzata in modo coerente per gli stati di errore HTTP dal 500 al 504.