Français

Outils de développement · Encodeur et décodeur d'URL

Plus contre %20 : l'historique de l'application/x-www-form-urlencoded

· Contexte

encodage d'URL formulaires HTML normes http

Envoi du formulaire affichant l'espace de codage du signe plus dans la chaîne de requête par rapport à vingt pour cent dans la syntaxe URI
Illustration vectorielle originale de ToolAcre

Les formulaires codent un espace comme + alors que la norme URI indique %20, et la raison est historique. Cet article retrace la convention depuis les premiers formulaires HTML jusqu'à la définition actuelle du WHATWG et explique pourquoi elle n'a jamais disparu.

Plus versus %20 : pourquoi les formulaires et les URI encodent les espaces différemment

Formulaires HTML soumis sous forme d'espaces d'encodage GET sous forme de signes plus dans la chaîne de requête. Le même espace devient %20 dans les URL suivant la RFC 3986. Les deux sont corrects car ils suivent des normes différentes. Les champs de formulaire contenant des espaces deviennent nom=valeur+avec+espaces dans l'encodage du formulaire mais %20 dans RFC 3986. La distinction de plus de vingt pour cent indique quelle norme s'applique à vos données.

L'encodage du formulaire utilise le plus pour les espaces comme convention historique de la RFC 1866 (1995), la définition originale de soumission de formulaire HTML 2.0. GET demande des espaces codés sous forme de signes plus, en réservant le plus pour le littéral + codé en %2B. Cette règle s'appliquait uniquement à l'application/x-www-form-urlencoded, et non à la syntaxe URI générale. Des milliards de frameworks de serveurs sont devenus dépendants de cette convention. Les tests des deux montrent des différences évidentes : le mode formulaire produit un plus ; Le mode URI produit %20. L'encodeur et le décodeur d'URL proposent les deux modes pour comparer directement.

Premiers formulaires HTML et soumission GET – comment l'encodage du formulaire a été défini et pourquoi + a été choisi

RFC 1866 (1995) a défini la soumission d'un formulaire où les espaces deviennent plus et le littéral plus devient %2B. Cela s'appliquait uniquement à l'application/x-www-form-urlencoded. RFC 3986 spécifiée %20 pour la syntaxe générale de l'URI. Deux normes cohabitaient volontairement.

RFC 2396 a clarifié les jeux de caractères de manière plus rigoureuse que les normes antérieures. Il a formalisé les caractères réservés servant la structure URI par rapport aux caractères non réservés comme données littérales. Les organismes de normalisation codifient le comportement des navigateurs et des proxys à mesure de leur évolution. La RFC 3986 est venue plus tard sans changer le comportement de codage, clarifiant simplement la notation. Tous les navigateurs actuels standardisent le codage UTF-8. Les formulaires HTML via les boutons de soumission envoient le format application/x-www-form-urlencoded avec un plus pour les espaces. La construction manuelle de l'URI utilise %20. Comprendre les deux normes évite les surprises d’intégration.

RFC 1866 et spécifications HTML ultérieures — où la règle a été écrite et comment elle s'écarte de la syntaxe URI

WHATWG URL Standard spécifie que URLSearchParams.toString() produit une sortie application/x-www-form-urlencoded avec des signes plus pour les espaces. Le constructeur d'URL encode en pourcentage conformément à la RFC 3986. Navigateur naviguant vers l'URL avec les codes d'espace %20 ; formulaire soumis sous forme d'encodage GET plus. Ces outils fondamentalement différents répondent à des objectifs différents. L'encodeURIComponent manuel donne %20 pour les espaces – style RFC 3986. Formulaires soumis à la même URL envoyer plus. Les serveurs analysant les soumissions de formulaires attendent plus ; la réception de %20 provoque des échecs silencieux des paramètres.

Les tests des deux révèlent les hypothèses côté serveur dont vous dépendez. JavaScript URLSearchParams offre un codage sécurisé de type formulaire, ainsi qu'une complexité accrue. Construisez URLSearchParams, ajoutez des entrées, appelez toString() pour obtenir application/x-www-form-urlencoded avec le plus approprié. Vous pouvez également créer des chaînes de requête avec encodeURIComponent ; vous obtenez RFC 3986 %20. Ne mélangez jamais les approches. Les chaînes de requête avec manual plus et encodeURIComponent créent une ambiguïté. Les récepteurs ne peuvent pas distinguer si plus signifie espace ou plus littéral. Les approches standard sont gérées de manière cohérente.

La norme URL aujourd'hui - application/x-www-form-urlencoded en tant que sérialiseur distinct avec ses propres règles

JSON Les API rejettent généralement plus comme espace, attendant %20 selon RFC 3986. Les clients qui envoient plus échouent silencieusement : les paramètres disparaissent. Tester les API avec les deux encodages révèle quelle norme elles acceptent. URLSearchParams en JavaScript gère l'encodage des formulaires. L'encodeur et le décodeur d'URL produisent la RFC 3986 %20.

La soumission du formulaire HTML gère automatiquement l'encodage. Votre infrastructure de serveur décide quelles règles s'appliquent. Rails, Django, PHP traitent tous automatiquement le plus comme un espace dans les données du formulaire reçu. Mais la création manuelle de chaînes de requête pour les mêmes points de terminaison est extrêmement importante. Un plus téléchargé crée une ambiguïté. La conformité aux spécifications et le comportement réel du serveur divergent légèrement. Documentez la norme attendue par vos points de terminaison. Testez les deux styles d’encodage. Le code défensif gère les deux avec élégance.

