Guide complet de l'encodage URL : qu'est-ce que l'encodage en pourcent
Chaque fois que vous cliquez sur un lien, soumettez un formulaire ou tapez une adresse Web, votre navigateur gère l'encodage URL en coulisses. Les chaînes mystérieuses composées de signes de pourcentage et de chiffres hexadécimaux que vous voyez dans les URL ne sont pas aléatoires ; elles constituent un mécanisme soigneusement conçu qui permet à Internet de fonctionner de manière fiable. Comprendre l'encodage URL est essentiel pour les développeurs Web, les concepteurs d'API et toute personne travaillant avec les technologies Web. Ce guide explique ce qu'est l'encodage URL, pourquoi il existe, comment il fonctionne et les implications de sécurité que vous devez connaître.
Qu'est-ce que l'encodage URL ?
L'encodage URL, officiellement appelé encodage en pourcent (percent-encoding), est un mécanisme défini dans la RFC 3986 qui convertit les caractères en un format pouvant être transmis en toute sécurité dans un identificateur de ressource uniforme (URI). La spécification URL n'autorise qu'un sous-ensemble de caractères ASCII à apparaître directement dans une URL. Tout caractère n'appartenant pas à cet ensemble autorisé doit être encodé sous la forme d'un signe de pourcent (%) suivi de deux chiffres hexadécimaux représentant la valeur d'octet du caractère.
< devient %3C, car le code ASCII de < est 60, soit 3C en hexadécimal.
Pourquoi l'encodage URL est nécessaire
Les URL ont une syntaxe spécifique qui utilise certains caractères comme séparateurs. Le point d'interrogation ? sépare le chemin de la chaîne de requête. Le symbole & sépare les paramètres de requête. Le signe = sépare le nom et la valeur du paramètre. La barre oblique / sépare les segments du chemin. Si ces caractères apparaissent dans les données transmises, ils seront interprétés à tort comme faisant partie de la structure de l'URL plutôt que du contenu.
Considérez ce qui se passe lorsqu'un utilisateur recherche « rock & roll » sur un site Web. Sans encodage, l'URL serait /search?q=rock & roll. Le navigateur interpréterait & comme un séparateur de paramètres de requête, divisant la requête en deux paramètres : q=rock et un deuxième paramètre nommé roll (sans valeur). L'encodage URL résout ce problème : /search?q=rock%20%26%20roll.
Fonctionnement de l'encodage en pourcent
Le processus d'encodage suit un algorithme simple défini par la spécification URI :
- Identifiez les caractères non réservés : les caractères A-Z, a-z, 0-9, -, ., _ et ~ sont non réservés. Ils n'ont jamais besoin d'être encodés et peuvent apparaître directement dans les URL.
- Identifiez les caractères réservés : les caractères :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ; et = sont réservés pour la syntaxe URL. Ils doivent être encodés lorsqu'ils sont utilisés comme données plutôt que comme séparateurs.
- Encodez tout le reste : tout caractère n'appartenant pas à l'ensemble non réservé ou réservé doit être encodé en pourcent. Cela inclut les espaces, les caractères de contrôle, les caractères non ASCII et tout caractère en dehors de la plage ASCII.
Processus d'encodage des caractères non ASCII
Les caractères non ASCII (comme les lettres accentuées, les caractères CJC et les émojis) nécessitent une étape supplémentaire. D'abord, le caractère est converti en sa séquence d'octets UTF-8. Ensuite, chaque octet est encodé individuellement en pourcent. Cela signifie qu'un seul caractère peut produire plusieurs triplets d'encodage en pourcent.
Par exemple, la séquence d'octets UTF-8 du symbole euro (€) est E2 82 AC. Une fois encodé en URL, il devient %E2%82%AC. Le caractère cyrillique « Д » a une séquence UTF-8 de D0 94, produisant %D0%94. L'émoji 😀 (face souriante) a une séquence UTF-8 de 4 octets, encodée en %F0%9F%98%80.
Caractères couramment encodés
Le tableau suivant montre les caractères encodés en URL les plus courants :
| Caractère | Encodage | Code ASCII | Raison |
|---|---|---|---|
| Espace | %20 | 32 (0x20) | Non autorisé dans les URL |
| ! | %21 | 33 (0x21) | Réservé (sous-séparateur) |
| # | %23 | 35 (0x23) | Réservé (séparateur de fragment) |
| $ | %24 | 36 (0x24) | Réservé (sous-séparateur) |
| & | %26 | 38 (0x26) | Réservé (séparateur de requête) |
| ' | %27 | 39 (0x27) | Réservé (sous-séparateur) |
| ( | %28 | 40 (0x28) | Réservé (sous-séparateur) |
| ) | %29 | 41 (0x29) | Réservé (sous-séparateur) |
| + | %2B | 43 (0x2B) | Réservé (espace dans les requêtes) |
| , | %2C | 44 (0x2C) | Réservé (sous-séparateur) |
| / | %2F | 47 (0x2F) | Réservé (séparateur de chemin) |
| : | %3A | 58 (0x3A) | Réservé (séparateur de protocole) |
| ; | %3B | 59 (0x3B) | Réservé (séparateur de paramètres) |
| = | %3D | 61 (0x3D) | Réservé (séparateur de valeur) |
| ? | %3F | 63 (0x3F) | Réservé (séparateur de requête) |
| @ | %40 | 64 (0x40) | Réservé (séparateur d'autorisation) |
| [ | %5B | 91 (0x5B) | Réservé (littéral IPv6) |
| ] | %5D | 93 (0x5D) | Réservé (littéral IPv6) |
Encodage URL vs encodage HTML
L'encodage URL et l'encodage d'entités HTML sont souvent confondus, mais leurs usages sont complètement différents et opèrent dans des contextes différents.
Encodage URL
L'encodage URL convertit les caractères au format %XX pour une transmission sécurisée dans les URL. Il est spécifié par la RFC 3986 et s'applique aux composants URL comme les chemins, les chaînes de requête et les fragments.
Encodage HTML
L'encodage HTML convertit les caractères en références d'entités comme &, < et > pour un rendu sécurisé dans les documents HTML. Il empêche le navigateur d'interpréter le contenu comme du balisage HTML. L'encodage HTML est spécifié par la spécification HTML.
Différences clés
| Aspect | Encodage URL | Encodage HTML |
|---|---|---|
| Contexte | URL et URI | Documents HTML |
| Format | %XX (pourcent + hexadécimal) | ou NNN; |
| < | %3C | < |
| Exemple pour & | %26 | & |
| Exemple pour " | %22 | " |
| Objectif | Transmission sécurisée dans les URL | Prévention de l'injection HTML |
| Spécification | RFC 3986 | HTML Living Standard |
(encodage HTML du &). Les deux sont valides, mais l'encodage URL du & est la pratique la plus correcte car elle préserve le sens voulu des données.
Encodage URL dans différents langages de programmation
Chaque langage de programmation majeur fournit des fonctions intégrées pour l'encodage et le décodage URL. Cependant, le comportement exact varie, et comprendre les différences est crucial pour éviter les erreurs.
JavaScript
JavaScript fournit trois fonctions d'encodage, chacune avec un comportement différent :
// encodeURI - encodes a complete URL
// Preserves: :, /, ?, #, &, =, +, @, ;, ,, !, ~, *, ', (, )
const url = encodeURI("https://example.com/search?q=hello world");
// Result: "https://example.com/search?q=hello%20world"
// encodeURIComponent - encodes a URL component
// Encodes ALL special characters including URL delimiters
const param = encodeURIComponent("price=100&discount=20");
// Result: "price%3D100%26discount%3D20"
// Never use escape() - it is deprecated
// It does not handle Unicode correctlyLa différence clé est que encodeURI conserve les caractères structurels de l'URL, tandis que encodeURIComponent encode tout. Utilisez encodeURI lorsque vous avez une URL complète, et encodeURIComponent lors de l'encodage d'une valeur de paramètre individuelle.
Python
from urllib.parse import quote, quote_plus, urlencode
# quote - standard URL encoding (spaces as %20)
encoded = quote("hello world&more")
# Result: "hello%20world%26more"
# quote_plus - spaces become + instead of %20
encoded_plus = quote_plus("hello world")
# Result: "hello+world"
# urlencode - encodes a dictionary as a query string
params = {"q": "hello world", "lang": "en"}
query = urlencode(params)
# Result: "q=hello+world&lang=en"PHP
// urlencode - spaces become +
$encoded = urlencode("hello world&more");
// Result: "hello+world%26more"
// rawurlencode - RFC 3986 compliant (spaces as %20)
$raw = rawurlencode("hello world&more");
// Result: "hello%20world%26more"Le caractère espace : %20 vs +
Le caractère espace a deux encodages courants, et il est important de comprendre quand utiliser chacun :
- %20 : encodage en pourcent standard défini par la RFC 3986. C'est l'encodage correct de l'espace dans les composants de chemin d'URL, toujours sûr.
- + (signe plus) : défini par le type média application/x-www-form-urlencoded, utilisé pour encoder les données de formulaire dans les chaînes de requête. Dans cet encodage, l'espace est remplacé par un signe plus, et le signe plus lui-même est encodé en %2B.
Cette distinction est importante car le décodage de + en espace n'est correct que dans le contexte des données application/x-www-form-urlencoded. Dans les composants de chemin d'URL, + est un signe plus littéral, pas un espace. La plupart des frameworks côté serveur gèrent correctement les chaînes de requête, mais cela peut entraîner des erreurs subtiles lors de l'encodage de chemins ou de l'utilisation de schémas URL personnalisés.
Implications de sécurité
L'encodage URL a des implications de sécurité importantes que tout développeur Web doit connaître.
Attaque par double encodage
Le double encodage se produit lorsque des données sont encodées en URL plusieurs fois. Un attaquant peut soumettre %2527, qui devient %27 au premier décodage, puis une apostrophe ' au deuxième décodage. Si un filtre de sécurité ne vérifie que le premier décodage, il manquera le caractère malveillant. Cela peut contourner la validation des entrées, les filtres XSS et les protections contre l'injection SQL.