Passer au contenu principal

📬 Méthodes HTTP

📖 Définition

Les méthodes HTTP indiquent l'action que le client souhaite effectuer sur le serveur. Chaque méthode a une signification et un usage spécifiques, et constitue le cœur de la conception d'API RESTful.

🎯 Comprendre par une analogie

Système de bibliothèque

GET    = Rechercher un livre (lecture)
├─ Demander au bibliothécaire "Avez-vous ce livre ?"
├─ Ne récupère que des données
└─ Aucun changement dans l'état de la bibliothèque

POST = Enregistrer un nouveau livre (création)
├─ Ajouter un nouveau livre à la bibliothèque
├─ Modification de l'état de la bibliothèque
└─ Création d'une nouvelle ressource

PUT = Remplacer entièrement les informations d'un livre (mise à jour complète)
├─ Réécrire toutes les informations du livre
└─ Remplacement total

PATCH = Modifier partiellement les informations d'un livre (mise à jour partielle)
├─ Modifier uniquement certaines informations du livre (ex : disponibilité)
└─ Modification partielle

DELETE = Supprimer un livre (suppression)
├─ Retirer le livre de la bibliothèque
└─ Suppression de la ressource

💡 Méthodes HTTP principales

GET - Récupération de données

Usage : Récupérer une ressource du serveur

Caractéristiques :
├─ Sûre (Safe) : Ne modifie pas l'état du serveur
├─ Idempotente : Résultat identique lors de plusieurs appels
├─ Peut être mise en cache
└─ Apparaît dans l'historique du navigateur

Exemple de requête :
GET /api/users HTTP/1.1
Host: example.com
// API Fetch de JavaScript
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data));

// jQuery
$.get('https://api.example.com/users', function(data) {
console.log(data);
});

// axios
axios.get('https://api.example.com/users')
.then(response => console.log(response.data));
# curl
curl https://api.example.com/users

# Récupération d'un utilisateur spécifique
curl https://api.example.com/users/123

# Utilisation de paramètres de requête
curl "https://api.example.com/users?page=1&limit=10"

Exemple de réponse :

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

{
"users": [
{ "id": 1, "name": "Jean Dupont" },
{ "id": 2, "name": "Marie Martin" }
]
}

POST - Création de données

Usage : Créer une nouvelle ressource sur le serveur

Caractéristiques :
├─ Non sûre : Modifie l'état du serveur
├─ Non idempotente : Plusieurs appels créent plusieurs ressources
├─ Non cachable
└─ Inclut des données dans le corps de la requête

Exemple de requête :
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json

{
"name": "Jean Dupont",
"email": "jean@example.com"
}
// Fetch API
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Jean Dupont',
email: 'jean@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));

// axios
axios.post('https://api.example.com/users', {
name: 'Jean Dupont',
email: 'jean@example.com'
})
.then(response => console.log(response.data));
# curl
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"Jean Dupont","email":"jean@example.com"}'

Exemple de réponse :

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

{
"id": 123,
"name": "Jean Dupont",
"email": "jean@example.com",
"createdAt": "2025-01-26T10:00:00Z"
}

PUT - Mise à jour complète des données

Usage : Remplacer une ressource entière par de nouvelles données

Caractéristiques :
├─ Non sûre : Modifie l'état du serveur
├─ Idempotente : Résultat identique lors de plusieurs appels
├─ Remplace entièrement la ressource
└─ Peut créer si la ressource n'existe pas

Exemple de requête :
PUT /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json

{
"name": "Jean Dupont",
"email": "nouveau-email@example.com",
"phone": "01 23 45 67 89"
}
// Fetch API
fetch('https://api.example.com/users/123', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Jean Dupont',
email: 'nouveau-email@example.com',
phone: '01 23 45 67 89'
})
})
.then(response => response.json())
.then(data => console.log(data));

