Api Platform Conference

The conference dedicated to API Platform and its ecosystem

Sep 21, 22 2023 | Lille & online

Accept application/x-www-form-urlencoded Form Data

API Platform only supports raw documents as request input (encoded in JSON, XML, YAML...). This has many advantages including support of types and the ability to send back to the API documents originally retrieved through a GET request. However, sometimes - for instance, to support legacy clients - it is necessary to accept inputs encoded in the traditional application/x-www-form-urlencoded format (HTML form content type). This can easily be done using the powerful event system of the framework.

⚠ Adding support for application/x-www-form-urlencoded makes your API vulnerable to CSRF attacks. Be sure to enable proper countermeasures such as DunglasAngularCsrfBundle.

In this tutorial, we will decorate the default DeserializeListener class to handle form data if applicable, and delegate to the built-in listener for other cases.

Create your DeserializeListener Decorator

This decorator is able to denormalize posted form data to the target object. In case of other format, it fallbacks to the original DeserializeListener.

// api/src/EventListener/DeserializeListener.php

namespace App\EventListener;

use ApiPlatform\Serializer\SerializerContextBuilderInterface;
use ApiPlatform\Symfony\EventListener\DeserializeListener as DecoratedListener;
use ApiPlatform\Util\RequestAttributesExtractor;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

final class DeserializeListener
    private $decorated;
    private $denormalizer;
    private $serializerContextBuilder;

    public function __construct(DenormalizerInterface $denormalizer, SerializerContextBuilderInterface $serializerContextBuilder, DecoratedListener $decorated)
        $this->denormalizer = $denormalizer;
        $this->serializerContextBuilder = $serializerContextBuilder;
        $this->decorated = $decorated;

    public function onKernelRequest(RequestEvent $event): void {
        $request = $event->getRequest();
        if ($request->isMethodCacheable(false) || $request->isMethod(Request::METHOD_DELETE)) {

        if ('form' === $request->getContentType()) {
        } else {

    private function denormalizeFormRequest(Request $request): void
        if (!$attributes = RequestAttributesExtractor::extractAttributes($request)) {

        $context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes);
        $populated = $request->attributes->get('data');
        if (null !== $populated) {
            $context['object_to_populate'] = $populated;

        $data = $request->request->all();
        $object = $this->denormalizer->denormalize($data, $attributes['resource_class'], null, $context);
        $request->attributes->set('data', $object);

Creating the Service Definition

# api/config/services.yaml
    # ...
            - { name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest', priority: 2 }
        # Autoconfiguration must be disabled to set a custom priority
        autoconfigure: false
        decorates: 'api_platform.listener.request.deserialize'
            $decorated: '@App\EventListener\DeserializeListener.inner'

What' new?

API platform conference 2023

Sep 21,22 2023: new edition of our conference dedicated to API Platform and its ecosystem!