Développer une API REST avec Symfony
Introduction à REST et concepts fondamentaux
Les applications web modernes utilisent presque systématiquement des appels à des fonctionnalités distantes. Cette approche permet notamment de pouvoir bénéficier de fonctionnalités riches et réutilisables mises à disposition sur Internet par des éditeurs. Ainsi, intégrer une carte géographique, utiliser des fonctionnalités de paiement en ligne ou encore intégrer les réseaux sociaux dans une application ou un site web est largement facilité.
Les concepts sous-jacents sont ceux des services web. Historiquement articulés autour du langage XML, cette approche s’est simplifiée avec l’arrivée des services en architecture REST, permettant de s’affranchir de la lourdeur d’XML. Les services en architecture REST permettent de mettre à disposition de véritables API utilisables et invocables en HTTP sur Internet.
1. Les concepts de REST
REST est un acronyme signifiant REpresentational State Transfer. L’idée est de placer une application dans un état de représentation de ses ressources en fonction de l’action demandée. Cette architecture de construction d’application s’appuie sur le protocole HTTP et sur la notion de ressource.
REST n’est pas à proprement parler un standard dans la mesure où...
La gestion du format JSON
Le format JSON est une constituante indispensable des architectures REST. Bien que ces architectures puissent utiliser n’importe quel format d’échange, JSON n’en reste pas moins celui qui est largement plébiscité grâce à sa simplicité et à sa légèreté.
1. Présentation du format JSON
Le format JSON (JavaScript Object Notation) est un format de données textuel inspiré de la notation des objets JavaScript, créé à partir de 2002 par Douglas Crockford. L’objectif du format JSON est de faciliter les échanges de données applicatives sur le Web, échanges qui étaient auparavant systématiquement basés sur XML. Ce dernier étant jugé trop verbeux et donc consommateur de bande passante, JSON constitue une alternative plus légère pour ces échanges.
a. Représentation des données en JSON
JSON représente les données sous forme d’objets. Ils sont constitués d’attributs exprimés grâce à des paires clé/valeur, la clé correspondant au nom de l’attribut et la valeur à la donnée associée. Cette donnée peut être un numérique, une chaîne de caractères, un autre objet ou bien un tableau.
Les clés sont des chaînes de caractères et il est nécessaire de les exprimer entre guillemets.
Les valeurs sont séparées des clés...
Mise en place d’une API REST
La mise en place d’une API REST avec Symfony est une chose relativement aisée dans la mesure où le framework propose nativement tous les outils nécessaires. Nous avons déjà vu au cours de cet ouvrage le développement des contrôleurs et de leurs actions et comment les associer à des URL ; cela permet de structurer l’API.
De plus, la prise en charge du format JSON pour l’échange des données nous permet de facilement gérer ce format dans la requête comme dans la réponse.
1. Le service serializer
Avant de nous permettre de manipuler des données en JSON, il est nécessaire d’installer le sérialiseur Symfony. Ce sérialiseur sera ensuite disponible sous forme d’un service injectable dans les classes de votre application.
Pour installer ce service nommé serializer, il faut exécuter une recette Flex avec la commande suivante :
composer require symfony/serializer-pack
Une fois installé, le service est injectable dans les actions de contrôleur via l’interface Symfony\Component\Serializer\SerializerInterface :
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Serializer\SerializerInterface;
class DefaultController extends AbstractController ...
Les objets de requête et de réponse
Les objets Symfony représentant la requête et la réponse HTTP ont déjà été largement présentés et utilisés dans cet ouvrage. Pour rappel, ils sont respectivement des types Symfony\Component\HttpFoundation\Request et Symfony\Component\HttpFoundation\Response.
Dans les actions des contrôleurs REST, la requête est disponible sous forme d’un paramètre injecté par Symfony dans la méthode, et la réponse constitue le type de retour de ces méthodes, comme dans le fragment de code suivant :
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
...
public function creer(Request $request, SerializerInterface
$serializer): Response
{
...
}
L’objet de requête n’est pas systématiquement nécessaire. En effet, il n’est utile que lorsque des données seront transportées dans le corps de la requête, typiquement sur des actions liées aux méthodes HTTP PUT et POST.
1. Le contenu et les en-têtes de requête
Lors de la manipulation des données entrantes, il est nécessaire de pouvoir récupérer les en-têtes et le corps de la requête.
Les en-têtes contiennent notamment le type de données envoyées par le client. Cette information est accessible via la méthode getContentType().
Dans le cas où des données JSON sont transmises dans la requête, elles le sont dans le corps ; ce contenu est accessible avec la méthode getContent().
Voici comment pourrait être structuré le code d’une action recevant un flux JSON en HTTP POST :
#[Route(
'/api/article',
name: 'api_article_creer',
methods: ['POST']
)]
public function creer(
Request $request, SerializerInterface $serializer
): Response
{
// On contrôle le format de données...
Tester une API REST
1. Les limites du navigateur web
Dans le cadre du développement d’une application web traditionnelle utilisant des vues, il est assez simple de constater le rendu des pages grâce à son navigateur web.
Pour une API REST c’est différent. En effet, nous pourrons toujours l’utiliser pour tester les actions qui réagissent sur des requêtes HTTP de type GET, mais pour les requêtes POST, PUT et DELETE c’est compliqué, le navigateur n’est pas prévu pour cela.
Bien sûr, nous pouvons créer des tests fonctionnels s’appuyant sur PHPUnit et les objets Client et Crawler, comme évoqué dans le chapitre Tester son application Symfony, mais il est tout de même pratique de pouvoir consulter les réponses renvoyées par l’API dans les phases de développement. Nous allons pour cela utiliser des outils dédiés au test d’API REST.
2. Les outils
Les outils de test des API REST ne sont ni plus ni moins que des générateurs de requêtes HTTP permettant de recevoir et d’explorer des réponses HTTP. En véritables outils pour le développeur, ils permettent de regrouper les requêtes en projets ainsi que de spécifier les éventuels en-têtes et contenu de ces requêtes.
a. Postman
Postman est un outil développé...
Créer une API REST avec API Platform
1. Présentation
API Platform est une librairie qui permet de créer simplement des API REST. Cette librairie est maintenue par Les Tilleuls.coop (https://les-tilleuls.coop) une entreprise française. Il existe un package permettant d’utiliser toute la souplesse d’API Platform dans Symfony et créer ainsi des API REST en un temps record !
2. Installation
Pour disposer du package API Platform dans son projet, il faut exécuter la recette Symfony correspondante à l’aide de la commande :
composer require api
Une fois la recette exécutée, API Platform est en place. Vous pouvez en valider l’installation en navigant à l’adresse http://<monsite>/api.
Pour le moment, aucune opération n’est disponible, mais cela va changer rapidement à l’aide de quelques attributs ou annotations sur les entités Doctrine de l’application.
3. La configuration d’API Platform
Au-delà de la librairie installée dans le dossier vendor/ du projet Symfony, d’autres fichiers sont apportés par l’installation d’API Platform, notamment :
-
config/routes/api_platform.yaml : contient le path de la route permettant d’accéder à l’interface de l’API, le path /api vient de cette déclaration et peut être modifié.
-
config/packages/api_platform.yaml : contient le paramétrage de base d’API Platform, et notamment la référence au répertoire qui contient les entités Doctrine à analyser. Il est également possible d’ajouter des métadonnées pour personnaliser l’interface.
Exemple de personnalisation :
api_platform:
title: "API REST pour MonJournal !" ...