// axios
axios.put('https://api.example.com/users/123', {
name: 'Jean Dupont',
email: 'nouveau-email@example.com',
phone: '01 23 45 67 89'
})
.then(response => console.log(response.data));
# curl
curl -X PUT https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"name":"Jean Dupont","email":"nouveau-email@example.com","phone":"01 23 45 67 89"}'

PATCH - Mise à jour partielle des données

Usage : Modifier uniquement une partie des données d'une ressource

Caractéristiques :
├─ Non sûre : Modifie l'état du serveur
├─ Peut être idempotente ou non
├─ Modifie uniquement certains champs
└─ Plus efficace que PUT

Exemple de requête :
PATCH /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json

{
"email": "nouveau-email@example.com"
}
// Fetch API
fetch('https://api.example.com/users/123', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'nouveau-email@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));

// axios
axios.patch('https://api.example.com/users/123', {
email: 'nouveau-email@example.com'
})
.then(response => console.log(response.data));
# curl
curl -X PATCH https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"email":"nouveau-email@example.com"}'

Comparaison PUT vs PATCH :

Données existantes :
{
"id": 123,
"name": "Jean Dupont",
"email": "ancien@example.com",
"phone": "01 11 22 33 44"
}

Requête PUT (remplacement total) :
{
"name": "Jean Dupont",
"email": "nouveau@example.com"
}
Résultat :
{
"id": 123,
"name": "Jean Dupont",
"email": "nouveau@example.com"
// Champ téléphone supprimé !
}

Requête PATCH (modification partielle) :
{
"email": "nouveau@example.com"
}
Résultat :
{
"id": 123,
"name": "Jean Dupont",
"email": "nouveau@example.com",
"phone": "01 11 22 33 44"
// Champ téléphone conservé !
}

DELETE - Suppression de données

Usage : Supprimer une ressource

Caractéristiques :
├─ Non sûre : Modifie l'état du serveur
├─ Idempotente : Plusieurs appels donnent le même résultat
├─ Corps de réponse potentiellement vide
└─ Suppression potentiellement irréversible

Exemple de requête :
DELETE /api/users/123 HTTP/1.1
Host: example.com
// Fetch API
fetch('https://api.example.com/users/123', {
method: 'DELETE'
})
.then(response => {
if (response.ok) {
console.log('Suppression effectuée');
}
});

// axios
axios.delete('https://api.example.com/users/123')
.then(response => console.log('Suppression effectuée'));
# curl
curl -X DELETE https://api.example.com/users/123

Exemple de réponse :

HTTP/1.1 204 No Content

ou

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

{
"message": "Utilisateur supprimé",
"deletedId": 123
}

🔍 Autres méthodes HTTP

HEAD - Récupération uniquement des en-têtes

Usage : Identique à GET mais ne retourne que les en-têtes sans corps

Cas d'utilisation :
├─ Vérifier l'existence d'une ressource
├─ Vérifier la taille du fichier
└─ Vérifier le temps de modification

Exemple :
HEAD /api/users/123 HTTP/1.1
Host: example.com

Réponse :
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 256
Last-Modified: Sat, 26 Jan 2025 10:00:00 GMT
# curl
curl -I https://api.example.com/users/123

OPTIONS - Vérification des méthodes supportées

Usage : Vérifier les méthodes supportées par le serveur (utilisé pour les requêtes préliminaires CORS)

Exemple :
OPTIONS /api/users HTTP/1.1
Host: example.com

Réponse :
HTTP/1.1 200 OK
Allow: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Origin: *
# curl
curl -X OPTIONS https://api.example.com/users -i

📊 Comparaison des attributs des méthodes

