Retour sur la conférence de Nicolas Grekas : "Consuming HTTP APIs in PHP the Right way! "

Ahmed Eben Hassine
Ahmed Eben hassine
4 novembre 2024

Dans cet article, nous plongeons dans la présentation de Nicolas Grekas, figure emblématique de la communauté Symfony. Sa conférence aborde une problématique fondamentale : bien que la communication serveur à serveur via HTTP paraisse simple en théorie, elle engendre souvent des défis inattendus en pratique. Cela renforce l'importance d'une intégration efficace des produits clients ou des SDK dans d'autres solutions finales, tout en nécessitant une capacité d'adaptation aux changements sans compromettre l'ensemble.

Nicolas nous guide à travers les complexités de l'écosystème des PSR en PHP, en partant de la compréhension fondamentale du composant Http Client jusqu'à la cartographie des requêtes dans notre domaine d'activité. Un accent particulier est mis sur l'importance d'offrir une expérience développeur de premier ordre lors de la création d'un SDK.

La présentation met en lumière l'utilisation efficace d'outils essentiels tels que php-http/discovery et symfony/http-client, tout en explorant les abstractions mises en œuvre par le composant HTTP Client. Nous avons soigneusement noté les éléments clés de cette présentation, que nous développerons dans cet article en fonction de notre perspective.

 

Consuming HTTP APIs in PHP the Right way!

Présenté par Nicolas Grekas

Nicolas Grekas

 

 

Symfony HttpClient : Un composant puissant et interopérable 

Le composant Symfony HttpClient se distingue par sa conception "standalone", conçu pour simplifier la gestion des requêtes HTTP dans les applications Symfony. Il s'intègre naturellement au framework et propose une interface stateless intuitive. Ce client HTTP est performant, supportant HTTP2 grace au curl gère les requêtes asynchrones avec streaming, offre un mécanisme de cache et capture les exceptions, permet de garder une connexion TCP ouverte entre les requêtes, permettant une expérience fluide et sans contraintes.

Exemple d'utilisation pratique

Voici un exemple de code utilisant Symfony HttpClient pour envoyer une requête GET vers l’API de GitHub. Ce composant gère la réponse de façon asynchrone, garantissant des performances optimales :

use Symfony\Contracts\HttpClient\HttpClientInterface;
class SymfonyDocs { 

    public function __construct( private HttpClientInterface $client, ) {}    

    public function fetchGitHubInformation(): array
    {
        // or through a factory method: HttpClient::create()->request(...)
        $response = $this->client->request(
            'GET',
            'https://api.github.com/repos/symfony/symfony-docs'
        );
        
        return $response->toArray();
    }
}

 

Interopérabilité et abstractions

L'une des forces majeures de Symfony HttpClient réside dans sa compatibilité étendue avec plusieurs standards d'abstraction en PHP. Cette interopérabilité maximale se manifeste à travers la prise en charge des spécifications Symfony Client Contracts, PSR-18, HTTPlug (v1/v2), et les flux PHP natifs, assurant ainsi une compatibilité transparente avec divers abstractions et facilitant l'intégration harmonieuse avec d'autres bibliothèques.

  • Symfony Http Client Contracts :  Ces interfaces constituent la pierre angulaire du composant Symfony HttpClient, avec HttpClientInterface comme point d'entrée essentiel. Particulièrement utilisé par d'autres composants (notamment le Mailer), Symfony Contracts joue un rôle crucial en permettant une interopérabilité fluide entre les composants symfony, et ce, sans nécessiter de lien direct avec une implémentation particulière.
  • PSR-18 : Cette spécification apporte une innovation majeure en introduisant une interface unique, sendRequest(RequestInterface $request), pour les clients HTTP. Son objectif est clair : rendre les bibliothèques plus réutilisables en les affranchissant de toute dépendance à une implémentation HTTP spécifique. Grâce à cette approche, les développeurs bénéficient d'une flexibilité remarquable, pouvant ainsi changer de client HTTP sans avoir à modifier la moindre ligne de leur logique métier.
  • HTTPlug: HTTPlug représente l'une des premières tentatives réussies de standardisation des clients HTTP en PHP.Cette abstraction permet de détacher efficacement le code des implémentations HTTP spécifiques, offrant ainsi une flexibilité précieuse : les développeurs peuvent, par exemple, basculer de CURL à Guzzle sans que cela n'affecte le reste de l'application. Sa présence historique et son adoption large dans l'écosystème PHP en font un standard de fait.
  • php-http/discovery : Se distinguant des autres composants, discovery n'est pas une implémentation directe d'un client HTTP, mais plutôt une bibliothèque  qui fournit la découverte automatique et l'installation automatique des implémentations bien connues de PSR-7, PSR-17, PSR-18 et HTTPlug éliminant ainsi la nécessité d'une configuration manuelle fastidieuse. Les clients Symfony HttplugClient et Psr18Client tirent pleinement parti de cette fonctionnalité en s'appuyant sur cette découverte pour sélectionner automatiquement les implémentations compatibles parmi ceux déjà présents dans les vendor, en utilisant en arrière-plan Psr17Factory, une fabrique apporté par Nicolas conforme à PSR-17, permettant de réaliser l'auto-identification des clients garce à l'outil Httplug.

