api-platform
api-platform copied to clipboard
Validation in DTO not working in api-platform 3.2
This is a sample endpoint that works well before api-platform 3.2 with 422 responses with violations
#[Route(
path: '/api/sample-endpoint',
defaults: ['_noForceRedirect' => true, '_format' => 'json'],
methods: Request::METHOD_POST
)]
public function __invoke(
#[MapRequestPayload(acceptFormat: 'json', resolver: CustomValueResolver::class)] SampleDTO $data,
string $vendor
)
<?php
namespace App\Api\Resolver;
use ApiPlatform\Symfony\Validator\Exception\ValidationException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver as DefaultRequestPayloadValueResolver;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Exception\ValidationFailedException;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
final class CustomValueResolver implements ValueResolverInterface, EventSubscriberInterface
{
private DefaultRequestPayloadValueResolver $defaultResolver;
public function __construct(
SerializerInterface&DenormalizerInterface $serializer,
?ValidatorInterface $validator = null,
?TranslatorInterface $translator = null,
) {
$this->defaultResolver = new DefaultRequestPayloadValueResolver($serializer, $validator, $translator);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::CONTROLLER_ARGUMENTS => 'onKernelControllerArguments',
];
}
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
return $this->defaultResolver->resolve($request, $argument);
}
public function onKernelControllerArguments(ControllerArgumentsEvent $event): void
{
try {
$this->defaultResolver->onKernelControllerArguments($event);
} catch (HttpException $e) {
$previous = $e->getPrevious();
if ($previous instanceof ValidationFailedException) {
throw new ValidationException($previous->getViolations());
}
throw $e;
}
}
}
After updating to 3.2 it started to send 422, with the exception stack trace
api-platform - 3.2.4 symfony - 6.3.7
IDK if it could help Api-Platform contributors, but it was well working in 3.2.4. My functional tests are validating that validation errors are handled and that API send ld+json
with @context
$this->assertMatchesPattern('{
"@context": "/contexts\/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"hydra:description": "owner: You are not allowed to set the owner to this value.",
"violations": [{
"propertyPath": "owner",
"message": "You are not allowed to set the owner to this value.",
"code": null
}]
}', $content);
So they failed because API is now sending 422 with the exception trace as soon as I upgrade to 3.2.5.
I guess it comes from the update on error listener to be compliant with the RFC 7807. I tried to update configuration, but it doesn't help:
api_platform:
defaults:
extra_properties:
rfc_7807_compliant_errors: false
(On my application, I'm using DTO, MicroMapperInterface and custom validators)
Any updates on this? This completely error handling in some parts of my API. What's the workaround here?