┌─────────┬──────┬────────┬─────────┬────────────┐
│ Méthode │ Sûre │ Idempotence │ Cachable │ Corps requête │
├─────────┼──────┼────────┼─────────┼────────────┤
│ GET │ ✅ │ ✅ │ ✅ │ ❌ │
│ POST │ ❌ │ ❌ │ ❌ │ ✅ │
│ PUT │ ❌ │ ✅ │ ❌ │ ✅ │
│ PATCH │ ❌ │ △ │ ❌ │ ✅ │
│ DELETE │ ❌ │ ✅ │ ❌ │ △ │
│ HEAD │ ✅ │ ✅ │ ✅ │ ❌ │
│ OPTIONS │ ✅ │ ✅ │ ❌ │ ❌ │
└─────────┴──────┴────────┴─────────┴────────────┘

Explication des termes :
- Sûre (Safe) : Ne modifie pas l'état du serveur
- Idempotente (Idempotent) : Résultat identique lors de plusieurs appels
- Cachable : Possibilité de mettre en cache la réponse

💡 Conception d'API RESTful

Mappage CRUD avec méthodes HTTP

Create  → POST
Read → GET
Update → PUT / PATCH
Delete → DELETE

Exemple d'API RESTful

Ressource : utilisateurs (users)

GET /users - Liste tous les utilisateurs
GET /users/123 - Récupère un utilisateur spécifique
POST /users - Crée un nouvel utilisateur
PUT /users/123 - Remplace complètement un utilisateur
PATCH /users/123 - Modifie partiellement un utilisateur
DELETE /users/123 - Supprime un utilisateur

Ressources imbriquées :
GET /users/123/posts - Liste des posts d'un utilisateur
GET /users/123/posts/456 - Récupère un post spécifique
POST /users/123/posts - Crée un nouveau post
PUT /users/123/posts/456 - Modifie un post
DELETE /users/123/posts/456 - Supprime un post

Exemple pratique : API de blog

// API de posts de blog

// 1. Liste des posts (pagination, filtrage)
GET /api/posts?page=1&limit=10&category=tech

// 2. Récupération d'un post spécifique
GET /api/posts/123

// 3. Création d'un nouveau post
POST /api/posts
{
"title": "Maîtrise complète des méthodes HTTP",
"content": "...",
"category": "tech"
}

// 4. Mise à jour complète d'un post
PUT /api/posts/123
{
"title": "Maîtrise complète des méthodes HTTP (mis à jour)",
"content": "...",
"category": "tech"
}

// 5. Mise à jour partielle (augmentation du nombre de vues)
PATCH /api/posts/123
{
"views": 101
}

// 6. Suppression d'un post
DELETE /api/posts/123

// 7. Commentaires
GET /api/posts/123/comments - Liste des commentaires
POST /api/posts/123/comments - Création d'un commentaire
DELETE /api/posts/123/comments/456 - Suppression d'un commentaire

🤔 Questions fréquentes

Q1. Quelle est la différence entre POST et PUT ?

R :

POST :
├─ Crée une nouvelle ressource
├─ Le serveur détermine l'URI de la ressource
├─ Non idempotent (plusieurs appels créent plusieurs ressources)
└─ Exemple : POST /users

PUT :
├─ Remplace entièrement une ressource
├─ Le client spécifie l'URI de la ressource
├─ Idempotent (plusieurs appels donnent le même résultat)
└─ Exemple : PUT /users/123

Analogie pratique :
POST = "Créez un nouveau compte bancaire" (la banque attribue un numéro)
PUT = "Remplacez toutes les informations du compte 123"

Q2. Peut-on envoyer un corps de requête avec GET ?

R :

Techniquement possible mais :
├─ Autorisé par la spécification HTTP mais non recommandé
├─ Ignoré par de nombreux serveurs/frameworks
├─ Problèmes de mise en cache et de journalisation
└─ Utiliser des paramètres de requête recommandé

❌ Mauvais exemple :
GET /api/users
{
"filters": { "age": 25 }
}

✅ Bon exemple :
GET /api/users?age=25

Ou utiliser POST pour des recherches complexes :
POST /api/users/search
{
"filters": { "age": 25, "city": "Paris" }
}