Détails du fichier composer.json

Dans le fichier composer.json du package Symfony HttpClient, se trouve la section "provide" des packages virtuels, expliquant certains points importants :

  • psr/http-client-implementation : Le composant Symfony HttpClient est bien une implémentation d'un client HTTP et sera sélectionné automatiquement par le mécanisme de discovery.
  • php-http/async-client-implementation : celle là signifie que notre composant offre également une implémentation d'un client HTTP asynchrone.

 

Nicolas a évoqué le principe de Coding Against Abstractions dans ses explications, soulignant comment php-http/discovery favorise une architecture moderne, flexible et découplée, en accord avec les principes SOLID et les pratiques de développement modernes. Grâce aux packages virtuels mentionnés ci-dessus, php-http/discovery peut sélectionner automatiquement l’implémentation du client et de l'abstraction appropriée au projet, renforçant ainsi l'interopérabilité et permettant une intégration fluide sans configuration manuelle, tout en facilitant la coexistence avec d'autres bibliothèques PHP.

Pour en savoir plus sur l'utilisation de Discovery, vous pouvez consulter la documentation officielle ici.

Avantages d'HTTPClient

HttpClient présente plusieurs avantages significatifs :

  • Simplicité : HTTPClient est plus simple à utiliser, surtout pour des cas d’usage basiques.
  • charge à la fois les wrappers de flux PHP, cURL et un wrapper asynchrone via le client ampphp.
  • Performances : Les requêtes sont envoyées en mode asynchrone par défaut, ce qui permet de gagner en performance, particulièrement lorsque plusieurs requêtes sont exécutées en parallèle (ex. dans des boucles).
  • Configuration isolée : La configuration d'HTTPClient est externalisée dans des fichiers de configuration du framework (comme framework.yaml ), rendant le code plus propre et facile à maintenir.
# config/packages/framework.yaml
framework:
    http_client:
        scoped_clients:
            vemo.client:
                base_uri: 'https://api.vemo.com'
                headers:
                    Accept: 'application/json'
                    Authorization: 'Bearer %env(VEMO_API_TOKEN)%'

 

Fonctionnalités supplémentaires

De plus le HttpClient propose quelques fonctionnalités supplémentaires :

  • Augmentation des connexions ouvertes : Nous pouvons configurer CurlHttpClient pour limiter le nombre maximum de connexions ouvertes à 4, ce qui permet de gérer efficacement les ressources et d'éviter la surcharge du serveur.
$client = HttpClient::create(['max_host_connections' => 4]);
  • Intégration avec Mercure : HTTPClient facilite l’interaction avec le protocole Mercure, souvent utilisé pour les notifications en temps réel.
  • Streaming : Il sera possible d'appeler la méthode stream() pour obtenir des chunks de la réponse de manière séquentielle, sans avoir à attendre la réception complète de celle-ci.
  • Consume Server-sent events :  Les Server-Sent Events (SSE) sont une norme Internet permettant d'envoyer des données en temps réel des serveurs vers les pages web. Grâce au client EventSourceHttpClient, il devient simple de transmettre ces flux unidirectionnels (du serveur au client), contrairement aux WebSockets qui fonctionnent dans les deux sens. Pour plus de détails je vous invite à consulter cet article https://symfony.com/blog/new-in-symfony-5-2-eventsource-http-client
  • Async : Il est possible d'utiliser les Promise (même concept en JS) avec le client HttplugClient en installant le package guzzlehttp/promises. Cela constitue une option supplémentaire si votre infrastructure utilise déjà Httplug.

