REST API design - 03 - Les méthodes HTTP, pour de vrai

GET, POST, PUT, PATCH, DELETE et les autres : idempotence, safety, et quand utiliser quoi.

  1. 01 REST API design - 00 - Pourquoi le design de ton API change tout
  2. 02 REST API design - 01 - Les principes REST que personne ne lit
  3. 03 REST API design - 02 - Des URLs qui ont du sens
  4. 04 REST API design - 03 - Les méthodes HTTP, pour de vrai
  5. 05 REST API design - 04 - Les codes de statut HTTP qu'il faut connaître
  6. 06 REST API design - 05 - Body, headers et le diable dans les détails
  7. 07 REST API design - 06 - La pagination, ou comment ne pas tuer ta base
  8. 08 REST API design - 07 - Filtrage et tri sans prise de tête
  9. 09 REST API design - 08 - La validation avec Zod, gardien de ton API
  10. 10 REST API design - 09 - Erreurs : un format que tes clients vont adorer
  11. 11 REST API design - 10 - Authentification : JWT, API keys et OAuth2
  12. 12 REST API design - 11 - Versioning : quand et comment faire évoluer ton API
  13. 13 REST API design - 12 - CORS : comprendre et debugger les erreurs cross-origin
  14. 14 REST API design - 13 - Rate limiting : protéger ton API sans frustrer tes clients
  15. 15 REST API design - 14 - Caching : les bonnes réponses sont celles qu'on n'envoie pas
  16. 16 REST API design - 15 - Upload de fichiers : multipart, signed URLs et streaming
  17. 17 REST API design - 16 - Relations entre ressources : embarquer, lier ou les deux
  18. 18 REST API design - 17 - HATEOAS : des liens dans tes réponses
  19. 19 REST API design - 18 - OpenAPI : le contrat entre ton API et le monde
  20. 20 REST API design - 19 - Documentation : une API non documentee est une API inutile
  21. 21 REST API design - 20 - Testing : tester ton API sans devenir fou
  22. 22 REST API design - 21 - Webhooks : quand c'est ton API qui appelle
  23. 23 REST API design - 22 - Performance : quand chaque milliseconde compte
  24. 24 REST API design - 23 - Sécurité : les attaques que tu vas subir (et comment t'en protéger)
  25. 25 REST API design - 24 - Glossaire : tous les termes REST API en un seul endroit

03 - Les méthodes HTTP, pour de vrai

Ce que tu vas apprendre

  • Les 7 méthodes HTTP utilisees en REST et leur semantique
  • La différence entre méthode safe et idempotente
  • PUT vs PATCH : le debat eternel, tranche une bonne fois
  • Les erreurs les plus courantes avec les méthodes HTTP

Prerequisites


POST pour tout : le syndrome du marteau

Sur un vieux projet, j'ai découvert une API ou 100% des endpoints etaient en POST. Creer un utilisateur ? POST. Lire un utilisateur ? POST avec {"action": "read"} dans le body. Supprimer ? POST avec {"action": "delete"}. Le dev m'a dit : "POST, ca marche pour tout." Techniquement vrai. Semantiquement, c'est un massacre.

Les méthodes HTTP ne sont pas decoratives. Elles portent une semantique precise que les navigateurs, proxies, CDN et outils de monitoring comprennent. Utiliser la bonne méthode, c'est rendre ton API previsible.

Les méthodes, une par une

GET -- Lire une ressource

GET est safe (pas d'effet de bord) et idempotent (meme résultat a chaque appel). Pas de body dans la requête.

httpGET /api/users/42 HTTP/1.1
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{"id": 42, "name": "Alice", "email": "alice@example.com"}

POST -- Creer une ressource

POST n'est ni safe ni idempotent. Deux appels identiques creent deux ressources.

httpPOST /api/users HTTP/1.1
Content-Type: application/json

{"name": "Bob", "email": "bob@example.com"}

HTTP/1.1 201 Created
Location: /api/users/43
Content-Type: application/json

{"id": 43, "name": "Bob", "email": "bob@example.com"}

Note le header Location qui pointe vers la ressource créée. C'est un détail que beaucoup oublient mais qui rend l'API propre.

PUT -- Remplacer une ressource

PUT est idempotent. Tu envoies la representation complète de la ressource. Si tu oublies un champ, il est ecrase (souvent a null).

httpPUT /api/users/42 HTTP/1.1
Content-Type: application/json

{"name": "Alice Martin", "email": "alice.martin@example.com", "role": "admin"}

HTTP/1.1 200 OK

PATCH -- Modifier partiellement

PATCH n'est pas garanti idempotent (meme si en pratique, on l'implemente souvent de facon idempotente). Tu envoies seulement les champs a modifier.

httpPATCH /api/users/42 HTTP/1.1
Content-Type: application/json

{"email": "new-alice@example.com"}

HTTP/1.1 200 OK

DELETE -- Supprimer une ressource

DELETE est idempotent. Supprimer deux fois la meme ressource donne le meme résultat (la ressource n'existe plus).

httpDELETE /api/users/42 HTTP/1.1

HTTP/1.1 204 No Content

Un deuxieme appel peut renvoyer 204 ou 404 -- les deux sont valides. Mon opinion : 204 dans les deux cas, c'est plus simple pour le client.

HEAD -- GET sans le body

HEAD retourne les memes headers qu'un GET, mais sans body. Utile pour vérifier si une ressource existe ou pour checker les headers de cache.

httpHEAD /api/users/42 HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 89
ETag: "abc123"

OPTIONS -- Découvrir les méthodes disponibles

OPTIONS retourne les méthodes autorisees sur une URL. C'est aussi utilise par les navigateurs pour les requêtes CORS preflight.

httpOPTIONS /api/users HTTP/1.1

HTTP/1.1 204 No Content
Allow: GET, POST, HEAD, OPTIONS

Safe vs idempotent

Deux concepts que tout le monde melange :

Méthode Safe Idempotent
GET oui oui
HEAD oui oui
OPTIONS oui oui
POST non non
PUT non oui
PATCH non non*
DELETE non oui

Safe : la requête ne modifie pas l'état du serveur. Un GET ne doit jamais modifier de donnees. J'ai vu des GET qui declenchaient des effets de bord (envoi de mail, compteurs). Ne fais pas ca.

Idempotent : appeler N fois donne le meme résultat qu'appeler une fois. PUT et DELETE sont idempotents. POST ne l'est pas -- d'ou l'utilité des clés d'idempotence (on en parlera dans l'article sur les headers).

*PATCH n'est pas idempotent par spécification, mais en pratique on l'implemente souvent comme tel avec des "merge patch".

PUT vs PATCH : le vrai debat

En TypeScript, la différence est nette :

typescript// PUT : remplacement complet
router.put("/api/users/:id", async (req, res) => {
  const user = await userService.replace(req.params.id, {
    name: req.body.name,       // obligatoire
    email: req.body.email,     // obligatoire
    role: req.body.role,       // obligatoire
    bio: req.body.bio,         // obligatoire, meme si vide
  });
  res.json(user);
});

// PATCH : mise a jour partielle
router.patch("/api/users/:id", async (req, res) => {
  // seuls les champs presents sont mis a jour
  const user = await userService.update(req.params.id, req.body);
  res.json(user);
});

Mon avis apres des annees de pratique : utilise PATCH pour 90% de tes mises à jour. PUT, c'est bien pour les cas ou tu veux garantir que la ressource est dans un état complet et connu apres l'appel. Mais en réalité, les clients envoient rarement tous les champs.

Les erreurs classiques

  1. GET avec body : techniquement pas interdit par la spec, mais les proxies et CDN peuvent le supprimer. Ne fais pas ca.
  2. POST pour lire : ca casse le cache HTTP et empeche les navigateurs de fonctionner correctement.
  3. DELETE avec body : meme problème que GET avec body. Si tu as besoin de paramètres, utilise les query params.
  4. PUT partiel : si tu envoies 3 champs sur 10 avec PUT, les 7 autres seront null. Utilise PATCH.

Tu peux retrouver un recapitulatif de toutes les méthodes sur paltemps.fr.

Résumé

  • Chaque méthode HTTP a une semantique precise : respecte-la
  • GET est safe et idempotent, POST ne l'est ni l'un ni l'autre
  • PUT remplace entièrement, PATCH modifie partiellement
  • Prefere PATCH pour les mises à jour courantes
  • HEAD et OPTIONS existent et sont utiles, ne les oublie pas

Precedent : Design des URLs | Suivant : Les codes de statut HTTP

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.