Q3. Peut-on envoyer un corps avec DELETE ?

R :

Possible mais à utiliser avec précaution :
├─ Autorisé par la spécification HTTP
├─ Certains serveurs/proxys peuvent l'ignorer
├─ Généralement, l'ID de ressource est inclus dans l'URI
└─ Le corps peut transmettre des informations supplémentaires

Exemple d'utilisation :

✅ Méthode standard :
DELETE /api/users/123

✅ Conditions de suppression complexes :
DELETE /api/posts/bulk
{
"ids": [1, 2, 3, 4, 5]
}

✅ Transmission de la raison de suppression :
DELETE /api/users/123
{
"reason": "Demande de l'utilisateur",
"confirm": true
}

Q4. Pourquoi l'idempotence est-elle importante ?

R :

Importance de l'idempotence :

1. Réponse aux défaillances réseau
├─ Possibilité de réessayer en cas d'échec
├─ Pas d'inquiétude concernant les requêtes en double
└─ Reprise sûre

Exemples :
GET /users/123 → Plusieurs appels sûrs
POST /users → Plusieurs appels créent plusieurs utilisateurs !
PUT /users/123 → Plusieurs appels donnent le même résultat
DELETE /users/123 → Plusieurs suppressions donnent le même résultat

2. Logique de reprise côté client
├─ Réessais sûrs en cas de timeout
└─ Possibilité de mise en place de mécanismes de reprise automatique

3. Mise en cache et optimisation
├─ Requêtes idempotentes peuvent être mises en cache
└─ Optimisation de performance facilitée

Q5. Critères de sélection des méthodes en pratique ?

R :

Guide de sélection :

1. Lecture de données uniquement
→ GET

2. Création de nouvelles données
→ POST

3. Remplacement complet des données
→ PUT
Ex : Mise à jour complète du profil utilisateur

4. Modification partielle de données
→ PATCH
Ex : Incrémentation du nombre de likes, changement d'état

5. Suppression de données
→ DELETE

6. Recherche complexe
→ POST /search
(Contournement des limites de longueur d'URL de GET)

Exemples pratiques :

// ✅ Bon exemple
GET /api/products - Liste des produits
GET /api/products/123 - Détails du produit
POST /api/products - Enregistrement d'un produit
PATCH /api/products/123/stock - Modification du stock
PUT /api/products/123 - Mise à jour complète du produit
DELETE /api/products/123 - Suppression du produit

// ❌ Mauvais exemple
GET /api/deleteProduct?id=123 - Utiliser DELETE
POST /api/getProducts - Utiliser GET
POST /api/updateProduct - Utiliser PUT/PATCH

🎓 Mise en pratique

1. Pratique avec l'API Fetch

// Requête GET
async function getUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
const data = await response.json();
return data;
}

// Requête POST
async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
return await response.json();
}

// Requête PUT
async function updateUser(id, userData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
return await response.json();
}

// Requête PATCH
async function patchUser(id, partialData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(partialData)
});
return await response.json();
}

// Requête DELETE
async function deleteUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'DELETE'
});
return response.ok;
}

2. Gestion des erreurs

async function apiRequest(url, options = {}) {
try {
const response = await fetch(url, options);

if (!response.ok) {
throw new Error(`Erreur HTTP ! statut : ${response.status}`);
}

return await response.json();
} catch (error) {
console.error('Échec de la requête API :', error);
throw error;
}
}

// Exemple d'utilisation
try {
const user = await apiRequest('https://api.example.com/users/123');
console.log(user);
} catch (error) {
console.error('Échec de la récupération de l\'utilisateur');
}

🔗 Documents associés

🎬 Conclusion

Les méthodes HTTP sont au cœur des API RESTful. Comprendre leurs caractéristiques vous permettra de concevoir des API intuitives et faciles à maintenir !

Prochaine étape : Lisez Codes de statut HTTP pour comprendre 200, 404, 500, etc.