06 - Les headers HTTP
Ce que tu vas apprendre
- Les 30 headers les plus utilises et leur rôle precis
- La différence entre headers de requête et de réponse
- Pourquoi le prefixe X- n'est plus recommande
- Les headers de sécurité a mettre partout
Prerequisites
Avoir lu 02 - La requête HTTP et 03 - La réponse HTTP.
Les headers HTTP, c'est un peu comme les metadonnees d'un email. Personne ne les lit sauf quand ca tombe en panne. Et quand ca tombe en panne, c'est toujours a cause d'un header manquant, mal orthographie ou avec la mauvaise valeur.
J'ai passe un apres-midi entier a debugger un problème de CORS qui venait d'un Content-type au lieu de Content-Type. Le serveur backend etait en Go et faisait une comparaison case-sensitive sur le header. Techniquement, les headers HTTP ne sont pas sensibles a la casse. Pratiquement, certaines implementations le sont quand meme.
Anatomie d'un header
Un header, c'est une paire clé-valeur séparée par deux-points et un espace :
Content-Type: application/json
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
nom valeur
Quelques regles :
- Le nom n'est pas sensible a la casse (
content-type=Content-Type) - La valeur peut contenir des espaces
- Un meme nom peut apparaître plusieurs fois (les valeurs sont concatenees avec des virgules)
- Pas de limite officielle de taille, mais les serveurs imposent des limites (nginx : 8 KB par header par défaut)
Les headers de requête essentiels
Host
Host: api.example.com
Obligatoire en HTTP/1.1. Permet au serveur de savoir quel site tu vises quand plusieurs domaines sont heberges sur la meme IP (virtual hosting). Sans Host, le serveur ne sait pas ou router ta requête.
Content-Type
Content-Type: application/json
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=----FormBoundary
Le type MIME du body. Le serveur l'utilise pour savoir comment parser les donnees. Si tu envoies du JSON sans Content-Type: application/json, beaucoup de frameworks vont ignorer le body ou essayer de le parser comme du form-urlencoded.
Content-Length
Content-Length: 42
La taille du body en octets. Indispensable pour que le serveur sache quand le body se termine (sauf en chunked encoding).
Accept
Accept: application/json
Accept: text/html, application/xhtml+xml, */*;q=0.8
Ce que le client veut recevoir. Le q est le facteur de qualité (préférence) entre 0 et 1. */*;q=0.8 signifie "j'accepte n'importe quoi avec une préférence de 0.8." Le serveur utilise ca pour la negociation de contenu.
User-Agent
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
User-Agent: curl/8.4.0
User-Agent: MyApp/1.0
Identifie le client. Les User-Agent des navigateurs sont devenus des chaînes absurdes a cause de decennies de sniffing. Tout le monde pretend etre Mozilla parce que les serveurs servaient du contenu degrade aux clients non-Mozilla dans les annees 2000.
Pour tes API, mets un User-Agent descriptif. Ca aide énormément pour le debugging cote serveur.
Authorization
Authorization: Basic dXNlcjpwYXNz
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Les credentials d'authentification. Basic encode le login:password en base64 (pas de chiffrement, juste de l'encodage -- ne l'utilise jamais sans HTTPS). Bearer envoie un token opaque ou JWT.
Cookie
Cookie: session=abc123; theme=dark; lang=fr
Les cookies stockes par le navigateur pour ce domaine. Envoyes automatiquement a chaque requête. On en parle en détail dans l'article 07.
Accept-Encoding
Accept-Encoding: gzip, deflate, br
Les algorithmes de compression que le client supporte. Le serveur choisit un de ces algorithmes et l'indique dans Content-Encoding.
Accept-Language
Accept-Language: fr-FR, fr;q=0.9, en;q=0.8
Les langues preferees du client. Utilise pour la negociation de contenu linguistique. En pratique, peu de serveurs l'exploitent -- la plupart gerent la langue via l'URL ou un cookie.
If-None-Match / If-Modified-Since
If-None-Match: "abc123"
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT
Headers conditionnels pour le cache. "Renvoie-moi la ressource seulement si elle a change." Si elle n'a pas change, le serveur répond 304 sans body.
Les headers de réponse essentiels
Content-Type (réponse)
Content-Type: application/json; charset=utf-8
Meme header qu'en requête, cote réponse. Mets toujours le charset pour les contenus textuels. charset=utf-8 devrait etre ton reflexe.
Set-Cookie
Set-Cookie: session=xyz; Path=/; HttpOnly; Secure; SameSite=Lax
Le serveur demande au navigateur de stocker un cookie. Chaque Set-Cookie ne concerne qu'un seul cookie (contrairement au header Cookie qui les envoie tous d'un coup).
Cache-Control
Cache-Control: public, max-age=3600
Cache-Control: no-store
Cache-Control: no-cache, must-revalidate
La directive de cache la plus puissante. max-age=3600 : cache pendant 1 heure. no-store : ne cache jamais. no-cache : cache mais revalide a chaque utilisation (le nom est trompeur).
ETag
ETag: "abc123"
ETag: W/"abc123"
Un identifiant de version de la ressource. Le W/ indique un ETag "faible" (weak) -- la ressource est semantiquement équivalente meme si les octets ne sont pas identiques.
Location
Location: /api/users/42
Location: https://example.com/new-url
La cible d'une redirection (3xx) ou l'URL d'une ressource créée (201).
Vary
Vary: Accept-Encoding, Accept-Language
Dit aux caches : "la réponse depend de ces headers de requête." Si le cache a une version gzip et que le client demande du brotli, le cache ne doit pas servir la version gzip.
Vary: * signifie "la réponse est unique a chaque requête, ne cache jamais." C'est l'équivalent de no-store mais plus subtil.
Connection
Connection: keep-alive
Connection: close
En HTTP/1.1, keep-alive est le défaut : la connexion TCP reste ouverte pour les requêtes suivantes. close dit au serveur de fermer la connexion apres cette réponse. En HTTP/2, ce header est ignore (le multiplexage gere tout).
Transfer-Encoding
Transfer-Encoding: chunked
Le body arrive en morceaux. Detaille dans l'article 03.
Content-Encoding
Content-Encoding: gzip
Content-Encoding: br
Le body est compresse avec cet algorithme. Ne pas confondre avec Transfer-Encoding : Content-Encoding est une propriété du contenu lui-meme, Transfer-Encoding est une propriété du transfert.
Server
Server: nginx/1.25.3
Identifie le serveur. Comme je l'ai mentionne dans l'article 03, c'est souvent trop d'information. Masque la version en production.
X-Forwarded-For
X-Forwarded-For: 203.0.113.50, 70.41.3.18
L'IP d'origine du client quand la requête passe par un ou plusieurs proxies. Chaque proxy ajoute l'IP du hop précédent. Le premier IP est celui du client original.
Attention : ce header est trivial a falsifier. Ne l'utilise pour la sécurité que si tu fais confiance a tous tes proxies intermediaires. Le standard moderne est Forwarded mais X-Forwarded-For reste bien plus repandu.
Strict-Transport-Security (HSTS)
Strict-Transport-Security: max-age=31536000; includeSubDomains
Dit au navigateur : "ne me contacte plus jamais en HTTP, seulement en HTTPS, pendant un an." Protection contre le downgrade d'HTTPS vers HTTP.
X-Content-Type-Options
X-Content-Type-Options: nosniff
Desactive le content sniffing du navigateur. A mettre partout.
Headers custom : plus de X-
Pendant des annees, la convention etait de prefixer les headers custom par X- : X-Request-ID, X-Correlation-ID. En 2012, la RFC 6648 a déprécié cette convention. La raison : quand un header custom finit par devenir standard, on se retrouve avec deux noms (X-Forwarded-For et Forwarded).
Aujourd'hui, la recommandation est de ne plus utiliser le prefixe X-. Mais en pratique, la moitie de l'internet continue de le faire. X-Request-ID reste bien plus courant que Request-ID.
Mon approche pragmatique : pour les nouveaux headers, pas de X-. Pour les existants, garde ce que tout le monde utilise.
Sur paltemps.fr, on utilise Request-ID pour le tracing et X-Forwarded-For parce que c'est ce que nos proxies envoient.
Résumé
- Les headers sont des metadonnees clé-valeur, insensibles a la casse pour le nom
Hostest le seul header obligatoire en HTTP/1.1Content-Typeaveccharset=utf-8devrait etre un reflexeCache-Controlest plus puissant queExpires(qui est déprécié)X-Content-Type-Options: nosniffetStrict-Transport-Securitysur chaque réponse- Le prefixe
X-n'est plus recommande pour les nouveaux headers X-Forwarded-Forest facile a falsifier
Precedent : 05 - Les codes de statut Suivant : 07 - Les cookies