cURL : Dialogue avec une API en PHP

cURL : Dialogue avec une API en PHP

Posté le 05/11/2023 | 0 commentaire dans PHP Développement | Retour à la liste

Table des matières

    1. Euh, Jamie, c’est quoi une API ?
      1. API
      2. Comment ça marche ?
      3. REST, SOAP, RESTful, …
    2. cURL
      1. Initialiser cURL
      2. Mise en place des paramètres
        1. Par l’array
        2. A l’ancienne
        3. Quelques options intéressantes
      3. Exécution de la session
      4. Fermer la ressource
    3. Récupérer le contenu d’une page web
      1. L’utilité du User-Agent
    4. Transmission avec une API
      1. Requête GET
        1. Des paramètres ?
      2. Requête POST
    5. Pour aller plus loin

Il y a quelques années, j’ai été confronté à l’API de Mastodon. J'avais d'ailleurs créé une librairie TootoPHP pour récupérer des pouets et en poster depuis PHP, peut-être que je l'utiliserai un jour ^^). Et me suis rendu compte que j’utilisais en fait 2 méthodes pour dialoguer avec une API en PHP. J’étais initialement parti pour vous présenter les 2, mais je ne détaillerai que la plus efficace : cURL.
La seconde, plus aisée et rapide fera l’objet d’un second article à venir.

Euh, Jamie, c’est quoi une API ?

Vous avez raison, avant tout cela, posons les bases.

API

Je suis sûr que vous avez déjà entendu parler d’API, même sans savoir ce que c’est. API signifie Application Programming Interface, ou Interface de Programmation Applicative. Ouais, moi non plus ça m’aide pas beaucoup. Ce qui est important là dedans, c’est le mot Interface.

En programmation comme dans la vie quotidienne, une interface désigne un moyen accessible (dans le sens facile) d’interagir avec un programme, une classe, une chaîne HiFi ou votre lave-vaisselle.
Pour imager, prenons l’exemple classique d’une télévision et sa télécommande. Cette dernière est l’interface entre vous et la TV.

Pour changer une chaîne, il suffit d’appuyer sur le bouton du canal désiré, et la télécommande va envoyer un signal au récepteur de la TV afin qu’elle change de fréquence. Personnellement, j’ai encore en mémoire la vieille TV de mes grands-parents où il fallait changer la fréquence avec un potar en façade. Ça change la vie
Et donc, comme dans chaque interface, une API impose une procédure qu’il faut respecter si l’on souhaite que ça fonctionne. Vous n’imaginez pas allumer votre voiture en appuyant sur le bouton des phares ? Ici c’est pareil.

Comment ça marche ?

Je l’attendais celle-là. Et bien, ça marche plutôt bien.

Plus sérieusement, voilà comment ça fonctionne en très gros :
Un site web propose d’héberger des photos. Il est alors possible de s’inscrire sur ce site, et d’y envoyer des photos. Le site vous donne en retour une URL que vous pouvez donner à vos amis pour montrer vos prouesses.
Et bien généralement, ces services web proposent une API pour utiliser leurs services sans passer par leur site. C’est le cas de Twitter (récupérer des tweets), PayPal pour les solutions de paiement, Facebook, … où l’on peut récupérer des informations où en poster via PHP, ou une console, …

Pour notre exemple d’hébergement de photos, on peut imaginer qu’on effectuera une première requête vers l’API pour s’authentifier sur le site, puis une seconde en envoyant la photo, et le serveur nous renverra alors l’URL de l’image en ligne si la transaction a été effectuée.

REST, SOAP, RESTful, …

Je ne détaillerai pas ici les différents types d’API, mais sachez, même si l’on entend parler que de lui, qu’il n’existe pas que REST.
SOAP est à ma connaissance le plus vieux (90), mais aussi moins utilisé, et repose sur des échanges basés sur du XML. Certains prétendent qu’il connaîtra un essor dans quelques années, à voir.

Enfin RESTful désigne simplement une application REST, plus récent (2000) mais également voulu moins lourd et plus simple. Dans la suite de ce billet, je ne parlerai que de ce type d’API.

