💯

API

Interfaces de programmation d'application ou Application Programming Interfaces.

Une API est une application.

Quand on parle d’application, on sous-entend souvent une application monolithique (un seul bloc). Depuis 15 ans, on sĂ©pare les modules pour que back et front puissent fonctionner sĂ©parĂ©ment. Notamment parce qu’on est dans une Ăšre de micro-services.

Une API est une application sans front (ou peu) qui permet de rĂ©pondre Ă  une question. C’est une interface qui rend un service. Elle retourne souvent du JSON.

Un micro-service est une API dans sa forme minimale (par exemple, un pour la base de données, un pour le front, etc
).

On trouve de nombreuses API gratuites :

JSON est utilisĂ© parce qu’on fait de l’asynchrone et on affiche la rĂ©ponse seulement quand elle arrive.

⚙
Outils : API Platform (par Les-Tilleuls) : https://api-platform.com/

Créer une API avec Symfony et API Platform


Projet Github : https://github.com/LSarribouette/mumbling-with-api-platform

Dans un terminal,

Dans PhpStorm,

Sur ‘localhost/api’, on voit maintenant l’entitĂ© avec :

📌
Pour aller plus loin : https://api-platform.com/docs/distribution/ https://api-platform.com/docs/core/operations/

SĂ©curitĂ© : restreindre l’accĂšs aux mĂ©thodes HTTP


Il est possible de restreindre l’accĂšs Ă  certaines mĂ©thodes HTTP comme DELETE, soit aux utilisateurs ayant un certain rĂŽle, soit complĂštement.

Lors de la crĂ©ation de l’entitĂ©, on a choisi de la mettre en ressource de l’API. Un attribut #[ApiResource] a Ă©tĂ© ajoutĂ© Ă  la classe :

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\XMenRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: XMenRepository::class)]
#[ApiResource]
class XMen
{...}

On peut choisir de donner accÚs uniquement à la méthode GET en ajoutant un attribut #[Get] (ou plusieurs #[Get, Post]) en dessous du précédent :

#[ORM\Entity(repositoryClass: XMenRepository::class)]
#[ApiResource]
#[Get]
class XMen
{...}

De nombreux attributs sont disponibles : #[Get], #[GetCollection], #[Post], #[Put], #[Delete], #[Patch]


On peut Ă©galement choisir de donner accĂšs aux mĂ©thodes selon le rĂŽle de l’utilisateur en ajoutant un attribut #[IsGranted].

Interroger une API


Objectif : récupérer la liste des X-Men en JSON et remplir la liste dans la page HTML.

Dans un IDE (ici VSCode),

<!DOCTYPE html>
<html lang="fr">
<head>
    <title>Interroger mon API</title>
</head>
<body>
    <h1>Liste des X-Men</h1>
    <ul id="maListe"></ul>
    <script>
        // a completer
    </script>
</body>
</html>

Pour récupérer la liste des X-Men en JSON, trois options sont possibles :

  1. XML HTTP Request (non)
  1. AJAX avec jQuery (non)
  1. Fetch avec en paramùtre l’URL de l’API que l’on veut joindre (oui)

Dans la balise <script>,

<script>
  fetch('http://127.0.0.1:8000/api/x_mens.json') 
  .then((reponse) => reponse.json())
  .then((json) => console.log(json));
</script>

Lorsqu’on lance le Live Server, la liste est visible dans l’inspecteur, onglet Console.

â„č
S’il y a un problĂšme avec l’API, on peut le voir dans l’inspecteur, onglet RĂ©seau.
â„č
Si erreur de cross-origin, on peut modifier le .env Ă  la derniĂšre ligne CORS_ALLOW_ORIGIN et on lui rajouter une condition *|local.

Pour remplir la liste dans la page HTML, on complĂšte le script JavaScript :

<script>
    fetch('http://127.0.0.1:8000/api/x_mens.json') 
    .then((reponse) => reponse.json())
    .then((json) => {
        let monUl = document.getElementById("maListe");
        for (const uneXMen of json) {
        let monLi = document.createElement('li');
        monLi.innerText = uneXMen.pseudo;
        monUl.appendChild(monLi);
        }
    })
</script>

â„č
Pareil mais avec un Twig ? > AprÚs avoir ajouter les paquets nécessaires (twig et symfony/asset), > créer un contrÎleur MainController avec une méthode index() qui retourne le Twig index.html.twig, > et ajouter le bout de code correspondant dans le {% block body %}.

Format Hydra


https://api-platform.com/docs/core/extending-jsonld-context/

https://www.hydra-cg.com/

Un Hydra est un autre format qui contient tout ce qu’il y avait dans le fichier JSON, avec en plus d’autres informations comme le nombre d’élĂ©ments.

Si ce nombre est supĂ©rieur Ă  20, on a un URL qui permet d’avoir accĂšs aux 20 Ă©lĂ©ments suivants.

â„č
Par dĂ©faut, le format de notre API est Hydra donc on n’a pas besoin d’ajouter l’extension Ă  la fin de l’URL : on avait prĂ©cisĂ© “.json” pour spĂ©cifier le format JSON.

On peut également boucler sur un Hydra en utilisant member.

<script>
  fetch('http://10.22.0.254:8002/api/superheroes') 
  .then((reponse) => reponse.json())
  .then((json) => {
    let monUl = document.getElementById("maListe");
    for (const uneXMen of json["hydra:member"]) {
      let monLi = document.createElement('li');
      monLi.innerText = uneXMen.pseudo;
      monUl.appendChild(monLi);
    }
  })
</script>

Authentification


Il est possible de limiter l’accùs à une API à des utilisateurs ayant certains droits.

Pour cela, on utilise des JSON Web Token (JWT) grĂące au paquet LexikJWTAuthenticationBundle.

â„č
On crée un utilisateur avec make:user (et non pas make:auth).
📌
Pour aller plus loin : https://jwt.io/ https://api-platform.com/docs/core/jwt/#jwt-authentication