Intermédiaire 8 min de lecture 25 janvier 2025

HTTP Content-Type: tout comprendre pour éviter les erreurs de format

Requêtes qui échouent en 415, JSON envoyé comme texte, fichiers téléchargés au lieu d'être affichés. Très souvent, l'en-tête HTTP Content-Type n'est pas correct ou absent. Voici comment il fonctionne, pourquoi il est crucial et comment le configurer sans se tromper.

Qu'est-ce que l'en-tête HTTP Content-Type ?

C'est l'en-tête qui décrit la nature du corps du message HTTP: type MIME, encodage de caractères, et paramètres associés.

Les éléments principaux à connaître :

1 Types MIME fondamentaux

Définissent le format du contenu envoyé ou reçu.

text/html
application/json
text/css, text/javascript (ou application/javascript)
image/png, image/jpeg, application/pdf

2 Paramètres de Content-Type

Affinent la description du contenu.

charset=UTF-8
boundary=----WebKitFormBoundaryXYZ
profile, format, charset=iso-8859-1 (héritage)

3 Formats de soumission côté client

Impactent la manière dont le serveur interprète le corps.

application/json
application/x-www-form-urlencoded
multipart/form-data
text/plain (rarement souhaité)

4 Cas techniques et subtilités

Points à surveiller en production :

Suffixes +json, +xml (ex: application/hal+json)
X-Content-Type-Options: nosniff
text/csv et séparateurs régionaux
Content negotiation (Accept vs Content-Type)

Problèmes classiques

415 Unsupported Media Type

Le serveur attend application/json mais reçoit text/plain ou form-urlencoded.

JSON servi en text/html

Les clients ne parsers pas, res.json() échoue et les navigateurs proposent un téléchargement.

Charset manquant ou incorrect

Accents cassés: text/html sans charset ou charset=iso-8859-1 non souhaité.

multipart/form-data mal formé

Paramètre boundary absent ou invalide; les fichiers ne sont pas parsés.

Exemple de problème courant :

# Requête incorrecte (envoi JSON sans le bon Content-Type)
curl -X POST https://api.exemple.com/users \
-H "Content-Type: text/plain" \
-d '{"name":"Ada"}' # ❌ 415 Unsupported Media Type
# Requête correcte
curl -X POST https://api.exemple.com/users \
-H "Content-Type: application/json; charset=utf-8" \
-d '{"name":"Ada"}' # ✅ 200 OK

Symptômes qui doivent vous alerter

🚨 Signaux d'alarme

!
Le navigateur télécharge un fichier au lieu d'afficher la page
!
res.json() lève une exception alors que la réponse semble JSON
!
Les accents s'affichent mal malgré UTF-8 côté base de données
!
CSS/JS bloqués avec "Refused to apply ... because its MIME type ('text/plain') is not a supported stylesheet/script"
!
Téléversement de fichiers: le serveur ne trouve aucun champ ou fichier

Comment les détecter

Solution recommandée : Vérificateur Content-Type

Un analyseur dédié affiche les en-têtes de vos requêtes/réponses, détecte les types incohérents, souligne les charsets manquants et les boundary invalides. Il met en évidence les divergences entre le corps et l'en-tête pour éviter les surprises.

✅ Détection automatique

MIME, charset, nosniff, erreurs 415/406

📊 Analyse complète

Vérification du corps vs Content-Type, suggestions de correction

🧹 Correction rapide

Modèles d'en-têtes prêts à l'emploi pour API et assets

💾 Export des requêtes

Snippets cURL/HTTPie corrects

Autres méthodes de détection

Outils du navigateur (DevTools)

Onglet Network → Response Headers → vérifier Content-Type et charset
Activer "Disable cache", tester avec X-Content-Type-Options: nosniff

En ligne de commande (Unix)

# Voir les en-têtes de réponse
curl -I https://exemple.com/ressource
# Vérifier Content-Type depuis une réponse complète
curl -i https://api.exemple.com/data | grep -i "^Content-Type"
# Déduire le type d'un fichier
file --mime-type --brief chemin/fichier.ext
# Requête JSON correcte avec HTTPie
http POST https://api.exemple.com/users name=Ada # envoie application/json

En code

JavaScript

fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json; charset=utf-8' },
  body: JSON.stringify({ name: 'Ada' })
}).then(r => r.headers.get('Content-Type'))

Python

import requests
r = requests.post('https://api.exemple.com/users', json={'name': 'Ada'})
r.headers.get('Content-Type')

PHP

header('Content-Type: application/json; charset=UTF-8');
echo json_encode(['status' => 'ok']);

Configurer correctement et prévenir

🚀 Mise en conformité rapide

Avant d'écrire des correctifs partout, vérifiez et mettez en place des en-têtes Content-Type adaptés à chaque route et chaque fichier statique.

Types MIME précis pour chaque réponse
Charset explicite pour text/* (UTF-8)
boundary correct pour multipart/form-data

Méthodes techniques avancées

🔧 Déclarer précisément

Envoyer charset=UTF-8 pour toutes les réponses text/*
Utiliser les suffixes +json et +xml lorsque pertinent
Envoyer X-Content-Type-Options: nosniff pour durcir la sécurité

🧹 Valider

Refuser côté serveur les types non supportés (415) avec message clair
Mapper correctement les extensions → types MIME pour les assets
Contrôler boundary et taille des parties pour multipart/form-data

⚙️ Automatiser

Tests d'intégration qui vérifient Content-Type et charset des réponses
CI avec cURL/HTTPie pour valider les en-têtes sur les routes clés
Configuration web serveur (Nginx/Apache) versionnée et testée

Checklist rapide

Chaque route API renvoie le Content-Type attendu
Charset UTF-8 explicite pour toutes les réponses text/*
CSS/JS servis avec le bon type et nosniff activé
JSON uniquement en application/json; pas de text/html
Téléversements: multipart/form-data avec boundary correct
Tests E2E vérifiant 415/406 et le type renvoyé

Conclusion

Content-Type pilote l'interprétation de vos requêtes et réponses. Un seul en-tête mal déclaré suffit à casser une intégration.

Déclarez clairement le type, ajoutez le charset quand nécessaire et automatisez les vérifications pour éviter les erreurs coûteuses.

Vérifiez vos en-têtes Content-Type maintenant

Utilisez un outil pour inspecter, valider et corriger Content-Type, charset et paramètres associés.

Analyser mes en-têtes