[Symfony] Récupérer la charge utile d'une requête HTTP POST

Publié le 22/02/2020 • Mis à jour le 22/02/2020


English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧

Dans ce bout de code nous allons voir comment récupérer la charge utile (🇬🇧 payload en anglais) d'une requête HTTP POST. C'est utile par exemple quand on veut créer un point d'accès d'API (endpoint). On voudra envoyer objet JSON comme :

{
  "firstname": "Fab",
  "lastname": "pot"
}

Veuillez noter que si vous lancez le snippet avec le bouton "exécutez", la charge utile sera vide puisqu'on a accède à la page avec la méthode GET. Pour tester si ça fonctionne, utilisez cURL ou utilisez un client REST comme postman avec l'exemple ci-dessus. Vous devez poster ce message à l'URL : "/fr/snippets/recuperer-la-charge-utile-d-une-requete-http-post/run". Attention, la fonction json_decode() ne retourne par forcément un tableau. Si vous utilisez une chaîne comme "1111", celle-ci sera considérée comme du JSON valide et un entier sera retourné à la place d'un tableau.


<?php declare(strict_types=1);

// src/Controller/Snippet/Snippet79Trait.php

namespace App\Controller\Snippet;

use Symfony\Component\HttpFoundation\Request;
use function Symfony\Component\String\u;

/**
 * J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
 * Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
 * ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Les services sont injectés dans le constructeur du contrôleur principal.
 *
 * @see https://symfony.com/doc/current/components/string.html
 */
trait Snippet79Trait
{
    public function snippet79(Request $request): void
    {
        // Payload is a string
        $payloadString = $request->getContent();
        echo sprintf('$payloadString (%s)  : "%s"'."\n", gettype($payloadString), $payloadString);

        // But if you pass true as the first argument it will return a resource object
        $payloadResource = $request->getContent(true);
        echo sprintf('$payloadResource (%s)'."\n", gettype($payloadResource));

        $u = u($payloadString); // Let's play with the new string component

        // if empty, nothing to do left
        if ($u->isEmpty()) {
            echo 'Payload is empty! (test with cURL or postman)'."\n";

            return;
        }

        if ($u->length() > 100) {
            echo 'Payload is too big!'."\n";

            return;
        }

        $json = json_decode($payloadString, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            echo "Can't decode payload!"."\n";

            return;
        }

        echo 'JSON is valid:'."\n";
        var_dump($json);

        // This line will allow us to see the results when using CURL or postman without having the full HTML rendering
        if ($request->isMethod(Request::METHOD_POST)) {
            die();
        }

        // That's it! 😁
    }
}