Si je veux créer une URL à l'aide d'une variable, j'ai deux choix pour encoder la chaîne. urlencode()
et rawurlencode()
.
Quelles sont exactement les différences et laquelle est préférée?
php
urlencode
url-encoding
Gary Willoughby
la source
la source
rawurlencode
. Vous rencontrerez rarement un système qui s'étouffe lorsque des espaces sont codés en tant que%20
, alors que les systèmes qui s'étouffent sur des espaces codés en+
sont plus courants.Réponses:
Cela dépendra de votre objectif. Si l'interopérabilité avec d'autres systèmes est importante, il semble que le rawurlencode soit la voie à suivre. La seule exception concerne les systèmes hérités qui s'attendent à ce que la chaîne de requête suive le style de codage de forme des espaces codés comme + au lieu de% 20 (auquel cas vous avez besoin du code url).
rawurlencode suit RFC 1738 avant PHP 5.3.0 et RFC 3986 après (voir http://us2.php.net/manual/en/function.rawurlencode.php )
Remarque sur RFC 3986 vs 1738. rawurlencode avant php 5.3 encodait le caractère tilde (
~
) selon RFC 1738. Cependant, depuis PHP 5.3, rawurlencode suit RFC 3986 qui ne nécessite pas d'encodage de caractères tilde.urlencode code les espaces sous forme de signes plus (pas comme
%20
dans rawurlencode) (voir http://us2.php.net/manual/en/function.urlencode.php )Cela correspond à la définition de l'application / x-www-form-urlencoded dans la RFC 1866 .
Lecture supplémentaire:
Vous pouvez également souhaiter voir la discussion sur http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .
En outre, la RFC 2396 vaut le détour. La RFC 2396 définit une syntaxe URI valide. La partie principale qui nous intéresse est de 3.4 Composant de requête:
Comme vous pouvez le voir, le
+
est un caractère réservé dans la chaîne de requête et devrait donc être codé selon RFC 3986 (comme dans rawurlencode).la source
La preuve est dans le code source de PHP.
Je vais vous guider à travers un processus rapide sur la façon de découvrir ce genre de chose par vous-même à l'avenir à tout moment. Soyez avec moi, il y aura beaucoup de code source C que vous pouvez parcourir (je l'explique). Si vous voulez rafraîchir certains C, un bon endroit pour commencer est notre wiki SO .
Téléchargez la source (ou utilisez http://lxr.php.net/ pour la parcourir en ligne), grep tous les fichiers pour le nom de la fonction, vous trouverez quelque chose comme ceci:
PHP 5.3.6 ( le plus récent au moment de la rédaction) décrit les deux fonctions dans leur code natif C dans le fichier url.c .
RawUrlEncode ()
UrlEncode ()
D'accord, alors qu'est-ce qui est différent ici?
Ils appellent tous deux essentiellement deux fonctions internes différentes respectivement: php_raw_url_encode et php_url_encode
Alors allez chercher ces fonctions!
Regardons php_raw_url_encode
Et bien sûr, php_url_encode:
Un peu de connaissances avant d'aller de l'avant, EBCDIC est un autre jeu de caractères , similaire à ASCII, mais un concurrent total. PHP tente de gérer les deux. Mais en gros, cela signifie que l'octet EBCDIC 0x4c n'est pas
L
en ASCII, c'est en fait un<
. Je suis sûr que vous voyez la confusion ici.Ces deux fonctions gèrent EBCDIC si le serveur Web l'a défini.
En outre, ils utilisent tous les deux un tableau de recherche de caractères (pensez au type de chaîne)
hexchars
pour obtenir certaines valeurs, le tableau est décrit comme tel:Au-delà de cela, les fonctions sont vraiment différentes, et je vais les expliquer en ASCII et EBCDIC.
Différences en ASCII:
URLENCODE:
+
signe à la chaîne de sortie.isalnum(c)
), et n'est pas non plus et_
,-
ou un.
caractère, alors nous, sortons un%
signe à la position 0 du tableau, faisons unhexchars
tableau pour rechercher leos_toascii
tableau ( un tableau d' Apache qui traduit char en code hexadécimal) pour la clé dec
(le caractère actuel), nous décalons ensuite bit à droite de 4, affectons cette valeur au caractère 1, et à la position 2 nous attribuons la même recherche, sauf que nous préformons un logique et pour voir si la valeur est 15 (0xF), et retourner un 1 dans ce cas, ou un 0 sinon. À la fin, vous vous retrouverez avec quelque chose d'encodé._-.
caractères, il sort exactement ce que c'est.RAWURLENCODE:
Remarque: De nombreux programmeurs n'ont probablement jamais vu d'itération de boucle for de cette façon, c'est quelque peu hack et non la convention standard utilisée avec la plupart des boucles for, faites attention, il attribue
x
ety
vérifie la sortie enlen
atteignant 0 et incrémente les deuxx
ety
. Je sais, ce n'est pas ce que vous attendez, mais c'est un code valide.str
._-.
caractères, et s'il ne l'est pas, nous faisons presque la même affectation qu'avec URLENCODE où il préforme les recherches, cependant, nous incrémentons différemment, en utilisanty++
plutôt queto[1]
, c'est parce que le les cordes sont construites de différentes manières, mais atteignent le même objectif à la fin de toute façon.\0
octet.Différences:
\0
octet à la chaîne, RawUrlEncode le fait (cela peut être un point discutable)Ils itèrent fondamentalement différemment, on attribue un signe + en cas d'ASCII 20.
Différences dans EBCDIC:
URLENCODE:
0
, à l'exception d'être un.
ou-
, OU inférieurA
mais supérieur à caractère9
, OU supérieurZ
et inférieur àa
mais non a_
. OU supérieur àz
(ouais, EBCDIC est un peu foiré de travailler avec). S'il correspond à l'un d'entre eux, effectuez une recherche similaire à celle trouvée dans la version ASCII (cela ne nécessite tout simplement pas de recherche dans os_toascii).RAWURLENCODE:
z
, elle exclut~
du codage d'URL.\0
octet à la chaîne avant le retour.Grand résumé
~
que UrlEncode ne fait pas ( il s'agit d'un problème signalé ). Il convient de noter que ASCII et EBCDIC 0x20 sont tous deux des espaces.+
, RawUrlEncode crée un espace%20
via des recherches de tableau.Avertissement: je n'ai pas touché C depuis des années et je n'ai pas regardé EBCDIC depuis très très longtemps. Si je me trompe quelque part, faites le moi savoir.
Implémentations suggérées
Sur la base de tout cela, le rawurlencode est la voie à suivre la plupart du temps. Comme vous le voyez dans la réponse de Jonathan Fingland, respectez-la dans la plupart des cas. Il traite du schéma moderne pour les composants URI, où comme l'urlencode fait les choses à l'ancienne, où + signifiait «espace».
Si vous essayez de convertir entre l'ancien format et les nouveaux formats, assurez-vous que votre code ne se gâte pas et ne transforme pas quelque chose qui est un signe + décodé en espace en double-encodant accidentellement, ou des scénarios similaires "oops" autour de ce espace / 20% / + problème.
Si vous travaillez sur un système plus ancien avec un logiciel plus ancien qui ne préfère pas le nouveau format, restez avec le code url, cependant, je pense que% 20 sera en fait rétrocompatible, comme sous l'ancien standard% 20 fonctionnait, n'était tout simplement pas préféré. Essayez-le si vous êtes prêt à jouer, faites-nous savoir comment cela a fonctionné pour vous.
Fondamentalement, vous devriez vous en tenir au raw, à moins que votre système EBCDIC ne vous déteste vraiment. La plupart des programmeurs ne rencontreront jamais EBCDIC sur un système fabriqué après l'an 2000, peut-être même 1990 (c'est poussant, mais toujours probable à mon avis).
la source
les rendements
tandis que
les rendements
La différence étant le
asd%20asd
vsasd+asd
urlencode diffère de RFC 1738 par l'encodage des espaces au
+
lieu de%20
la source
Une raison pratique de choisir l'un plutôt que l'autre est que vous allez utiliser le résultat dans un autre environnement, par exemple JavaScript.
En PHP
urlencode('test 1')
retourne'test+1'
toutrawurlencode('test 1')
retourne'test%201'
comme résultat.Mais si vous avez besoin de "décoder" cela en JavaScript en utilisant la fonction decodeURI () ,
decodeURI("test+1")
vous obtiendrez"test+1"
alors que vousdecodeURI("test%201")
obtiendrez"test 1"
le résultat.En d'autres termes, l'espace ("") encodé par urlencode en plus ("+") en PHP ne sera pas correctement décodé par decodeURI en JavaScript.
Dans de tels cas, la fonction PHP rawurlencode doit être utilisée.
la source
json_encode
etJSON.parse
à cette fin.Je crois que les espaces doivent être codés comme:
%20
lorsqu'il est utilisé dans le composant de chemin d'URL+
lorsqu'il est utilisé à l'intérieur d'un composant de chaîne de requête d'URL ou de données de formulaire (voir 17.13.4 Types de contenu de formulaire )L'exemple suivant montre l'utilisation correcte de
rawurlencode
eturlencode
:Production:
Que se passe-t-il si vous codez le chemin d'accès et interrogez les composants de chaîne dans l'autre sens? Pour l'exemple suivant:
latest+songs
au lieu delatest songs
q
contiendralady gaga
la source
q
contiendralady gaga
" Que contient-il d'autre sinon? Le paramètre de requêteq
semble avoir la même valeur transmise au$_GET
tableau indépendamment de l'utilisationrawurlencode
ouurlencode
de PHP 5.2+. Bien que,urlencode
code dans leapplication/x-www-form-urlencoded
format qui est par défaut pour les demandes GET, je vais donc avec votre approche. +1+
et%20
sont décodés comme espace lorsqu'ils sont utilisés dans des chaînes de requête.La différence réside dans les valeurs de retour, c'est-à-dire:
urlencode () :
rawurlencode () :
Les deux sont très similaires, mais le dernier (rawurlencode) remplacera les espaces par un '%' et deux chiffres hexadécimaux, ce qui convient pour coder des mots de passe ou autres, où un '+' n'est pas par exemple:
la source
1. Quelles sont exactement les différences et
La seule différence réside dans le traitement des espaces:
urlencode - basé sur une implémentation héritée convertit les espaces en +
rawurlencode - basé sur RFC 1738 traduit les espaces en% 20
La raison de la différence est que + est réservé et valide (non codé) dans les URL.
2. lequel est préféré?
Assez juste, j'ai une stratégie simple que je suis en train de prendre ces décisions que je partagerai avec vous dans l'espoir que cela puisse aider.
Je pense que c'était la spécification HTTP / 1.1 RFC 2616 qui appelait à des " applications tolérantes "
Face à de telles questions, la meilleure stratégie consiste toujours à consommer autant que possible et à produire ce qui est conforme aux normes.
Donc, mon conseil est d'utiliser
rawurlencode
pour produire des chaînes encodées conformes aux normes RFC 1738 et d'utiliserurldecode
pour être rétrocompatible et accueillir tout ce que vous pourriez rencontrer.Maintenant, vous pouvez simplement me croire sur parole, mais prouvons que nous le ferons ...
Il semblerait que PHP ait exactement cela à l'esprit, même si je n'ai jamais rencontré personne refusant l'un des deux formats, je ne peux pas penser à une meilleure stratégie à adopter comme stratégie de facto, n'est-ce pas?
nJoy!
la source
la source
Espaces codés comme
%20
vs.+
La plus grande raison que j'ai vue d'utiliser
rawurlencode()
dans la plupart des cas est parce queurlencode
code les espaces de texte en tant que+
(signes plus) où lesrawurlencode
code comme les plus courants%20
:J'ai spécifiquement vu certains points de terminaison d'API qui acceptent les requêtes de texte codées s'attendre à voir
%20
un espace et, par conséquent, échouer si un signe plus est utilisé à la place. Évidemment, cela va différer entre les implémentations d'API et votre kilométrage peut varier.la source
Je crois que l'urlencode est pour les paramètres de requête, tandis que le rawurlencode est pour les segments de chemin. Cela est principalement dû aux
%20
segments de chemin vs+
aux paramètres de requête. Voir cette réponse qui parle des espaces: quand encoder l'espace en plus (+) ou% 20?Cependant,
%20
il fonctionne désormais également dans les paramètres de requête, c'est pourquoi le rawurlencode est toujours plus sûr. Cependant, le signe plus a tendance à être utilisé lorsque l'expérience utilisateur de l'édition et de la lisibilité des paramètres de requête est importante.Notez que cela signifie
rawurldecode
ne pas décoder+
en espaces ( http://au2.php.net/manual/en/function.rawurldecode.php ). C'est pourquoi $ _GET est toujours automatiquement transmisurldecode
, ce qui signifie que+
et%20
sont tous deux décodés en espaces.Si vous souhaitez que le codage et le décodage soient cohérents entre les entrées et les sorties et que vous avez choisi de toujours utiliser
+
et non%20
pour les paramètres de requête, celaurlencode
convient pour les paramètres de requête (clé et valeur).La conclusion est:
Segments de chemin - utilisez toujours rawurlencode / rawurldecode
Paramètres de requête - pour le décodage, utilisez toujours urldecode (fait automatiquement), pour le codage, rawurlencode ou urlencode est correct, choisissez-en un pour être cohérent, en particulier lorsque vous comparez des URL.
la source
simple * rawurlencode le chemin - chemin est la partie avant le "?" - les espaces doivent être encodés en tant que% 20 * encoder la chaîne de requête en url - La chaîne de requête est la partie après le "?" -les espaces sont mieux encodés car "+" = rawurlencode est généralement plus compatible
la source