Exemple concret : le même champ de formulaire vu comme une chaîne de requête et comme un corps de requête — avec + à un endroit et %20 à un autre

JavaScript URLSearchParams applique le codage de formulaire : l'espace devient un plus, et non %20. new URLSearchParams({q: "hello world"}) produit "q=hello+world", et non "q=hello%20world". Il s'agit d'une règle d'application historique/x-www-form-urlencoded intégrée spécifiquement à JavaScript. Mais transmettre cette chaîne sous forme de requête brute à une nouvelle URL conserve plus comme plus ; seul URLSearchParams le décode sous forme d'espace. Le constructeur est fidèle à ce qu'il voit. La différence du signe plus provoque des bugs courants lors du mélange incorrect des fonctions.

Le constructeur d'URL et encodeURIComponent sont des outils différents. encodeURIComponent encode presque tout sauf les lettres, chiffres et - _ non réservés. ! ~ *' ( ). Cela ne suppose aucun contexte. Le constructeur d'URL analyse l'URL réelle et applique les règles WHATWG par composant. encodeURIComponent transforme "hello/world" en "hello%2Fworld" ; la nouvelle URL considère les barres obliques comme séparateurs de chemin. Même entrée, sortie différente. Utilisez encodeURIComponent lors de la création d'URL en concaténant des éléments. Utilisez URLSearchParams ou le constructeur d'URL pour les URL complètes ou partielles.

Pourquoi cela ne peut pas être corrigé : des décennies de serveurs et de clients qui dépendent du comportement actuel

Les règles de codage en pourcentage ont évolué de la RFC 1738 (1994) à la RFC 2396 (1998) jusqu'à la RFC 3986 (2005). Chaque génération a clarifié les ambiguïtés. La RFC 1738 était conservatrice, traitant les caractères comme dangereux car les premiers sites Web avaient une prise en charge limitée des caractères. Déploiements standardisés sur UTF-8, les implémentations sont devenues cohérentes. Les normes ultérieures ont assoupli les restrictions sur les caractères prouvant leur sécurité dans tous les systèmes. Consensus moderne : UTF-8 partout. Les organismes de normalisation maintiennent farouchement la rétrocompatibilité. Pour y remédier, il faudrait une coordination mondiale – impossible après trois décennies. Deux normes cohabitent volontairement.

Les tests avec plus et %20 révèlent les hypothèses du serveur. Les journaux du serveur montrent ce que les clients envoient. Les formulaires utilisent plus ; les URL manuelles utilisent %20. Choisissez par contexte et suivez la documentation de l'API.

Ce que cela ne couvre pas : carrosseries en plusieurs parties/form-data et JSON

Le test des deux encodages révèle le comportement du serveur. Envoyez a+b dans les deux sens. De nombreux serveurs de production attendent un codage de formulaire ; les API les plus récentes attendent %20. Votre choix dépend des attentes du destinataire. URLSearchParams gère l'encodage des formulaires ; encodeURIComponent gère le codage RFC.

Ne combinez jamais les méthodes de codage. La valeur codée avec encodeURIComponent %2B puis transmise à URLSearchParams est doublement codée en %252B. Le décodage donne une fois %2B au lieu de plus. Le caractère devient une chaîne littérale de pourcentage deux à six plutôt qu'un signe plus. Vérifiez les étapes intermédiaires de votre processus de construction. L'encodage se produit exactement une fois par valeur seulement. Documentez la norme de codage utilisée par votre pipeline. Testez avec des caractères spéciaux, notamment plus, espace, esperluette.

À retenir : deux normes, toutes deux correctes dans leur contexte – comment l'encodeur et le décodeur d'URL vous donnent le formulaire RFC 3986, avec %20 pour les espaces, afin que vous sachiez lequel vous regardez

Le partage plus contre vingt n'est pas un bug à corriger. Il s’agit d’un artefact historique de normes résolvant différemment des problèmes distincts. Pour y remédier, il faudrait une coordination mondiale – impossible après trente ans. Les organismes de normalisation ne brisent pas le Web de manière rétroactive. La RFC 3986, les règles de formulaire et la construction de l'URL du navigateur ont chacune des normes et des raisons. Le codage de formulaire RFC 1866 et le codage URI RFC 3986 servent différentes couches. Encodez délibérément en connaissant votre standard. Testez avec des charges utiles réalistes.

Choisissez l'encodage par contexte. Les formulaires utilisent plus selon les normes HTML. Les URI manuels utilisent %20 selon RFC 3986. Les API précisent à quoi s'attendre ; suivez la documentation ou testez les deux. L'encodeur et le décodeur d'URL affichent RFC 3986. Besoin d'encodage de formulaire ? URLSearchParams fait cela. L'outil ne mélange pas les encodages ; comprendre les normes évite les surprises. L'incohérence d'encodage entre les couches entraîne une perte subtile de paramètres, une troncature et une corruption des données. Les deux normes sont correctes dans leur domaine. Appliquer délibérément et documenter.