api-platform icon indicating copy to clipboard operation
api-platform copied to clipboard

Validation in DTO not working in api-platform 3.2

Open ackalhan opened this issue 1 year ago • 3 comments

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

ackalhan avatar Nov 08 '23 07:11 ackalhan

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)

Alexandre-T avatar Nov 19 '23 05:11 Alexandre-T

Any updates on this? This completely error handling in some parts of my API. What's the workaround here?

mtret avatar Mar 14 '24 13:03 mtret