curl -I envoie HEAD, pas GET — Piège du débogage des en-têtes
Problème
Lors du débogage des en-têtes de réponse HTTP avec curl -I ou curl -sI, la réponse peut afficher
des valeurs d'en-têtes différentes de celles que les vraies requêtes GET reçoivent. C'est parce que -I envoie
une requête HEAD, et les middlewares serveur qui ne traitent que les requêtes GET seront ignorés.
Contexte / Conditions de déclenchement
- Test des en-têtes de cache avec
curl -sIet observation de valeurs inattendues - Middleware qui vérifie
method == GETavant de définir des en-têtes (courant dans les middlewares de cache) - Les en-têtes semblent corrects dans les tests automatisés mais incorrects dans les tests curl manuels
- Les valeurs de
Cache-Control,Surrogate-ControlouSurrogate-Keyne correspondent pas aux attentes - Middleware Axum/Express/tout framework avec des gardes de méthode
Solution
Utilisez curl -s -D - -o /dev/null à la place de curl -I pour obtenir les en-têtes de réponse d'une requête GET :
# INCORRECT — envoie une requête HEAD, le middleware peut ignorer le traitement
curl -sI https://example.com/api/endpoint
# CORRECT — envoie une requête GET, affiche les en-têtes, rejette le corps
curl -s -D - -o /dev/null https://example.com/api/endpoint
Si vous avez besoin seulement d'en-têtes spécifiques :
curl -s -D - -o /dev/null https://example.com/api/endpoint | grep -iE 'cache-control|surrogate'
Vérification
Comparez la sortie des deux méthodes :
echo "=== HEAD (curl -I) ==="
curl -sI https://example.com/api/endpoint | grep cache-control
echo "=== GET (curl -D) ==="
curl -s -D - -o /dev/null https://example.com/api/endpoint | grep cache-control
Si les valeurs diffèrent, votre middleware a une garde réservée aux requêtes GET (ce qui est un comportement correct).
Exemple
Middleware Axum qui ne définit les en-têtes de cache que pour les requêtes GET :
async fn cache_middleware(request: Request, next: Next) -> Response {
let method = request.method().clone();
let mut response = next.run(request).await;
// Les requêtes HEAD ignorent ceci — curl -I ne verra pas ces en-têtes !
if method != Method::GET {
return response;
}
response.headers_mut().insert("cache-control", ...);
response.headers_mut().insert("surrogate-control", ...);
response
}
Notes
- Ce n'est PAS un bug — c'est un comportement correct. Les en-têtes de cache ne doivent s'appliquer qu'aux réponses GET cachées.
- La spécification HTTP dit que les réponses HEAD DEVRAIENT inclure les mêmes en-têtes que GET, mais les implémentations de middleware ne les répliquent souvent pas parce que HEAD est rarement utilisé par les CDN ou les navigateurs pour les décisions de cache.
- Fastly, Cloudflare et autres CDN envoient des requêtes GET aux origines, donc le comportement de cache est correct
même si
curl -Iaffiche des en-têtes différents. - Ce piège est particulièrement insidieux parce que
curl -Iest la façon la plus courante de vérifier les en-têtes.