<?php declare(strict_types=1);
namespace PPApi\EventSubscriber;
use PPApi\Model\V1\APIError;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class JSONRequestTransformer implements EventSubscriberInterface
{
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
if (
// allow GET request with header `Content-Type`
$request->isMethod('GET') ||
$request->isMethod('DELETE') ||
(
// for cases like: application/json; charset=UTF-8 etc
!str_contains($request->headers->get('Content-Type'), 'application/json') &&
// addon requesting '/authenticate' endpoint with missing content-type header
!preg_match('~^/authenticate~', $event->getRequest()->getPathInfo())
)
) {
return;
}
if (!$this->transformJsonBody($request)) {
$err = new APIError(JsonResponse::HTTP_INTERNAL_SERVER_ERROR, 'Invalid JSON format.');
$response = new JsonResponse($err, JsonResponse::HTTP_BAD_REQUEST);
$event->setResponse($response);
}
}
private function transformJsonBody(Request $request) {
$data = json_decode($request->getContent(), true);
if (json_last_error() !== JSON_ERROR_NONE) {
return false;
}
if ($data === null) {
return true;
}
$request->request->replace($data);
return true;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 100],
];
}
}