Tests avec Symfony HttpClient : utilisation de MockHttpClient

Symfony HttpClient facilite les tests grâce à la classe MockHttpClient, qui simule des requêtes HTTP. Elle utilise MockResponse pour représenter des réponses simulées, et JsonMockResponse pour des réponses JSON. Les réponses peuvent être définies statiquement ou générées dynamiquement via des callbacks. Par exemple, on peut initialiser MockHttpClient avec une liste de réponses ou utiliser MockResponse::fromFile() pour charger des données de test à partir de fichiers. Ces outils permettent de garantir le bon fonctionnement de votre logique métier sans dépendre d'API externes.

use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Component\HttpClient\HttpClient;

$mockResponses = [
    new MockResponse('{"key": "value"}', ['http_code' => 200]),
    new MockResponse('{"error": "Not found"}', ['http_code' => 404]),
];

$client = HttpClient::create(['mock_response' => $mockResponses]);
$response = $client->request('GET', 'https://api.example.com/data');

Lors de la conférence API Platform, on a présenté une autre solution pour tester les API externes : PHP-VCR. Pour en savoir plus, c'est par ici : Comment tester une API externe en ayant 0 mocks ?

Gestion de la limitation de débit avec ThrottlingHttpClient

Le composant Symfony HttpClient inclut un décorateur ThrottlingHttpClient qui permet de limiter le nombre de requêtes dans une période donnée, respectant ainsi les politiques de limitation de débit. Cela permet de gérer efficacement le flux des requêtes tout en évitant de surcharger les services externes.

use Symfony\Component\HttpClient\ThrottlingHttpClient;

$client = new ThrottlingHttpClient(HttpClient::create(), 2); // Limite à 2 requêtes par seconde
$response = $client->request('GET', 'https://api.example.com/data');

Utilisation des Attributs PHP d'Autowiring

À partir de Symfony 6.1, il est désormais possible de configurer la logique d'autowiring à l'aide de l'attribut #[Autowire], offrant ainsi une approche plus flexible pour l'injection de dépendances.

use Symfony\Component\DependencyInjection\Attribute\Autowire;

class MyService
{
    public function __construct(
        #[Autowire('@service_id')] private $myService
    ) {
        // $myService sera automatiquement mappé au service service_id
    }
}

Dans la version de Symfony 7.1, #[AutowireInline], a été introduit pour permettre de définir l'ensemble de la configuration d'un service, y compris ses arguments, simplement en utilisant les paramètres du constructeur.

class SomeClass1
{
    public function __construct(
        #[AutowireInline(class: SomeSourceAwareLogger::class, args: [new Reference(LoggerInterface::class), 'bar'])]
        public SomeSourceAwareLogger $someSourceAwareLogger,
    ) {
    }
}

Enfin, si vous souhaitez explorer un peu plus l'histoire des attributs, n'hésitez pas à jeter un œil au retour de Clément Talleau sur sa conférence intitulée "API Platform, des développeurs d'attributs"

 

Conclusion

En résumé, HTTPClient est un véritable atout dans notre boîte à outils de développeurs. Il nous permet de créer du code facilement interchangeable tout en offrant une meilleure flexibilité. Grâce aux conseils de Nicolas, qui nous encourage à éviter les implémentations spécifiques et à tirer parti de la discovery, notre expérience de développement s'en trouve améliorée. Avec ses fonctionnalités avancées et sa simplicité d'utilisation, HTTPClient s'impose comme le choix idéal pour nos projets, surtout dans le monde dynamique du développement web moderne, où la performance et la gestion des ressources sont essentielles.

 

À la recherche d'une nouvelle opportunité ? Voir toutes les offres
Découvrez quelques uns de nos projets Symfony Voir les projets

A lire aussi

Voir tous les articles