cURL

La bibliothèque cURL de PHP est certainement la plus efficace et la plus utilisée des méthodes pour se connecter à une API. Il est possible de faire des tas de choses avec, comme l’utilisation de web services, de proxy, de faire du téléchargement, un crawler, gérer un FTP, …
Si cURL est bien connu des utilisateurs de Linux, c’est un outil multi-plateforme rapide, pas très compliqué à utiliser et qui gère l’authentification sécurisée.

Pour pouvoir l’utiliser avec PHP, il suffit d’activer la bibliothèque libcurl. Un petit

phpinfo();

pour vérifier si elle est bien activée et c’est parti.

Initialiser cURL

Pour créer une nouvelle ressource cURL, la syntaxe est simple:

$curl = curl_init();

A cela, on peut ajouter un argument : L’URL de destination. Ou l’on peut l’ajouter plus tard, c’est la méthode que je préfère.

Mise en place des paramètres

Il existe 2 façons pour ajouter des options à une ressource cURL :

Par l’array

J’aime bien le jeu de mots
Il est possible de fournir à notre ressource un tableau préalablement créé afin de lui spécifier des paramètres avec la fonction curl_setopt_array() :

$opts = [
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_URL            => $this->domainURL . $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_CONNECTTIMEOUT => 30
];

curl_setopt_array($curl, $opts);

Le premier argument à fournir est la ressource à paramétrer. La seconde contient notre tableau associatif, avec les options.

A l’ancienne

Quand je dis à l’ancienne, ne pas comprendre que cette fonction est plus vieille que l’autre. C’est juste la forme redondante que prend cette méthode à écrire. Bref, il est possible de passer les arguments un à un avec la fonction curl_setopt() :

curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

Cette fonction attend en argument :

  1. La ressource cURL à paramétrer
  2. Le paramètre
  3. La valeur

Quelques options intéressantes

Je vous livre ici quelques options de cURL, les plus utiles et basiques selon moi :

  • CURLOPT_URL : URL de l’hôte à utiliser pour la connexion.
  • CURLOPT_CONNECTTIMEOUT : Durée maximale que pourra prendre la tentative de connexion à l’hôte, en secondes.
  • CURLOPT_TIMEOUT : Durée maximale d’exécution de la requête, en secondes
  • CURLOPT_HEADER : Permet d’inclure l’entête dans la valeur de retour.
  • CURLOPT_RETURNTRANSFER : Retourne le transfert sous une chaîne au lieu de l’afficher.
  • CURLOPT_HTTPHEADER : Permet d’envoyer des entêtes HTTP avec la transaction. Nous verrons ça plus bas.
  • CURLOPT_SSL_VERIFYPEER : Si cette option est à true (par défaut), alors cURL vérifiera l’authenticité du certificat. Si vous n’utilisez pas de connexion SSL ou TLS, passez la à false.
  • CURLOPT_POST : Indique que la requête est de type POST. Si cette ligne n’est pas présente, cURL enverra par défaut une requête GET.
  • CURLOPT_POSTFIELDS : Dans une requête POST, tableau associatif avec les données à envoyer à l’hôte.
  • CURLOPT_FOLLOWLOCATION : Si cURL doit suivre les redirections éventuelles.
  • CURLOPT_USERAGENT : Spécifier un User-agent dans l’entête d’une requête HTTP. Liste de quelques user-agent sur Wikipédia.

Exécution de la session

Pour exécuter la requête, rien de plus simple. Il suffit d’utiliser la fonction curl_exec()

$response = curl_exec($curl);

Vous l’aurez compris, l’argument à passer à cette fonction est notre ressource cURL. Cette fonction retourne simplement la réponse de l’hôte distant.

Fermer la ressource

Pour libérer de la mémoire, il est vivement conseillé, une fois la transmission terminée, de fermer la ressource :

curl_close($curl);

Testons cela alors.

Récupérer le contenu d’une page web

