TW3 — Technologies du Web 3

Bonnes pratiques d'API

Versionner une API, uniformiser les erreurs, comprendre HATEOAS, configurer CORS et documenter avec OpenAPI.

Une API n'est pas seulement un ensemble de routes qui fonctionnent : c'est un contrat public que d'autres équipes vont consommer pendant des années. Ces pratiques évitent de casser leurs clients à chaque évolution.

🏷️ Versionner l'API

Dès qu'une modification casse la compatibilité (champ supprimé, format changé), il faut une nouvelle version.

GET /v1/articles      # version dans l'URL, la plus lisible
GET /articles         # + en-tête Accept: application/vnd.api.v2+json

Le versioning par URL (/v1/) est le plus simple à enseigner, à tester et à mettre en cache. Réservez le versioning par en-tête aux API très évolutives.

Ce qui ne casse pas la compatibilité : ajouter un champ optionnel, ajouter une route. Ce qui la casse : renommer un champ, changer un type, rendre un paramètre obligatoire.

⚠️ Un format d'erreur uniforme

Tous les échecs doivent renvoyer la même structure, quelle que soit la route.

{
  "erreur": {
    "code": "VALIDATION_ECHOUEE",
    "message": "Le champ « email » est invalide.",
    "details": [{ "champ": "email", "raison": "format" }]
  }
}
// Middleware d'erreur Express (4 arguments)
app.use((err, req, res, next) => {
  const status = err.status ?? 500
  res.status(status).json({
    erreur: {
      code: err.code ?? "ERREUR_INTERNE",
      message: status === 500 ? "Erreur interne." : err.message,
    },
  })
})

N'exposez jamais une trace d'exception ou une requête SQL dans la réponse : c'est une fuite d'information exploitable. Journalisez le détail côté serveur, renvoyez un message générique côté client.

🧭 HATEOAS en bref

HATEOAS consiste à joindre à chaque réponse les liens vers les actions possibles, pour que le client navigue sans coder les URLs en dur.

{
  "id": 42,
  "titre": "REST expliqué",
  "_links": {
    "self": { "href": "/v1/articles/42" },
    "commentaires": { "href": "/v1/articles/42/commentaires" }
  }
}

C'est le niveau le plus abouti du modèle de maturité de Richardson. Peu d'API l'appliquent intégralement, mais le principe reste utile pour la pagination (liens next et prev).

🌍 CORS

Un navigateur bloque par défaut les requêtes vers une autre origine. Le serveur doit explicitement autoriser les origines légitimes.

npm install cors
const cors = require("cors")

app.use(cors({
  origin: ["https://mon-front.fr"],
  methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
  credentials: true,
}))

origin: "*" combiné à credentials: true est refusé par les navigateurs et constitue une mauvaise pratique de sécurité. Listez les origines autorisées.

🛡️ Sécurité minimale

Valider les entrées

Contrôlez type, longueur et format côté serveur, jamais uniquement côté client.

Limiter le débit

Un rate limiting protège des abus et du bruteforce sur la connexion.

Servir en HTTPS

Sans chiffrement, tokens et mots de passe circulent en clair.

Filtrer les champs renvoyés

Ne renvoyez jamais le hash du mot de passe ni les champs internes.

📖 Documenter avec OpenAPI

OpenAPI (ex-Swagger) décrit l'API dans un fichier YAML ou JSON exploitable par des outils de documentation et de génération de clients.

paths:
  /articles/{id}:
    get:
      summary: Récupérer un article
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: integer }
      responses:
        "200": { description: Article trouvé }
        "404": { description: Article inexistant }

Une documentation générée depuis le code reste à jour ; une documentation rédigée à la main diverge en quelques semaines.

➡️ Suite

La page Consommer et tester montre comment appeler et vérifier votre API.

API REST

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page