Created
April 6, 2018 14:12
-
-
Save mathieutu/774fb7c8bd67bc322c0eb0f0bf21e001 to your computer and use it in GitHub Desktop.
Exception Handler Symfony with GuzzleHttp Handling.
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
<?php | |
namespace App\Infrastructure\Http; | |
use Exception; | |
use GuzzleHttp\Exception\RequestException; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
use Symfony\Component\HttpFoundation\JsonResponse; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; | |
use Symfony\Component\HttpKernel\Exception\HttpException; | |
use Symfony\Component\HttpKernel\KernelEvents; | |
use Symfony\Component\HttpKernel\KernelInterface; | |
use Tightenco\Collect\Support\Arr; | |
class ExceptionHandler implements EventSubscriberInterface | |
{ | |
private $isDebug; | |
public function __construct(KernelInterface $kernel) | |
{ | |
$this->isDebug = $kernel->isDebug(); | |
} | |
public static function getSubscribedEvents() | |
{ | |
return [ | |
KernelEvents::EXCEPTION => 'handleException', | |
]; | |
} | |
public function handleException(GetResponseForExceptionEvent $event) | |
{ | |
if ($this->expectsJson($event->getRequest())) { | |
$event->setResponse($this->prepareJsonResponse($event->getException())); | |
} | |
} | |
private function expectsJson(Request $request): bool | |
{ | |
return ($request->isXmlHttpRequest() && $this->acceptsAnyContentType($request)) || $this->wantsJson($request); | |
} | |
private function acceptsAnyContentType(Request $request): bool | |
{ | |
$acceptable = $request->getAcceptableContentTypes(); | |
return count($acceptable) === 0 | |
|| (isset($acceptable[0]) && ($acceptable[0] === '*/*' || $acceptable[0] === '*')); | |
} | |
private function wantsJson(Request $request): bool | |
{ | |
$acceptable = $request->getAcceptableContentTypes(); | |
return isset($acceptable[0]) && strpos($acceptable[0], 'json') !== false; | |
} | |
private function prepareJsonResponse(Exception $e): JsonResponse | |
{ | |
$status = $this->getStatusCode($e); | |
$headers = $this->getHeaders($e); | |
return (new JsonResponse($this->convertExceptionToArray($e), $status, $headers)) | |
->setEncodingOptions(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); | |
} | |
private function convertExceptionToArray(Exception $e): array | |
{ | |
return $this->isDebug ? [ | |
'message' => $this->getMessage($e), | |
'exception' => get_class($e), | |
'file' => $e->getFile(), | |
'line' => $e->getLine(), | |
'trace' => collect($e->getTrace())->map(function ($trace) { | |
return Arr::except($trace, ['args']); | |
})->all(), | |
] : [ | |
'message' => $this->getMessage($e), | |
]; | |
} | |
private function getStatusCode(Exception $e) | |
{ | |
if ($e instanceof HttpException) { | |
return $e->getStatusCode(); | |
} | |
if ($e instanceof RequestException) { | |
return $e->getResponse()->getStatusCode(); | |
} | |
return Response::HTTP_INTERNAL_SERVER_ERROR; | |
} | |
private function getHeaders(Exception $e) | |
{ | |
if ($e instanceof HttpException) { | |
return $e->getHeaders(); | |
} | |
if ($e instanceof RequestException) { | |
return $e->getResponse()->getHeaders(); | |
} | |
return []; | |
} | |
private function getMessage(Exception $e) | |
{ | |
if ($e instanceof RequestException) { | |
if ($e->hasResponse() && $response = json_decode($e->getResponse()->getBody(), true)) { | |
return $response['message'] ?? $response; | |
} | |
return RequestException::getResponseBodySummary($e->getResponse()); | |
} | |
if ($e instanceof HttpException || $this->isDebug) { | |
return $e->getMessage(); | |
} | |
return 'Server Error'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment