curl pas à pas
Composer et diagnostiquer des requêtes avec curl.
Objectifs
À la fin de cette leçon, vous saurez :
- envoyer toutes les méthodes HTTP avec
curl, corps et en-têtes compris ; - lire la sortie verbeuse
-vpour voir l'échange complet ; - reproduire la requête d'un client fautif — LE réflexe de débogage API ;
- transformer curl en sonde de santé scriptable.
🔗 Pour vous rafraîchir la mémoire : méthodes et codes de statut · en-têtes, JSON et cookies
Le minimum vital — et pourquoi il ne suffit jamais
$ curl https://exemple.fr
<!doctype html>
<html>
... ← curl affiche uniquement le CORPS de la réponse
Par défaut, curl avale statut et en-têtes pour ne montrer que le contenu — pratique pour télécharger, inutilisable pour diagnostiquer. Tout le reste se demande explicitement.
Voir l'échange complet : -v
curl -v https://exemple.fr
Sortie annotée (abréviations réelles) :
* Host exemple.fr:443 was resolved. ← résolution DNS (chapitre 10)
* Connected to exemple.fr ... port 443 ← connexion TCP (chapitre 9)
* TLS 1.3 connection using TLS_AES_128_GCM_SHA256 ← chiffrement (chapitre 12)
> GET / HTTP/1.1 ← `>` = ce que curl ENVOIE
> Host: exemple.fr
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK ← `<` = ce qui REVIENT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 1256
<
{ [1256 bytes data] ← puis le corps
La sortie -v raconte TOUTE la pile du cours dans l'ordre : DNS → TCP → TLS → HTTP requête → HTTP réponse → corps. Les symboles : * informations de couche basse, > requête sortante, < réponse entrante.
C'est l'outil de diagnostic HTTP n°1. Scénario quotidien : votre frontend affiche une erreur mystérieuse. Ouvrez l'onglet Réseau des devtools, copiez la requête exacte (URL, méthode, en-têtes), rejouez-la avec curl -v : vous isolez immédiatement si le problème vient du serveur (réponse visible brute) ou du client (traitement de la réponse).
Composer n'importe quelle requête : -X, -H, -d
Les trois pièces du puzzle :
| Option | Rôle | Exemple |
|---|---|---|
-X | la méthode | -X POST |
-H | un en-tête (répétable) | -H "Content-Type: application/json" |
-d | le corps | -d '{"name": "Paul"}' |
Démonstration complète sur httpbin.org, un service d'écho qui renvoie ce qu'il reçoit :
curl -X POST https://httpbin.org/post \
-H "Content-Type: application/json" \
-d '{"name": "Paul", "role": "student"}'
Réponse (extrait) :
{
"args": {},
"data": "{\"name\": \"Paul\", \"role\": \"student\"}",
"headers": {
"Content-Type": "application/json",
"Host": "httpbin.org"
},
"url": "https://httpbin.org/post"
}
Lisez le champ "data" : votre JSON est arrivé EXACTEMENT tel quel, et les en-têtes annoncés sont bien partis. Ce service permet de vérifier ce que votre code envoie réellement — précieux quand un client se comporte bizarrement.
Les autres méthodes, mêmes pièces :
# PATCH partiel : modifier seulement l'email
curl -X PATCH https://httpbin.org/patch \
-H "Content-Type: application/json" \
-d '{"email": "nouveau@exemple.fr"}'
# DELETE : souvent sans corps ni réponse
curl -X DELETE -o /dev/null -w "%{http_code}\n" https://httpbin.org/delete
# 200
# GET avec query parameters : attention au & dans les guillemets !
curl "https://httpbin.org/get?tri=nom&page=2"
⚠️ Détail shell hérité du chapitre 1 : l'esperluette & coupe les commandes ! Sans guillemets, ?tri=nom&page=2 enverrait page=2 en arrière-plan (;-like). Toujours quoter les URLs contenant &.
Codes et en-têtes seulement : les modes compacts
curl -i https://exemple.fr # en-têtes + corps (pas la couche basse)
curl -I https://exemple.fr # EN-TÊTES SEULS (requête HEAD)
Et la perle des scripts : ne garder QUE le code de statut :
curl -o /dev/null -s -w "%{http_code}\n" https://exemple.fr
# 200
Décodage : -o /dev/null jette le corps, -s silence les barres de progression, -w "%{http_code}" imprime le verdict final. Trois lettres transformées en sonde de santé.
Votre premier moniteur de disponibilité
Assemblons avec les réflexes shell acquis depuis le chapitre 1 :
for url in https://exemple.fr https://api.github.com; do
code=$(curl -o /dev/null -s -w '%{http_code}' "$url")
if [ "$code" = "200" ]; then
echo "$url : ok"
else
echo "$url : PROBLÈME ($code)"
fi
done
https://exemple.fr : ok
https://api.github.com : ok
Boucle, substitution, test, message : c'est un vrai mini-outil de monitoring, écrit en six lignes. Vous le brancherez plus tard à un cron pour être alerté d'une panne — cercle complet avec le mini-projet script du chapitre 2.
Le protocole de débogage API, de bout en bout
Synthétisons la méthode complète que cette leçon installe :
- Observer la requête fautive dans les devtools du navigateur (URL, méthode, en-têtes, corps) ;
- Rejouer exactement cette requête avec
curl -v— hors du navigateur ; - Comparer : même erreur ? → le problème est côté serveur (lire ses logs). Disparue ? → le client déformait quelque chose (en-tête manquant, JSON cassé) ;
- Corriger UN élément, relancer, vérifier — toujours la méthode systématique du chapitre 6.
Exercice
- Interrogez
https://api.github.comavec-v: notez le statut, le Content-Type, et repérez les trois couches (TCP/TLS/HTTP) dans la sortie. - Envoyez un POST JSON vers
https://httpbin.org/postavec un en-tête personnalisé (-H "X-Formation: devmind") ; retrouvez-le dans la réponse. - Demandez délibérément une ressource inexistante (
https://api.github.com/utilisateurs-inexistants-xyz). Quel code ? Que dit le corps ? - Écrivez une boucle qui teste trois URLs et affiche leur code de statut.
- Question de réflexion : pourquoi
curl -I(HEAD) est-il parfois refusé (405) par certaines applications alors queGETfonctionne ?
Résumé
curl -v= l'échange complet couche par couche ;>sortant,<entrant.-X/-H/-dcomposent toute requête ; toujours quoter URLs avec&.- Reproduire à la main la requête d'un client fautif : LE réflexe de débogage API.
-o /dev/null -s -w "%{http_code}"= sonde de santé scriptable.
https://exemple.fr → 200
https://api.github.com → 200
https://httpbin.org/status/404 → 404
(httpbin propose `/status/<code>` pour provoquer n'importe quel statut : parfait pour tester vos gestionnaires d'erreurs.)
**Question 5.** Parce que `HEAD` doit retourner les mêmes en-têtes que GET mais SANS corps — et beaucoup d'applications (frameworks, routes codées à la main) n'implémentent que GET/POST et rejettent les autres méthodes avec `405 Method Not Allowed`. Le serveur web brut répondrait, mais l'APPLICATION intercepte avant. Morale : un 405 sur HEAD ne signifie pas que le site est en panne — essayez `curl -o /dev/null -s -w "%{http_code}"` en GET avant de conclure. Connaître la différence entre « le serveur » et « l'application » évite de faux diagnostics.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1. Sortie type :
* Connected to api.github.com ... port 443
* TLS 1.3 connection ...
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
Trois couches visibles dans une seule commande : TCP (Connected), TLS (chiffrement négocié — chapitre suivant), HTTP (statut + type). L'API GitHub répond en JSON comme annoncé.
Question 2.
curl -X POST https://httpbin.org/post -H "X-Formation: devmind" -d '{}'
La réponse contient :
"X-Formation": "devmind"
Les en-têtes personnalisés (préfixe X-) traversent tout le chemin et reviennent dans l'écho : preuve qu'ils ont circulé. C'est ainsi qu'on vérifie un jeton d'authentification ou un identifiant de traçage sans lire le code serveur.
Question 3. Statut observé : 404 Not Found. Le corps mérite la lecture : GitHub y place souvent un message JSON explicatif. Nuance vue en cours : 404 = requête valide, ressource absente — le serveur a compris, cherché, et répond proprement. Si vous obteniez plutôt 400 ou 500, la faute serait respectivement dans la requête ou dans le service.
Question 4.
for url in https://exemple.fr https://api.github.com https://httpbin.org/status/404; do
echo "$url → $(curl -o /dev/null -s -w '%{http_code}' "$url")"
done