-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactoring the conversion of exceptions
- Loading branch information
Florian Krämer
committed
Jan 6, 2025
1 parent
aee6944
commit aa044cd
Showing
13 changed files
with
362 additions
and
315 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Phauthentic\Symfony\ProblemDetails\ExceptionConversion; | ||
|
||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpKernel\Event\ExceptionEvent; | ||
use Throwable; | ||
|
||
/** | ||
* Handles Thowable and converts them into a Problem Details HTTP response. | ||
* | ||
* Notice that you might need to adjust the priority of the listener in your services.yaml file to make sure it is | ||
* executed in the right order if you have other listeners. | ||
*/ | ||
interface ExceptionConverterInterface | ||
{ | ||
public function canHandle(Throwable $throwable): bool; | ||
|
||
public function convertExceptionToErrorDetails(Throwable $throwable, ExceptionEvent $event): Response; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Phauthentic\Symfony\ProblemDetails\ExceptionConversion; | ||
|
||
use Phauthentic\Symfony\ProblemDetails\ProblemDetailsFactoryInterface; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpKernel\Event\ExceptionEvent; | ||
use Throwable; | ||
|
||
/** | ||
* Handles Thowable and converts it into a Problem Details HTTP response. | ||
* | ||
* Notice that you might need to adjust the priority of the listener in your services.yaml file to make sure it is | ||
* executed in the right order if you have other listeners. | ||
* | ||
* <code> | ||
* Phauthentic\Symfony\ProblemDetails\ThrowableToProblemDetailsKernelListener: | ||
* arguments: ['%kernel.environment%', { }] | ||
* tags: | ||
* - { name: kernel.event_listener, event: kernel.exception, priority: -20 } | ||
* </code> | ||
* | ||
* @link https://www.rfc-editor.org/rfc/rfc9457.html | ||
*/ | ||
class GenericThrowableConverter implements ExceptionConverterInterface | ||
{ | ||
/** | ||
* @param ProblemDetailsFactoryInterface $problemDetailsFactory | ||
* @param string $environment | ||
* @param array<callable> $mappers | ||
*/ | ||
public function __construct( | ||
protected ProblemDetailsFactoryInterface $problemDetailsFactory, | ||
protected string $environment = 'prod', | ||
protected array $mappers = [] | ||
) { | ||
} | ||
|
||
public function canHandle(Throwable $throwable): bool | ||
{ | ||
return true; | ||
} | ||
|
||
public function convertExceptionToErrorDetails(Throwable $throwable, ExceptionEvent $event): Response | ||
{ | ||
$extensions = []; | ||
if ($this->environment === 'dev' || $this->environment === 'test') { | ||
$extensions['trace'] = $throwable->getTrace(); | ||
} | ||
|
||
return $this->problemDetailsFactory->createResponse( | ||
status: Response::HTTP_INTERNAL_SERVER_ERROR, | ||
title: $throwable->getMessage(), | ||
extensions: $extensions, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Phauthentic\Symfony\ProblemDetails\ExceptionConversion; | ||
|
||
use Phauthentic\Symfony\ProblemDetails\ProblemDetailsFactoryInterface; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpKernel\Event\ExceptionEvent; | ||
use Symfony\Component\HttpKernel\Exception\HttpException; | ||
use Throwable; | ||
|
||
/** | ||
* Handles Symfony\Component\HttpKernel\Exception\HttpException exceptions and converts them into Problem Details HTTP | ||
* responses. | ||
* | ||
* Notice that you might need to adjust the priority of the order in your services.yaml file to make sure it is | ||
* executed in the right order if you have other converters. | ||
* | ||
* @link https://www.rfc-editor.org/rfc/rfc9457.html | ||
*/ | ||
class HttpExceptionConverter implements ExceptionConverterInterface | ||
{ | ||
public function __construct( | ||
protected ProblemDetailsFactoryInterface $problemDetailsFactory | ||
) { | ||
} | ||
|
||
public function canHandle(Throwable $throwable): bool | ||
{ | ||
return $throwable instanceof HttpException; | ||
} | ||
|
||
public function convertExceptionToErrorDetails(Throwable $throwable, ExceptionEvent $event): Response | ||
{ | ||
/** @var HttpException $throwable */ | ||
return $this->problemDetailsFactory->createResponse( | ||
status: $throwable->getStatusCode(), | ||
type: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/' . $throwable->getStatusCode(), | ||
title: $throwable->getMessage() | ||
); | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/ExceptionConversion/ValidationFailedExceptionConverter.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Phauthentic\Symfony\ProblemDetails\ExceptionConversion; | ||
|
||
use Phauthentic\Symfony\ProblemDetails\FromExceptionEventFactoryInterface; | ||
use Phauthentic\Symfony\ProblemDetails\Validation\ValidationErrorsBuilder; | ||
use RuntimeException; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpKernel\Event\ExceptionEvent; | ||
use Symfony\Component\HttpKernel\Exception\HttpException; | ||
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; | ||
use Symfony\Component\Validator\Exception\ValidationFailedException; | ||
use Throwable; | ||
|
||
/** | ||
* Notice that you might need to adjust the priority of the order in your services.yaml file to make sure it is | ||
* executed in the right order if you have other converters. | ||
*/ | ||
class ValidationFailedExceptionConverter implements ExceptionConverterInterface | ||
{ | ||
public function __construct( | ||
protected ValidationErrorsBuilder $validationErrorsBuilder, | ||
protected FromExceptionEventFactoryInterface $problemDetailsResponseFactory | ||
) { | ||
} | ||
|
||
public function canHandle(Throwable $throwable): bool | ||
{ | ||
if ($throwable instanceof UnprocessableEntityHttpException) { | ||
$throwable = $throwable->getPrevious(); | ||
} | ||
|
||
return $throwable instanceof ValidationFailedException; | ||
} | ||
|
||
private function extractValidationFailedException(Throwable $throwable): ValidationFailedException | ||
{ | ||
if ($throwable instanceof UnprocessableEntityHttpException) { | ||
$throwable = $throwable->getPrevious(); | ||
} | ||
|
||
if ($throwable instanceof ValidationFailedException) { | ||
return $throwable; | ||
} | ||
|
||
throw new RuntimeException('ValidationFailedException not found'); | ||
} | ||
|
||
public function convertExceptionToErrorDetails(Throwable $throwable, ExceptionEvent $event): Response | ||
{ | ||
$throwable = $this->extractValidationFailedException($throwable); | ||
|
||
$errors = $this->validationErrorsBuilder->buildErrors($throwable); | ||
|
||
return $this->problemDetailsResponseFactory->createResponseFromKernelExceptionEvent($event, $errors); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.