API Platform 2.4 beta : MongoDB, Elasticsearch, Mercure, Symfony Messenger et bien plus !
Publié le 28 janvier 2019
Notre coopérative est fière de vous annoncer la sortie de la beta d’API Platform 2.4, enrichie d'un large éventail de nouvelles fonctionnalités ! Pour rappel, API Platform est un framework “full-stack” permettant de développer en un tour de main des projets basés sur des API. API Platform fournit :
- Une bibliothèque d'API modulaire et complète, construite sur des composants de Symfony
- Une interface d'administration générée dynamiquement à partir des spécifications de l'API, construite à l'aide de React et React Admin
- Un générateur de client permettant d'échafauder des applications React / Redux, React Native et Vue.js à partir des spécifications de l'API
API Platform supporte les formats REST modernes (JSON-LD / Hydra, JSONAPI, OpenAPI, HAL…) ainsi que GraphQL. Pour créer votre projet, il vous suffit de décrire les structures publiques des données à exposer via l'API. API Platform se chargera d'exposer l'API Web et d’amorcer les clients pour qu'ils l'utilisent.
Les fonctionnalités apportées par la version 2.4 sont de haute volée. En voici la liste :
- Support de lecture et d’écriture pour MongoDB, le système de gestion de base de données de référence pour les documents, incluant de nombreux filtres utiles.
- Support de lecture pour Elasticsearch, le moteur d'analyse et de recherche open source, incluant des filtres pour la recherche avancée.
- "Push" automatique des ressources mises à jour du serveur aux clients en utilisant le protocole Mercure.
- Intégration du composant Symfony Messenger afin d’implémenter aisément le modèle CQRS et gérer les messages de manière asynchrone (en utilisant des brokers comme RabbitMQ, Apache Kafka, Amazon SQS ou Google PubSub).
- Possibilité d'utilisation de la fonctionnalité «Server Push» de HTTP / 2 pour envoyer de manière préemptive les relations d'une ressource demandée au client.
- Disponibilité automatique des filtres de liste dans l'admin basée sur React lorsqu'un filtre correspondant est disponible côté API.
- Compatibilité totale avec la version 3 de OpenAPI (anciennement connu sous le nom de Swagger) et intégration du générateur de documentation ReDoc.
- Prise en charge améliorée des DTO.
- Configuration par ressource des en-têtes de cache HTTP
- Possibilité d'utiliser facilement l'en-tête HTTP Sunset pour annoncer la date de suppression des endpoints dépréciés.
Le changelog complet est disponible sur GitHub. Découvrons maintenant ces nouvelles fonctionnalités !
MongoDB est l’une des bases de données NoSQL les plus populaires. La prise en charge native de MongoDB était la fonctionnalité la plus demandée et la plus attendue d’API Platform ! Sam Van der Borght a commencé à se pencher sur ce sujet en mars 2016. En juillet 2017, la Pull Request a été transférée sur la V2 du framework par Pablo Godinez, avec l'aide de Hamza Amrouche (membre de la core team d'API Platform), Alexandre Delplace et bien d’autres. Depuis août 2018, Alan Poulain (membre de la core-team et auteur du sous-système GraphQL) a déployé des efforts considérables pour finir ce patch.
Avec 114 commits et 234 fichiers modifiés en presque 3 ans, c'est l'une des plus grandes contributions du projet.
L'intégration de MongoDB repose sur Doctrine MongoDB ODM 2.0 (actuellement en version bêta). Pour activer cette fonctionnalité, il suffit d'installer et de configurer DoctrineMongoDBBundle. API Platform va le détecter automatiquement. Créez ensuite une classe mappée avec MongoDB et marquez-la en tant que ressource API :
<?php
namespace AppDocument;
use ApiPlatformCoreAnnotationApiResource;
use DoctrineODMMongoDBMappingAnnotations as ODM;
/**
* @ApiResource
* @ODMDocument
*/
class Book
{
/**
* @ODMId(strategy="INCREMENT", type="integer")
*/
public $id;
/**
* @ODMField(type="string")
*/
public $title;
}
La prise en charge de MongoDB exploite la flexibilité d’API Platform : elle a été implémentée en tant que fournisseur de données et persisteur de données. Les relations, la pagination ainsi que les filtres booléens, les dates, les nombres, les ordres, et les filtres de recherche sont également pris en charge !
Un grand merci à tous les contributeurs de cette fonctionnalité, ainsi qu’à Andreas Braun, responsable de la maintenance de Doctrine MongoDB ODM, pour ses relectures approfondies !
Elasticsearch est un outil Open Source permettant d'effectuer des recherches et des analyses avancées sur un très grand nombre de données. La société Orange a sponsorisé le développement du support d’Elasticsearch pour API Platform, ainsi que d’intéressants filtres de recherche. Cette implémentation a été réalisée par Baptiste Meyer (core-team API Platform). Grâce à Orange, cette fonctionnalité est désormais disponible dans la version 2.4 d’API Platform !
Pour activer et configurer le support d’Elasticsearch, reportez-vous à la documentation officielle. Ensuite, une simple classe de ressources correspondant à un index Elasticsearch suffit pour bénéficier de toute la puissance d'API Platform :
<?php
namespace AppModel;
use ApiPlatformCoreAnnotationApiProperty;
use ApiPlatformCoreAnnotationApiFilter;
use ApiPlatformCoreAnnotationApiResource;
use ApiPlatformCoreBridgeElasticsearchDataProviderFilterMatchFilter;
/**
* @ApiResource
*/
class Tweet
{
/**
* @ApiProperty(identifier=true)
*
* @var string
*/
public $id;
/**
* @var User
*/
public $author;
/**
* @var DateTimeInterface
*/
public $date;
/**
* @ApiFilter(MatchFilter::class)
*
* @var string
*/
public $message;
}
Ensuite, vous pouvez utiliser une URL telle que / tweets? Message = foo pour effectuer une recherche à l'aide de Elasticsearch.
Gardez en tête que c’est votre responsabilité d’alimenter votre index Elastic. Pour ce faire, vous pouvez utiliser Logstash, un persisteur de données personnalisé, ou tout autre mécanisme adapté à votre projet (tel qu'un ETL). Baptiste a également profité de cette occasion pour améliorer le code gérant la pagination. Il s'agit désormais d'une classe générique utilisée par tous les fournisseurs de données natifs (Doctrine ORM, MongoDB et Elasticsearch), que vous pouvez réutiliser par vous-même.
Mercure est un tout nouveau protocole basé sur HTTP / 2 et les Server-Sent Events (SSE). C’est une alternative moderne à WebSocket (WebSocket n’étant pas compatible avec HTTP / 2). Mercure est particulièrement utile pour publier en temps réel les mises à jour des ressources servies via des API Web. Il est supporté nativement par les navigateurs modernes (aucune bibliothèque requise ni SDK) et est très utile pour mettre à jour des applications Web et mobiles réactives.
Dans la version 2.4, nous avons ajouté la prise en charge de Mercure au composant serveur d'API Platform et aux générateurs d'applications React et React Native. La configuration de Docker Compose fournie avec API Platform a également été mise à jour pour fournir un hub Mercure. La configuration pour l'envoi automatique des mises à jour aux clients actuellement connectés est très simple :
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
/**
* @ApiResource(mercure=true)
*/
class Book
{
// ...
}
Grâce aux fonctionnalités de découverte automatique de Mercure, les clients générés s'abonnent automatiquement aux mises à jour :
Messenger est un nouveau composant Symfony créé par Samuel Roze (core team Symfony et API Platform). Il permet de distribuer des messages à l'aide de queues de messages (RabbitMQ, Kafka, Amazon SQS, Google PubSub…) et de les traiter de manière asynchrone. Il fournit un bus de messages permettant de mettre en œuvre le modèle de conception CQRS. Dans API Platform 2.4, nous avons ajouté un moyen pratique de tirer parti des fonctionnalités de Messenger. Cette nouvelle fonctionnalité est particulièrement utile pour créer des endpoints orientés service (de type RPC) :
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ApiResource(
* messenger=true,
* collectionOperations={
* "post"={"status"=202}
* },
* itemOperations={},
* outputClass=false
* )
*/
class ResetPasswordRequest
{
/**
* @var string
*
* @AssertNotBlank
*/
public $username;
}
Grâce au nouvel attribut Messenger, cet objet sera automatiquement envoyé au bus. Il peut ensuite être traité (de manière synchrone ou asynchrone) par un gestionnaire de messages :
<?php
namespace AppHandler;
use AppEntityResetPasswordRequest;
use SymfonyComponentMessengerHandlerMessageHandlerInterface;
class ResetPasswordRequestHandler implements MessageHandlerInterface
{
public function __invoke(ResetPasswordRequest $forgotPassword)
{
// do something with the resource
}
}
Et c’est tout ! Voilà ce qu’il vous faut pour utiliser le composant Messenger avec API Platform.
HTTP/2 permet à un serveur d’envoyer de manière préventive (ou «push») des réponses (ainsi que les demandes «promises» correspondantes) à un client en association avec une requête précédente envoyée par le client. Cela peut être utile lorsque le serveur sait que le client doit disposer de ces réponses pour traiter pleinement la réponse à la requête initiale (RFC 7540).
Cette fonctionnalité est particulièrement utile pour les performances des API REST : elle permet au serveur d’envoyer (push) instantanément les relations de la ressource actuelle dont le client aura besoin, avant même que le client sache qu'il devra émettre une requête HTTP supplémentaire.
API Platform 2.4 facilite grandement l'établissement de relations utilisant HTTP/2 :
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiProperty;
use ApiPlatformCoreAnnotationApiResource;
/**
* @ApiResource
*/
class Book
{
/**
* @ApiProperty(push=true)
*
* @var Author
*/
public $author;
}
Grâce à l'attribut push, si le client demande / books / 1, le serveur web enverra directement à la fois la ressource du livre demandée et l'auteur associé (par exemple, / authors / 12) au client. Pour de meilleures performances, cette fonctionnalité doit être utilisée avec le système d'invalidation de cache HTTP intégré (basé sur Varnish).
Jean-François Thuillier et Arnaud Oisel ont patché API Platform Admin et la bibliothèque JavaScript API Doc Parser sous-jacente pour détecter et utiliser automatiquement les filtres exposés par les spécifications de l'API (Hydra ou OpenAPI). Regardez par vous-même :
Le seul code dont vous avez besoin pour obtenir une telle interface est le suivant :
import React from 'react';
import {HydraAdmin} from '@api-platform/admin';
export default () => <HydraAdmin entrypoint="https://api.example.com"/>;
L'interface utilisateur est construite côté client de manière dynamique en analysant les spécifications de l'API.
Jean-François a également ajouté quelques helpers pour aider à la personnalisation de l’admin, et Laury Sorriaux a corrigé une limitation de longue date : il est désormais possible d’utiliser l’admin même avec une API non desservie à la racine du domaine (telle que / api).
API Platform 2.4 prend désormais en charge la nouvelle version du format de spécification OpenAPI (anciennement Swagger) (v3). Notre framework utilise également les nouvelles fonctionnalités introduites par cette version, telles que les liens.
Pour récupérer la spécification d’une version donnée d’OpenAPI de l'API, utilisez l'URL suivante : /docs.json?spec_version=3.
Vous pouvez également extraire la spécification au format JSON ou au format YAML :
- bin / console api: openapi: export --spec-version = 3 # JSON
- bin / console api: openapi: export --spec-version = 3 --yaml # YAML
Parallèlement à Swagger UI, nous avons implémenté la prise en charge de ReDoc, un générateur de docs d’API, écrit en React :
Anthony Grassiot (membre de la core-team API Platform) a apporté une aide considérable au support d’OpenAPI v3. L'intégration de ReDoc a été réalisée par Grégoire Hébert. Un grand merci à eux !
La gestion des objets de transfert de données était connue pour être difficile avec API Platform. En octobre dernier, une partie de l’équipe d’API Platform et de Sylius ont collaboré pour améliorer l'API de ce framework e-commerce basé sur Symfony, avec l’aide d’API Platform (on vous en dira bientôt plus à ce sujet !). Au cours de cet atelier, Antoine Bluchet et Kévin Dunglas ont travaillé sur une nouvelle façon de gérer les DTO avec API Platform :
<?php
namespace AppEntity;
use ApiPlatformCoreAnnotationApiResource;
use AppDtoBookInput;
use AppDtoBookOutput;
/**
* @ApiResource(
* inputClass=BookInput::class,
* outputClass=BookOutput::class
* )
*/
final class Book
{
// ...
}
Les nouveaux attributs input_class et output_class permettent d’utiliser des classes spécifiques respectivement pour la représentation en écriture et en lecture de la ressource.
Comme illustré dans l'exemple utilisant Symfony Messenger, il est également possible de définir ces nouveaux attributs sur false pour indiquer que l'opération ne prendra aucune entrée ni aucune sortie. Ces nouveaux attributs sont automatiquement pris en compte par tous les sous-systèmes d’API Platform, incluant GraphQL, Hydra et OpenAPI.
Un moyen simple de configurer le cache HTTP par ressource a été ajouté par Daniel West :
<?php
use ApiPlatformCoreAnnotationApiResource;
/**
* @ApiResource(cacheHeaders={"max_age"=60, "shared_max_age"=120})
*/
class Book
{
// ...
}
Avec cette configuration, API Platform générera automatiquement l'en-tête HTTP Cache-Control suivant : Cache-Control: max-age = 60, public, s-maxage = 120. Un grand merci à Daniel !
Le header de réponse HTTP Sunset indique qu'une URI peut très certainement ne plus répondre à un moment spécifique dans le futur (draft-wilde-sunset-header Internet Draft).
Cet en-tête fonctionne bien avec le mécanisme de dépréciation disponible depuis API Platform 2.3. Grâce au travail de Thomas Blank, il est maintenant facile de définir cet en-tête à l’aide de API Platform :
<?php
namespace AppEntity;
/**
* @ApiResource(itemOperations={
* "get"={
* "deprecation_reason"="Retrieve a Book instead",
* "sunset"="01/01/2020"
* }
* })
*/
class Parchment
{
// ...
}
API Platform 2.4 est livré avec une version améliorée des générateurs de clients React et Vue.js :
- Les relations sont maintenant toujours traitées correctement
- Les champs HTML de type nombre ainsi que les listes (arrays) sont convertis avec le type JSON approprié lors de leur envoi à l'API
- Les API non serveur à la racine du domaine (comme / api) sont maintenant supportées (grâce à Fabien Kovacic)
API Platform 2.4 est disponible sur GitHub. Aidez-nous à améliorer continuellement ce projet en y contribuant. Vous pouvez également lui donner une étoile sur Github ou suivre Webby sur Twitter !