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 reçoivent les requêtes GET réelles. C'est parce que -I envoie
une requête HEAD, et le middleware serveur qui traite uniquement les requêtes GET sera ignoré.
Contexte / Conditions déclenchantes
- Test des en-têtes de cache avec
curl -sIet affichage de valeurs inattendues - Middleware qui vérifie
method == GETavant de définir des en-têtes (courant dans le middleware de cache) - Les en-têtes apparaissent 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 gardes de méthode
Solution
Utilisez curl -s -D - -o /dev/null au lieu 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, ignore le corps
curl -s -D - -o /dev/null https://example.com/api/endpoint
Si vous avez besoin de seuls 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 possède une garde réservée au GET (ce qui est un comportement correct).
Exemple
Middleware Axum qui définit les en-têtes de cache uniquement 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 pouvant être cachées.
- La spec HTTP dit que les réponses HEAD DEVRAIENT inclure les mêmes en-têtes que GET, mais les implémentations de middleware souvent ne répliquent pas cela parce que HEAD est rarement utilisé par les CDN ou navigateurs pour les décisions de cache.
- Fastly, Cloudflare et les autres CDN envoient des requêtes GET aux origins, 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 le moyen le plus courant de vérifier les en-têtes.