Ici, nous allons tenter de récupérer le contenu d’une page web. Vous allez voir que le code est très simple :

<?php

$curl = curl_init();

$opts = [
    CURLOPT_URL => 'www.google.fr',
    CURLOPT_RETURNTRANSFER => true,
];

curl_setopt_array($curl, $opts);

$response = curl_exec($curl);
curl_close($curl);

Ici on définit peu de paramètres :

  • L’URL de la page à récupérer
  • Le souhait de retourner la réponse et non de l’afficher.

La variable $response contient en sortie la réponse de la requête. Ici, c’est une chaîne de caractères comprenant le code HTML de la page de google.
Vous pouvez donc exploiter comme n’importe quelle string ce résultat.

Petit rappel : Pour parser un document HTML, vous pouvez vous aider de la classe DOMDocument ou de l’extension SimpleXML.
Sinon, il suffit d’un echo pour l’afficher sur la page.

L’utilité du User-Agent

Brève petite astuce : Je vous ai mis l’option CURLOPT_USERAGENT dans la liste des paramètres tout à l’heure. Celle-ci peut nous permettre par exemple de simuler une connexion à Google comme si nous nous connections avec un smartphone.

Dans le code précèdent, ajoutons simplement un user-agent de navigateur mobile dans les paramètres de la transmission :

<?php

$curl = curl_init();

$opts = [
    CURLOPT_URL => 'www.google.fr',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'Mozilla/5.0 (Android 13; Mobile; rv:109.0) Gecko/114.0 Firefox/114.0'
];

curl_setopt_array($curl, $opts);

$response = curl_exec($curl);
curl_close($curl);

echo $response;

On voit ainsi que Google a pris en compte notre requête, et a adressé la réponse en fonction du user-agent spécifié :

Google nous envoie une version pourrie

Transmission avec une API

Maintenant que nous avons vu sommairement l’utilisation de cURL, nous allons nous attaquer à ce qui nous intéresse : Dialoguer avec une API.

Requête GET

Selon l’API, comme avec le protocole HTTP que vous connaissez, il faut parfois effectuer une transaction GET ou POST.
GET est généralement utilisée lorsque votre application ne doit que récupérer des données de l’hôte, mais il est possible d’y passer des arguments.

Pour tester cela, nous allons nous servir de l’API Random User Generator, que j’ai découvert il y a peu, grâce au blog de ShevAbam. Il s’agit uniquement de pouvoir récupérer des informations d’utilisateurs aléatoires (factices), utiles pour vos éventuels tests.

La documentation, portée sur jQuery, permet tout de même d’en comprendre le fonctionnement.

On y apprend que l’URL d’entrée pour cette API, celle qui représente la ressource à récupérer, appelée endpoint, est https://randomuser.me/api/ , et que la ressource récupérée est un objet JSON.

Passons au code :

<?php

$curl = curl_init();

$opts = [
    CURLOPT_URL => 'https://randomuser.me/api/'
    CURLOPT_RETURNTRANSFER => true,
];

curl_setopt_array($curl, $opts);

$response = json_decode(curl_exec($curl), true);

print_r($response);

Si vous avez bien suivi, il ne devrait rien y avoir de compliqué.
J’ai renseigné le endpoint dans le paramètre CURLOPT_URL, et décode ensuite l’objet JSON que l’API me renvoie.

Voilà le résultat produit :

Array
(
    [results] => Array
        (
            [0] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => leon
                            [last] => hübner
                        )

                    [location] => Array
                        (
                            [street] => 9377 parkstraße
                            [city] => bayreuth
                            [state] => hamburg
                            [postcode] => 29972
                        )

                    [email] => leon.hübner@example.com
                    [login] => Array
                        (
                            [username] => heavyladybug706
                            [password] => dogwood
                            [salt] => iSK8r2hd
                            [md5] => ce2261b02d713de1b6f25710f40a38e0
                            [sha1] => e640a316dca46761476458eb17fbf8f8018949f7
                            [sha256] => 9c919250c04e2c3b925434c56a0aae210cd96b70e6b5a65cc1ddf764067f8260
                        )

                    [dob] => 1982-10-19 09:48:01
                    [registered] => 2004-04-06 02:49:59
                    [phone] => 0658-4413331
                    [cell] => 0174-7427152
                    [id] => Array
                        (
                            [name] => 
                            [value] => 
                        )

                    [picture] => Array
                        (
                            [large] => 
                            [medium] => 
                            [thumbnail] => 
                        )

                    [nat] => DE
                )

        )

    [info] => Array
        (
            [seed] => 04b9f8b8ed62a4a6
            [results] => 1
            [page] => 1
            [version] => 1.1
        )

)

