Anatomie d'une requête HTTP
Anatomie d’une requête et d’une réponse HTTP.
Objectifs
À la fin de cette leçon, vous saurez :
- décrire la structure exacte d'une requête et d'une réponse HTTP, bloc par bloc ;
- décomposer une URL complète et nommer chaque partie ;
- expliquer ce que signifie « HTTP est sans état » — et pourquoi c'est un choix, pas une limite ;
- relier tout cela à la conversation netcat de la leçon 09-03.
🔗 Pour vous rafraîchir la mémoire : parler TCP à la main
Vous avez déjà vu ce protocole
Souvenez-vous : avec nc, vous avez écrit à la main GET / HTTP/1.1 et lu la réponse brute. Cette leçon formalise ce que vous avez alors observé. HTTP est du texte structuré transporté sur TCP — chaque octet est lisible, prévisible, testable.
Une requête, ligne par ligne
GET /users/42 HTTP/1.1
Host: exemple.fr
User-Agent: Mozilla/5.0 (X11; Linux x86_64)
Accept: application/json
Trois blocs, toujours dans cet ordre :
- Ligne de requête :
MÉTHODE chemin version. Ici : « donne-moi (GET) la ressource/users/42, en parlant HTTP version 1.1 » ; - En-têtes : des métadonnées
Clé: Valeur, une par ligne — qui parle (User-Agent), quel format est accepté (Accept), quel site est visé (Host) ; - Corps (facultatif pour GET, essentiel pour POST) : les données envoyées, séparées des en-têtes par une ligne vide obligatoire — c'est le marqueur « fin des en-têtes » que vous avez déjà manié avec nc.
La ligne vide n'est pas décorative : sans elle, le serveur attend indéfiniment des en-têtes qui ne finissent jamais. Chaque convention a sa raison d'être.
La réponse correspondante
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 34
{"id": 42, "name": "Paul"}
Structure symétrique :
- Ligne de statut : version + code + libellé — « voici le verdict » ;
- En-têtes : nature du contenu (Content-Type), taille annoncée (Content-Length), instructions diverses ;
- Corps : la donnée demandée.
Notez le contrat implicite rendu possible par les en-têtes : Content-Length: 34 annonce 34 octets ; si le client en compte 33, il SAIT qu'il manque quelque chose — la fiabilité du transfert se vérifie au lieu d'être espérée.
Décomposer une URL
https://exemple.fr:443/users/42?tri=nom&page=2
└─┬──┘ └────┬────┘└┬─┘└────┬────┘└───────┬────────┘
protocole hôte port chemin query parameters
| Partie | Rôle | Exemple |
|---|---|---|
| protocole | comment parler | https |
| hôte | quelle machine (via DNS !) | exemple.fr |
| port | quelle porte (implicite : 80/443) | 443 |
| chemin | QUELLE ressource | /users/42 |
| query parameters | options de lecture/filtrage | tri=nom&page=2 |
Convention d'architecture à retenir dès maintenant : le chemin identifie une ressource, les query parameters affinent la consultation. /users/42 = « l'utilisateur 42 » ; ?champs=nom,email = « mais ne me montre que ça ». Cette distinction structurera toutes vos futures API.
Sans état : le choix qui fait tourner le web
Point capital : HTTP est sans état (stateless). Le serveur ne se souvient PAS de la requête précédente — chaque échange est autonome, comme un guichet où chaque client doit réexpliquer son dossier.
Ce choix paraît handicapant (« mais comment fonctionne ma connexion ? ») ; il est en réalité stratégique :
- n'importe quel serveur du parc peut traiter n'importe quelle requête → répartition de charge triviale ;
- aucun état à restaurer après panne → résilience ;
- aucune mémoire à purger entre clients → sécurité simple.
requête 1 → serveur A (A ne retient rien)
requête 2 → serveur B (B n'en sait pas plus)
requête 3 → serveur C (et pourtant votre session fonctionne !)
Alors comment « rester connecté » sur un site ? Par convention : lors de la première connexion, le serveur remet un identifiant (cookie de session) ; le client le renvoie dans CHAQUE requête suivante ; le serveur consulte son carnet (base de données, souvent partagée entre les trois serveurs ci-dessus). L'état vit dans cette convention client+stockage, jamais dans le protocole. Détail instructif : c'est exactement notre mécanique de cookies qui sera disséquée dans deux leçons.
Exercice
- Écrivez à la main la requête GET complète vers
/api/cours?page=2surmonsite.fr. - Dans
https://boutique.fr/produits?cat=clavier&promo=1, identifiez protocole, hôte, port, chemin et paramètres. - Pourquoi trois serveurs derrière un même nom de domaine peuvent-ils servir vos requêtes successives sans se coordonner ?
- Écrivez la réponse HTTP minimale valide correspondant à « ressource trouvée, contenu HTML de 12 caractères ».
- Question de réflexion : pourquoi la ligne vide séparant en-têtes et corps est-elle indispensable ?
Résumé
- Requête = méthode + chemin + version, en-têtes, [corps] ; réponse = statut, en-têtes, corps — séparés par une ligne vide obligatoire.
- URL = protocole + hôte (+ port) + chemin (ressource) + query (options).
- Sans état = chaque requête autonome : scalabilité et résilience gratuites ; la continuité vient des cookies, convention au-dessus du protocole.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1.
GET /api/cours?page=2 HTTP/1.1
Host: monsite.fr
Deux lignes suffisent techniquement (Host obligatoire depuis HTTP/1.1) ; la ligne vide finale ferme les en-têtes.
Question 2.
protocole : https hôte : boutique.fr port : implicite (443)
chemin : /produits query : cat=clavier & promo=1
Lecture architecturale : la ressource « liste des produits », filtrée sur la catégorie clavier, promotion incluse. Le chemin désigne LE quoi, la query précise LE comment.
Question 3. Parce que le protocole est sans état : aucune requête ne dépend d'une mémoire locale du serveur précédent. N'importe laquelle des trois machines peut traiter n'importe quelle requête. La seule continuité nécessaire — votre session — vit dans le cookie que VOTRE navigateur renvoie, et dans un stockage commun (base de données) accessible aux trois. C'est cette propriété qui rend la montée en charge du web possible : ajouter un serveur = ajouter un exécutant interchangeable.
Question 4.
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12
Bonjour tout!
Le strict minimum : statut, Content-Type (sinon le client devine), Content-Length cohérent, ligne vide, corps. Tout autre en-tête est facultatif.
Question 5. Parce que les en-têtes ont une longueur variable et non délimitée autrement : sans marqueur de fin, le destinataire ne peut pas savoir où commence le corps (surtout quand le corps EST lui-même du texte pouvant contenir des deux-points...). La ligne vide est la frontière syntaxique universelle — même logique que les lignes vides séparant les messages SMTP ou les paragraphes d'un manifeste YAML. Un protocole textuel doit définir précisément ses séparateurs.