HTTP en profondeur - 04 - Les méthodes HTTP

Toutes les méthodes HTTP : GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD, TRACE, CONNECT. Safe, idempotent, cacheable.

04 - Les méthodes HTTP

Ce que tu vas apprendre

  • Les 9 méthodes HTTP standardisees et leur semantique exacte
  • La différence entre safe, idempotent et cacheable
  • Les usages réels de HEAD, OPTIONS, TRACE et CONNECT
  • Pourquoi TRACE est un risque de sécurité
  • Les erreurs classiques dans l'utilisation des méthodes

Prerequisites

Avoir lu 02 - La requête HTTP et 03 - La réponse HTTP pour comprendre la structure des messages.


J'ai travaille sur un projet ou toutes les routes API etaient en POST. Creer un utilisateur ? POST. Lire un utilisateur ? POST. Supprimer un utilisateur ? POST. Le dev avait une justification : "POST, ca marche pour tout, pourquoi s'embeter avec le reste ?" La réponse courte : parce que les méthodes HTTP ont une semantique et que cette semantique est exploitee par les navigateurs, les caches, les proxies et les CDN.

Les 9 méthodes

Voici les neuf méthodes définies par la spec HTTP :

GET     - Recuperer une ressource
HEAD    - Comme GET mais sans le body
POST    - Soumettre des donnees, creer une ressource
PUT     - Remplacer une ressource
DELETE  - Supprimer une ressource
PATCH   - Modifier partiellement une ressource
OPTIONS - Decouvrir les capacites du serveur
TRACE   - Echo de la requete (debug)
CONNECT - Etablir un tunnel TCP

Safe, idempotent, cacheable

Trois propriétés definissent le comportement attendu de chaque méthode :

Méthode Safe Idempotent Cacheable
GET oui oui oui
HEAD oui oui oui
POST non non rarement
PUT non oui non
DELETE non oui non
PATCH non non non
OPTIONS oui oui non
TRACE oui oui non
CONNECT non non non

Safe : la méthode ne modifie pas l'état du serveur. Un GET ne devrait jamais créer, modifier ou supprimer quoi que ce soit. Si ton GET /api/users/42 supprime l'utilisateur 42, tu as un problème.

