¿Cuándo se supone que debes usar escape en lugar de encodeURI/encodeURIComponent?
-
09-06-2019 - |
Pregunta
Al codificar una cadena de consulta para enviarla a un servidor web, ¿cuándo se utiliza? escape()
y cuando usas encodeURI()
o encodeURIComponent()
:
Utilice escape:
escape("% +&=");
O
utilizar encodeURI() / encodeURIComponent()
encodeURI("http://www.google.com?var1=value1&var2=value2");
encodeURIComponent("var1=value1&var2=value2");
Solución
escapar()
¡No lo uses!escape()
se define en la sección B.2.1.2 escapar y el texto de introducción del anexo B dice:
...Todas las características y comportamientos del lenguaje especificados en este anexo tienen una o más características indeseables y, en ausencia de un uso heredado, se eliminarían de esta especificación....
...Los programadores no deben utilizar ni asumir la existencia de estas características y comportamientos al escribir nuevo código ECMAScript....
Comportamiento:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape
Los caracteres especiales están codificados a excepción de:@*_+-./
La forma hexadecimal de los caracteres cuyo valor de unidad de código es 0xFF o menos es una secuencia de escape de dos dígitos: %xx
.
Para caracteres con una unidad de código mayor, el formato de cuatro dígitos %uxxxx
se utiliza.Esto no está permitido dentro de una cadena de consulta (como se define en RFC3986):
query = *( pchar / "/" / "?" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
Sólo se permite un signo de porcentaje si va seguido directamente de dos dígitos hexadecimales, porcentaje seguido de u
No se permite.
codificarURI()
Utilice encodeURI cuando desee una URL que funcione.Haz esta llamada:
encodeURI("http://www.example.org/a file with spaces.html")
Llegar:
http://www.example.org/a%20file%20with%20spaces.html
No llame a encodeURIComponent ya que destruiría la URL y devolvería
http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html
codificarURIComponente()
Utilice encodeURIComponent cuando desee codificar el valor de un parámetro de URL.
var p1 = encodeURIComponent("http://example.org/?a=12&b=55")
Luego puedes crear la URL que necesitas:
var url = "http://example.net/?param1=" + p1 + "¶m2=99";
Y obtendrás esta URL completa:
http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55¶m2=99
Tenga en cuenta que encodeURIComponent no escapa al '
personaje.Un error común es usarlo para crear atributos html como href='MyUrl'
, que podría sufrir un error de inyección.Si está construyendo html a partir de cadenas, utilice "
en lugar de '
para comillas de atributos, o agregue una capa adicional de codificación ('
se puede codificar como %27).
Para más información sobre este tipo de codificación puedes consultar: http://en.wikipedia.org/wiki/Percent-encoding
Otros consejos
La diferencia entre encodeURI()
y encodeURIComponent()
son exactamente 11 caracteres codificados por encodeURIComponent pero no por encodeURI:
Generé esta tabla fácilmente con mesa de consola en Google Chrome con este código:
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);
Este artículo me pareció esclarecedor:Locura de Javascript:Análisis de cadenas de consulta
Lo encontré cuando intentaba comprender por qué decodeURIComponent no decodificaba '+' correctamente.Aquí hay un extracto:
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 no codifica -_.!~*'()
, causando problemas al publicar datos en php en una cadena xml.
Por ejemplo:
<xml><text x="100" y="150" value="It's a value with single quote" />
</xml>
fuga general con 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
Puede ver que las comillas simples no están codificadas.Para resolver el problema, creé dos funciones para resolver el problema en mi proyecto, para Codificar URL:
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");
}
Para decodificar URL:
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 función escape() es para escapar de JavaScript, no de HTTP.
Pequeña tabla comparativa Java vs.JavaScript vs.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
Recomiendo no utilizar uno de esos métodos tal como está.Escribe tu propia función que haga lo correcto.
MDN ha dado un buen ejemplo sobre la codificación de URL que se muestra a continuación.
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);
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
Recuerde también que todos codifican diferentes conjuntos de caracteres y seleccione el que necesite de forma adecuada.encodeURI() codifica menos caracteres que encodeURIComponent(), que codifica menos caracteres (y también diferentes, según Dannyp) que escape().
Con el fin de codificar, JavaScript ha proporcionado tres funciones incorporadas:
escape() - no codifica
@*/+
Este método está en desuso después de ECMA 3, por lo que debe evitarse.encodeURI() - no codifica
~!@#$&*()=:/,;?+'
Se supone que el URI es un URI completo, por lo que no codifica caracteres reservados que tengan un significado especial en el URI.Este método se utiliza cuando la intención es convertir la URL completa en lugar de algún segmento especial de URL.Ejemplo -encodeURI('http://stackoverflow.com');
daré - http://stackoverflow.comencodeURIComponent() -no codifica
- _ . ! ~ * ' ( )
Esta función codifica un componente de Identificador uniforme de recursos (URI) reemplazando cada instancia de ciertos caracteres por una, dos, tres o cuatro secuencias de escape que representan la codificación UTF-8 del carácter.Este método debe usarse para convertir un componente de la URL.Por ejemplo, se debe un ejemplo de entrada del usuario -encodeURI('http://stackoverflow.com');
dará - http%3A%2F%2Fstackoverflow.com
Toda esta codificación se realiza en UTF 8, es decir, los caracteres se convertirán al formato UTF-8.
encodeURIComponent se diferencia de encodeURI en que codifica caracteres reservados y el signo numérico # de encodeURI
Descubrí que experimentar con los diversos métodos es una buena prueba de cordura incluso después de tener un buen conocimiento de cuáles son sus diversos usos y capacidades.
Con ese fin he encontrado este sitio web extremadamente útil para confirmar mis sospechas de que estoy haciendo algo correctamente.También ha demostrado ser útil para decodificar una cadena encodeURIComponent que puede ser bastante difícil de interpretar.Un gran marcador para tener:
Inspirado por La mesa de Juan, he decidido ampliar la mesa.Quería ver qué caracteres ASCII se codifican.
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);
La tabla muestra solo los caracteres codificados.Las celdas vacías significan que los caracteres originales y codificados son los mismos.
Solo para ser extra, estoy agregando otra tabla para urlencode()
vs rawurlencode()
.La única diferencia parece ser la codificación del carácter espacial.
<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>
tengo esta funcion...
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 respuesta aceptada es buena.Para ampliar en la última parte:
Tenga en cuenta que encodeURIComponent no escapa del carácter '.Un error común es usarlo para crear atributos HTML como href = 'myurl', que podría sufrir un error de inyección.Si está construyendo HTML a partir de cadenas, use "en lugar de 'para citas de atributos, o agregue una capa adicional de codificación (' se puede codificar como %27).
Si quieres estar seguro, porcentaje de codificación de caracteres no reservados También debe codificarse.
Puedes usar este método para escapar de ellos (fuente Mozilla)
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
// fixedEncodeURIComponent("'") --> "%27"
Reescritura moderna de la respuesta 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
)
)
O si puedes usar una mesa, reemplaza console.log
con console.table
(para una salida más bonita).