feat: make server errors visible to the user for htmx requests
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* Returns an error modal for unhandled exceptions on HTMX requests.
|
||||
*
|
||||
* Without this, a 500 from an HTMX endpoint is silently discarded by the browser
|
||||
* and the user sees nothing. This listener intercepts those exceptions and returns
|
||||
* a 200 with the error modal HTML, using HX-Retarget/HX-Reswap to append it to
|
||||
* <body> regardless of the original hx-target.
|
||||
*/
|
||||
class HtmxExceptionListener implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(private readonly Environment $twig)
|
||||
{
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::EXCEPTION => ['onKernelException', -10],
|
||||
];
|
||||
}
|
||||
|
||||
public function onKernelException(ExceptionEvent $event): void
|
||||
{
|
||||
if (false === $event->getRequest()->headers->has('HX-Request')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event->hasResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$html = $this->twig->render('htmx_error_modal.html.twig');
|
||||
|
||||
$response = new Response($html, Response::HTTP_OK);
|
||||
$response->headers->set('HX-Retarget', 'body');
|
||||
$response->headers->set('HX-Reswap', 'beforeend');
|
||||
|
||||
$event->setResponse($response);
|
||||
$event->allowCustomResponseCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% embed '_partials/_modal.html.twig' with { 'level': 'error' } %}
|
||||
{% block title %}
|
||||
Oops...
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% include '_partials/_alert.html.twig' with {
|
||||
level: 'error',
|
||||
modal: true,
|
||||
messages: ['Da ist etwas schiefgelaufen. Wir haben uns Notizen gemacht und kümmern uns schnellstmöglich darum.']
|
||||
} %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
Reference in New Issue
Block a user