Idempotent : appeler la méthode une fois ou dix fois produit le meme résultat. DELETE /api/users/42 appele deux fois devrait avoir le meme effet (l'utilisateur est supprime). Le deuxieme appel peut retourner 404, mais l'état du serveur ne change pas.

Cacheable : la réponse peut etre stockee et reutilisee. Seuls GET et HEAD sont cacheables par défaut. POST peut l'etre si le serveur envoie les bons headers, mais c'est rare.

GET : la méthode reine

GET /api/users?role=admin HTTP/1.1
Host: api.example.com
Accept: application/json

GET récupéré une ressource. Pas de body dans la requête (techniquement la spec ne l'interdit pas, mais en pratique personne ne le supporte). Les paramètres passent dans l'URL.

Ce qui va mal avec GET en pratique :

  • Des GET qui modifient des donnees (compteurs de vues implementes en GET sans cache)
  • Des GET avec des bodies (Elasticsearch le faisait, et ca a cause des problèmes avec les proxies)
  • Des query strings trop longues (la limite depend du serveur, nginx coupe a 8 KB par défaut)

HEAD : GET sans le body

HEAD /api/users/42 HTTP/1.1
Host: api.example.com
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 234
Last-Modified: Sat, 29 Mar 2026 08:00:00 GMT

HEAD retourne exactement les memes headers qu'un GET, mais sans le body. Utilisation réelle :

  • Verifier si une ressource existe (sans telecharger le contenu)
  • Récupérer la taille d'un fichier avant de le telecharger (Content-Length)
  • Verifier la fraicheur d'un cache (Last-Modified, ETag)
  • Monitorer la disponibilité d'un endpoint (health checks legers)

POST : le couteau suisse

POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 45

{"name": "Charlie", "email": "c@example.com"}

POST soumet des donnees au serveur. La spec dit que POST peut faire a peu pres n'importe quoi, ce qui en fait la méthode la plus flexible mais aussi la plus abusee.

En pratique :

  • Creer une ressource (le serveur choisit l'identifiant)
  • Soumettre un formulaire
  • Declencher un traitement (envoyer un email, lancer un job)
  • Tout ce qui ne rentre pas dans les autres méthodes

POST n'est pas idempotent. Envoyer deux fois le meme POST peut créer deux ressources. C'est pour ca qu'on voit des patterns comme les tokens d'idempotence dans les API de paiement.

PUT : remplacement total

PUT /api/users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 52

{"name": "Charlie", "email": "c@example.com", "role": "admin"}

PUT remplace la ressource complète. Si tu omets un champ, il disparaît. C'est la différence fondamentale avec PATCH.

PUT est idempotent : envoyer le meme PUT dix fois produit le meme résultat. La ressource a le contenu que tu as envoye, point.

DELETE : supprimer

DELETE /api/users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOi...
HTTP/1.1 204 No Content

DELETE supprime la ressource. Idempotent : supprimer une ressource deja supprimee ne change rien (meme si le serveur retourne 404 au lieu de 204).

Est-ce que DELETE peut avoir un body ? La spec dit que le body n'a pas de semantique définie pour DELETE. Certains serveurs l'ignorent, d'autres le rejettent. Mon conseil : ne mets pas de body dans un DELETE.

PATCH : modification partielle

PATCH /api/users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 22

{"role": "moderator"}

PATCH modifie une partie de la ressource. Seuls les champs envoyes sont modifies, les autres restent intacts. C'est la méthode la plus utilisee en pratique pour les mises à jour, meme si PUT est conceptuellement plus propre.

PATCH n'est pas idempotent par définition. Imagine un PATCH qui incremente un compteur : l'appeler deux fois donne un résultat différent. En pratique, la plupart des PATCH "set field to value" sont idempotents, mais la spec ne le garantit pas.

OPTIONS : qu'est-ce que tu sais faire ?

OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://frontend.example.com
HTTP/1.1 204 No Content
Allow: GET, POST, OPTIONS
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

OPTIONS a deux usages :

  1. Découverte : le header Allow liste les méthodes supportees par la ressource
  2. CORS preflight : le navigateur envoie automatiquement un OPTIONS avant certaines requêtes cross-origin pour vérifier les permissions

Le CORS preflight est de loin l'usage le plus courant. Si tu vois des requêtes OPTIONS dans tes logs et que tu ne les as pas envoyees, c'est le navigateur qui vérifié les permissions CORS.

TRACE : le piège

TRACE /api/users HTTP/1.1
Host: api.example.com
Cookie: session=abc123
HTTP/1.1 200 OK
Content-Type: message/http

TRACE /api/users HTTP/1.1
Host: api.example.com
Cookie: session=abc123

TRACE renvoie la requête telle que le serveur l'a reçue. L'idee originale : debugger les proxies intermediaires en voyant comment ils modifient les headers.

Le problème : un attaquant peut utiliser TRACE pour voler des cookies HttpOnly via du JavaScript (attaque Cross-Site Tracing). Le script envoie un TRACE, la réponse contient les cookies, et le script les lit meme s'ils sont HttpOnly.

La bonne pratique : désactivé TRACE sur tous tes serveurs. Nginx le bloque par défaut. Apache aussi depuis des annees.

CONNECT : le tunnel

CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com
HTTP/1.1 200 Connection Established

CONNECT transforme la connexion HTTP en tunnel TCP brut. C'est utilise par les proxies HTTP pour permettre les connexions HTTPS. Le client dit au proxy "connecte-moi a ce serveur sur ce port", et le proxy relaie les octets sans les lire.

Tu ne feras probablement jamais un CONNECT toi-meme. C'est le navigateur ou le client HTTP qui l'utilise automatiquement quand tu passes par un proxy HTTP pour acceder a un site HTTPS.

Les erreurs classiques

Tout en POST : on perd le caching, l'idempotence, et la semantique. Les CDN ne cachent pas les POST. Les navigateurs ne peuvent pas rejouer un POST sans demander confirmation.

DELETE avec confirmation dans le body : "envoie {"confirm": true} pour vraiment supprimer." C'est un anti-pattern. Si tu as besoin de confirmation, utilise un workflow en deux étapes (POST pour demander la suppression, puis DELETE pour confirmer).

PATCH qui remplace tout : si ton PATCH attend tous les champs de la ressource, c'est un PUT deguise. Utilise PUT et sois honnete.

Sur paltemps.fr, on suit une regle simple : si la méthode ne correspond pas a la semantique, on ne l'utilise pas, meme si "ca marche quand meme."

Résumé

  • 9 méthodes HTTP, chacune avec une semantique precise
  • Safe = pas de modification, Idempotent = repetable sans effet, Cacheable = stockable
  • GET et HEAD sont les seules méthodes cacheables par défaut
  • PATCH pour les mises à jour partielles, PUT pour le remplacement complet
  • OPTIONS est surtout utilise pour les preflight CORS
  • Desactive TRACE sur tous tes serveurs

Precedent : 03 - La réponse HTTP Suivant : 05 - Les codes de statut

Sources

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