Des paramètres ?

Je vous ai dit tout à l’heure qu’il était possible de spécifier des paramètres dans la requête. Voyons ça.

Comme dans n’importe quelle requête HTTP GET, les paramètres se mettent dans l’URL, tout simplement :

CURLOPT_URL => 'https://randomuser.me/api/?results=2&gender=male&inc=gender,name,nat',

J’ai fourni plusieurs paramètres, récupérés dans la doc. Le résultat :

Array
(
    [results] => Array
        (
            [0] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => adam
                            [last] => addy
                        )

                    [nat] => CA
                )

            [1] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => benjamin
                            [last] => martin
                        )

                    [nat] => NZ
                )
        )

    [info] => Array
        (
            [seed] => 52b8ab0ce31a8031
            [results] => 2
            [page] => 1
            [version] => 1.1
        )
)

Requête POST

Ce type de requête n’est pas plus compliquée. Il suffira généralement de quelques paramètres en plus dans notre ressource cURL.

Pour cet exemple, je me servirais de JSONPlaceholder. Pour ceux qui ne connaissent pas, c’est une fausse API en ligne qui existe uniquement à but de tests et prototypes. C’est parfait pour nous !

Encore une fois, la documentation est écrite pour Javascript, mais l’usage est simple. Vous pouvez si vous le souhaitez vous amuser avec les requêtes GET, mais ce qui nous intéresse ici est la création d’un nouveau post.

Pour faire cela, il va falloir envoyer une requête HTTP POST, avec 3 paramètres :

  • title : Le titre du post
  • body : Le corps du billet
  • userId : ID (entier) de l’auteur

Je vous donne le code :

<?php
 
$curl = curl_init();
 
$params = [
    'title' => 'Welcome Bro !',
    'body' => 'Lorem Ipsum etc etc',
    'userId' => 5
];
 
$params_string = http_build_query($params);
 
$opts = [
    CURLOPT_URL => 'http://jsonplaceholder.typicode.com/posts',
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $params_string,
    CURLOPT_RETURNTRANSFER => true,
];
 
curl_setopt_array($curl, $opts);
 
$response = json_decode(curl_exec($curl), true);
 
print_r($response);

J’ai mis en évidence les paramètres à modifier dans la ressource cURL pour exécuter correctement la requête.

Un point cependant, concernant la variable $params_string . C’est en fait la génération des paramètres encodés en URL, grâce à la fonction http_build_query($params).

Encore une fois, on décode la réponse et on observe le résultat :

Array
(
    [title] => Welcome Bro !
    [body] => Lorem Ipsum etc etc
    [userId] => 5
    [id] => 101
)

C’était vraiment compliqué ?

Pour aller plus loin

J’ai testé ici des exemples très scolaires et simples. Lors de l’utilisation d’une API plus complexe, par exemple avec une authentification par OAuth, des procédures et paramètres plus avancées sont requis.

N’hésitez pas d’y aller de vos commentaires si je peux améliorer cet article, merci !

Max Koder
Max Koder

Développeur en mauvaise herbe, électronicien et bricoleur à mes heures de hobby perdues, compteur de grains de riz, tenteur de tiramisu, mais surtout papa.

Principal développeur de 299Ko, j'essaye de maintenir ce CMS qui me tient à coeur.

Commentaires

Il n'y a pas de commentaires

Ajouter un commentaire