Comment fonctionne l’encodage d’URL
Une URL ne peut contenir qu’un petit ensemble de caractères ASCII, et certains ont un rôle : / sépare le chemin, ? commence la requête, & et = la découpent en paramètres, # commence le fragment. Tout autre caractère, ou l’un de ceux-ci utilisé comme simple donnée, s’écrit % suivi de deux chiffres hexadécimaux pour chacun de ses octets en UTF-8. On appelle cela l’encodage en pourcentage (RFC 3986).
espace → %20 (ou + dans les données de formulaire) & → %26 / → %2F é → C3 A9 → %C3%A9 € → E2 82 AC → %E2%82%AC
Les caractères à encoder dépendent de ce que vous encodez. Une valeur seule, comme un terme de recherche, doit aussi avoir / ? & = # encodés, sinon elle casserait l’URL où elle se trouve : c’est encodeURIComponent en JavaScript et urlencode en PHP. Une URL entière doit les garder, sinon ce n’est plus un lien : c’est encodeURI. Les formulaires HTML envoient les espaces sous la forme + au lieu de %20 (application/x-www-form-urlencoded) : un + dans une chaîne de requête signifie donc en général une espace.
Décoder fait l’inverse : chaque %XX devient un octet, et les octets sont lus comme de l’UTF-8. Le decodeURIComponent du navigateur dit seulement « URI malformed » quand quelque chose ne va pas. Cette page nomme la séquence et la désigne : un % sans deux chiffres hexadécimaux derrière, ou des octets qui ne sont pas de l’UTF-8 valide, ce qui signifie en général que le texte a été encodé en Latin-1.
Exemple
Le terme de recherche « vps hosting/€5 » en une seule valeur devient vps%20hosting%2F%E2%82%AC5 : l’espace est %20, la barre oblique %2F, et le signe euro, trois octets en UTF-8, devient %E2%82%AC. Avec « Écrire les espaces avec + » pour les données de formulaire, il devient vps+hosting%2F%E2%82%AC5. Décoder r%C3%A9sum%C3%A9 donne résumé, et décoder caf%E9 échoue à %E9, parce que c’est é en Latin-1, pas en UTF-8.
Questions
Qu’est-ce que l’encodage d’URL ?
L’encodage d’URL, ou encodage en pourcentage, écrit les caractères interdits dans une URL, ou qui y ont un sens spécial, sous la forme de % suivi de deux chiffres hexadécimaux pour chaque octet. L’espace devient %20, & devient %26 et é devient %C3%A9. Cela permet à n’importe quel texte de voyager sans risque dans un lien ou une chaîne de requête.
Quelle est la différence entre encodeURI et encodeURIComponent ?
encodeURI sert pour une adresse entière : il garde les caractères qui ont un rôle dans une URL, comme : / ? # & =, pour que le lien fonctionne encore. encodeURIComponent sert pour un seul morceau qui va dans une URL, comme la valeur d’un paramètre : il encode aussi ces caractères, de sorte qu’un & dans la valeur ne puisse pas commencer un nouveau paramètre. En cas de doute, encodez chaque valeur avec encodeURIComponent, puis assemblez-les.
L’espace doit-elle s’écrire %20 ou + ?
Les deux sont corrects, à des endroits différents. Dans le chemin d’une URL, l’espace doit être %20. Dans une chaîne de requête envoyée par un formulaire HTML (application/x-www-form-urlencoded), l’espace s’écrit +, et un vrai signe plus %2B. La plupart des serveurs lisent les deux dans une chaîne de requête. Pour décoder des données de formulaire, activez « Lire + comme une espace ».
Pourquoi ai-je l’erreur « URI malformed » au décodage ?
Soit un % n’est pas suivi de deux chiffres hexadécimaux, par exemple un simple « 100% » ou « %G1 », soit les octets %XX ne sont pas de l’UTF-8 valide, souvent parce que le texte a été encodé en Latin-1 (é en %E9) ou qu’un caractère sur plusieurs octets a été coupé. Cette page montre quelle séquence est fausse et où elle se trouve, pour que vous puissiez la corriger.
Comment décoder une URL en ligne de commande ou dans le code ?
En JavaScript : decodeURIComponent(s), après s.replace(/\+/g, ' ') pour des données de formulaire. En Python : urllib.parse.unquote(s), ou unquote_plus(s) pour des données de formulaire. En PHP : rawurldecode($s), ou urldecode($s), qui transforme aussi + en espace. Dans un shell avec Python installé : python3 -c "import sys, urllib.parse as u; print(u.unquote(sys.argv[1]))" 'r%C3%A9sum%C3%A9'.