Quand êtes-vous censé utiliser escape au lieu de encodeURI / encodeURIComponent ?
-
09-06-2019 - |
Question
Lors de l'encodage d'une chaîne de requête à envoyer à un serveur Web - quand utilisez-vous escape()
et quand utilises-tu encodeURI()
ou encodeURIComponent()
:
Utilisez l'échappement :
escape("% +&=");
OU
utilisez encodeURI() / encodeURIComponent()
encodeURI("http://www.google.com?var1=value1&var2=value2");
encodeURIComponent("var1=value1&var2=value2");
La solution
escape ()
Ne l'utilisez pas!
escape()
est défini dans la section B.2.1. 2 évasions et le texte d'introduction de l'annexe B dit:
... Toutes les caractéristiques et tous les comportements de langage spécifiés dans la présente annexe ont une ou plusieurs caractéristiques indésirables et, en l'absence d'utilisation héritée du passé, ils seraient supprimés de cette spécification. ...
... Les programmeurs ne devraient pas utiliser ou supposer l’existence de ces caractéristiques et comportements lors de l’écriture de nouveau code ECMAScript ....
Comportement:
https://developer.mozilla.org/ en-US / docs / Web / JavaScript / Référence / Global_Objects / escape
Les caractères spéciaux sont codés à l'exception de: @ * _ + -. /
La forme hexadécimale des caractères dont l'unité de code est égale ou inférieure à 0xFF est une séquence d'échappement à deux chiffres: %xx
.
Pour les caractères avec une unité de code supérieure, le format à quatre chiffres %uxxxx
est utilisé. Ceci n'est pas autorisé dans une chaîne de requête (comme défini dans la RFC3986 ):
query = *( pchar / "/" / "?" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
Un signe de pourcentage n'est autorisé que s'il est directement suivi de deux chiffres hexadécimaux, le pourcentage suivi de u
n'est pas autorisé.
encodeURI ()
Utilisez encodeURI lorsque vous souhaitez une URL fonctionnelle. Faites cet appel:
encodeURI("http://www.example.org/a file with spaces.html")
pour obtenir:
http://www.example.org/a%20file%20with%20spaces.html
N'appelez pas encodeURIComponent car cela détruirait l'URL et renverrait
http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html
encodeURIComponent ()
Utilisez encodeURIComponent lorsque vous souhaitez coder la valeur d'un paramètre d'URL.
var p1 = encodeURIComponent("http://example.org/?a=12&b=55")
Vous pouvez ensuite créer l'URL dont vous avez besoin:
var url = "http://example.net/?param1=" + p1 + "¶m2=99";
Et vous obtiendrez cette URL complète:
http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55¶m2=99
Notez qu'encodeURIComponent n'échappe pas au caractère '
. Un bogue courant consiste à l’utiliser pour créer des attributs HTML tels que href='MyUrl'
, qui pourraient subir un bogue d’injection. Si vous construisez du code HTML à partir de chaînes, utilisez "
au lieu de <=> pour les guillemets d'attributs, ou ajoutez une couche d'encodage supplémentaire (<=> peut être codé sous la forme% 27).
Pour plus d'informations sur ce type d'encodage, vous pouvez consulter: http: //en.wikipedia. org / wiki / Pourcentage d'encodage
Autres conseils
La différence entre encodeURI()
et encodeURIComponent()
correspond exactement à 11 caractères codés par encodeurURIComponent mais pas par encodeurURI:
J'ai généré ce tableau facilement avec console.table dans Google Chrome avec le code suivant:
.
var arr = [];
for(var i=0;i<256;i++) {
var char=String.fromCharCode(i);
if(encodeURI(char)!==encodeURIComponent(char)) {
arr.push({
character:char,
encodeURI:encodeURI(char),
encodeURIComponent:encodeURIComponent(char)
});
}
}
console.table(arr);
J'ai trouvé cet article éclairant: Javascript Madness: analyse de la chaîne de requête
Je l’ai trouvé lorsque j’essayais de comprendre pourquoi le décodageURIComponent ne décodait pas correctement le «+». Voici un extrait:
String: "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") = "A%20+%20B" Wrong!
encodeURI("A + B") = "A%20+%20B" Wrong!
encodeURIComponent("A + B") = "A%20%2B%20B" Acceptable, but strange
Encoded String: "A+%2B+B"
Expected Decoding: "A + B"
unescape("A+%2B+B") = "A+++B" Wrong!
decodeURI("A+%2B+B") = "A+++B" Wrong!
decodeURIComponent("A+%2B+B") = "A+++B" Wrong!
encodeURIComponent ne code pas -_.!~*'()
, ce qui pose un problème de publication de données sur php dans une chaîne xml.
Par exemple:
<xml><text x="100" y="150" value="It's a value with single quote" />
</xml>
Evasion générale avec encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E
Comme vous pouvez le constater, les guillemets simples ne sont pas codés. Pour résoudre le problème, j'ai créé deux fonctions pour résoudre le problème dans mon projet, pour URL de codage:
.function encodeData(s:String):String{
return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}
Pour l'URL de décodage:
function decodeData(s:String):String{
try{
return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
}catch (e:Error) {
}
return "";
}
encodeURI () - la fonction escape () sert à l'échappement javascript, pas à HTTP.
Petit tableau de comparaison Java, JavaScript et PHP.
1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode
char JAVA JavaScript --PHP---
[ ] + %20 %20 + %20
[!] %21 ! %21 %21 %21
[*] * * * %2A %2A
['] %27 ' %27 %27 %27
[(] %28 ( %28 %28 %28
[)] %29 ) %29 %29 %29
[;] %3B %3B %3B %3B %3B
[:] %3A %3A %3A %3A %3A
[@] %40 %40 @ %40 %40
[&] %26 %26 %26 %26 %26
[=] %3D %3D %3D %3D %3D
[+] %2B %2B + %2B %2B
[$] %24 %24 %24 %24 %24
[,] %2C %2C %2C %2C %2C
[/] %2F %2F / %2F %2F
[?] %3F %3F %3F %3F %3F
[#] %23 %23 %23 %23 %23
[[] %5B %5B %5B %5B %5B
[]] %5D %5D %5D %5D %5D
----------------------------------------
[~] %7E ~ %7E %7E ~
[-] - - - - -
[_] _ _ _ _ _
[%] %25 %25 %25 %25 %25
[\] %5C %5C %5C %5C %5C
----------------------------------------
char -JAVA- --JavaScript-- -----PHP------
[ä] %C3%A4 %C3%A4 %E4 %C3%A4 %C3%A4
[ф] %D1%84 %D1%84 %u0444 %D1%84 %D1%84
Je recommande de ne pas utiliser l’une de ces méthodes en l’état. Ecrivez votre propre fonction qui fait la bonne chose.
MDN a donné un bon exemple du codage d’URL présenté ci-dessous.
var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);
console.log(header);
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"
function encodeRFC5987ValueChars (str) {
return encodeURIComponent(str).
// Note that although RFC3986 reserves "!", RFC5987 does not,
// so we do not need to escape it
replace(/['()]/g, escape). // i.e., %27 %28 %29
replace(/\*/g, '%2A').
// The following are not required for percent-encoding per RFC5987,
// so we can allow for a little better readability over the wire: |`^
replace(/%(?:7C|60|5E)/g, unescape);
}
N'oubliez pas non plus qu'ils encodent tous différents jeux de caractères et sélectionnez celui dont vous avez besoin. encodeURI () encode moins de caractères que encodeURIComponent (), ce qui encode moins de caractères (mais aussi différents, du point de dannyp) à l'échappement ().
Aux fins de l'encodage, Javascript a fourni trois fonctions intégrées :
escape() - n'encode pas
@*/+
Cette méthode est obsolète après l'ECMA 3 et doit donc être évitée.encodeURI() - n'encode pas
~!@#$&*()=:/,;?+'
Il suppose que l'URI est un URI complet et n'encode donc pas les caractères réservés qui ont une signification particulière dans l'URI.Cette méthode est utilisée lorsque l'intention est de convertir l'URL complète au lieu d'un segment spécial d'URL.Exemple -encodeURI('http://stackoverflow.com');
va donner - http://stackoverflow.comencodeURIComponent() -n'encode pas
- _ . ! ~ * ' ( )
Cette fonction code un composant URI (Uniform Resource Identifier) en remplaçant chaque instance de certains caractères par une, deux, trois ou quatre séquences d'échappement représentant le codage UTF-8 du caractère.Cette méthode doit être utilisée pour convertir un composant d'URL.Par exemple, certaines entrées utilisateur doivent être annexées -encodeURI('http://stackoverflow.com');
donnera - http%3A%2F%2Fstackoverflow.com
Tout cet encodage est effectué en UTF 8 c'est à dire que les caractères seront convertis au format UTF-8.
encodeURIComponent diffère de encodeURI en ce sens qu'il code les caractères réservés et le signe numérique # de encodeURI
J'ai constaté qu'expérimenter différentes méthodes constituait un bon contrôle de la santé mentale même après avoir bien maîtrisé leurs utilisations et leurs capacités.
À cette fin, j’ai trouvé ce site extrêmement utile à confirmer mes soupçons que je fais quelque chose de manière appropriée. Il s’est également avéré utile pour décoder une chaîne encodée par l’URG qui peut être assez difficile à interpréter. Un excellent marque-page à avoir:
Inspiré par de Johann's tableau , j’ai décidé d’allonger le tableau. Je voulais voir quels caractères ASCII étaient encodés.
var ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var encoded = [];
ascii.split("").forEach(function (char) {
var obj = { char };
if (char != encodeURI(char))
obj.encodeURI = encodeURI(char);
if (char != encodeURIComponent(char))
obj.encodeURIComponent = encodeURIComponent(char);
if (obj.encodeURI || obj.encodeURIComponent)
encoded.push(obj);
});
console.table(encoded);
Le tableau montre uniquement les caractères encodés. Les cellules vides signifient que l'original et les caractères encodés sont les mêmes.
Juste pour être extra, j'ajoute une autre table pour urlencode()
vs rawurlencode()
. La seule différence semble être le codage du caractère d'espace.
<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
$obj = ["char" => $char];
if ($char != urlencode($char))
$obj["urlencode"] = urlencode($char);
if ($char != rawurlencode($char))
$obj["rawurlencode"] = rawurlencode($char);
if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
$encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>
J'ai cette fonction ...
var escapeURIparam = function(url) {
if (encodeURIComponent) url = encodeURIComponent(url);
else if (encodeURI) url = encodeURI(url);
else url = escape(url);
url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
return url;
};
La réponse acceptée est bonne. Pour prolonger la dernière partie:
Notez qu'encodeURIComponent n'échappe pas au caractère '. Un commun le bogue est de l’utiliser pour créer des attributs HTML tels que href = 'MyUrl', qui pourrait souffrir d'un bug d'injection. Si vous construisez du HTML à partir de chaînes, utilisez soit " au lieu de 'pour les citations d'attributs, ou ajoutez un couche supplémentaire de codage ('peut être codée sous la forme% 27).
Si vous voulez être prudent, encoder en pourcentage les caractères non conservés devrait également être encodé.
Vous pouvez utiliser cette méthode pour les échapper (source Mozilla )
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
// fixedEncodeURIComponent("'") --> "%27"
Réécriture moderne de la réponse de @ johann-echavarria:
console.log(
Array(256)
.fill()
.map((ignore, i) => String.fromCharCode(i))
.filter(
(char) =>
encodeURI(char) !== encodeURIComponent(char)
? {
character: char,
encodeURI: encodeURI(char),
encodeURIComponent: encodeURIComponent(char)
}
: false
)
)
Ou si vous pouvez utiliser une table, remplacez console.log
par console.table
(pour une sortie plus jolie).