Al codificar una cadena de consulta para enviarla a un servidor web, ¿cuándo usa escape()
y cuándo usa encodeURI()
o encodeURIComponent()
?
Utilizar escape
escape("% +&=");
OR
utilizar encodeURI ()/encodeURIComponent ()
encodeURI("http://www.google.com?var1=value1&var2=value2");
encodeURIComponent("var1=value1&var2=value2");
¡No lo uses! escape()
se define en la sección B.2.1.2 escape y el texto de introducción del Anexo B dice:
... Todas las características y comportamientos de lenguaje especificados en este anexo tienen una o más características indeseables y, en ausencia de un uso heredado, se eliminarán de esta especificación. ...
... Los programadores no deben usar o asumir la existencia de estas características y comportamientos al escribir un nuevo código ECMAScript ...
Comportamiento:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape
Los caracteres especiales se codifican con la excepción de: @ * _ + -. /
La forma hexadecimal para los caracteres, cuyo valor de unidad de código es 0xFF o menos, es una secuencia de escape de dos dígitos: %xx
.
Para los caracteres con una unidad de código mayor, se utiliza el formato de cuatro dígitos %uxxxx
. 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 = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
Solo se permite un signo de porcentaje si está seguido directamente por dos dígitos hexadecimales, no se permite el porcentaje seguido de u
.
Utilice encodeURI cuando desee una URL de trabajo. Haga 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
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 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 las citas de atributos, o agregue una capa adicional de codificación ('
puede codificarse como% 27).
Para obtener más información sobre este tipo de codificación, puede consultar: http://en.wikipedia.org/wiki/Percent-encoding
La diferencia entre encodeURI()
y encodeURIComponent()
son exactamente 11 caracteres codificados por encodeURIComponent pero no por encodeURI:
Generé esta tabla fácilmente con console.table 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);
Encontré este artículo esclarecedor: Javascript Madness: Query String Parsing
Lo encontré cuando estaba tratando de entender y por qué decodeURIComponent no estaba decodificando '+' 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>
Escape 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
Se puede ver, comilla simple no está codificada. Para resolver el problema, creé dos funciones para resolver el problema en mi proyecto, para la codificación de 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 de escape () es para el escape de JavaScript, no HTTP.
Pequeña tabla de comparación 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 usar uno de esos métodos como está. Escribe tu propia función que hace lo correcto.
MDN ha dado un buen ejemplo de 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
Además, recuerde que todos ellos codifican diferentes conjuntos de caracteres y seleccione el que necesita de manera adecuada. encodeURI () codifica menos caracteres que encodeURIComponent (), que codifica menos (y también diferentes, puntos de dannyp) que escapan ().
Con el propósito de codificar javascript se han otorgado tres funciones incorporadas:
escape (): no codifica @*/+
Este método está en desuso después del ECMA 3, por lo que debe evitarse.
encodeURI (): no codifica [email protected]#$&*()=:/,;?+'
Supone que el URI es un URI completo, por lo que no codifica los caracteres reservados que tienen un significado especial en el URI. Este método se usa cuando la intención es convertir la URL completa en lugar de algún segmento especial de la URL. Ejemplo: encodeURI('http://stackoverflow.com');
dará - http://stackoverflow.com
encodeURIComponent () -no codifica - _ . ! ~ * ' ( )
Esta función codifica un componente de Identificador Uniforme de Recursos (URI) al reemplazar 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 se debe utilizar para convertir un componente de URL. Por ejemplo, es necesario adjuntar algunos comentarios del usuario. Ejemplo: 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 en formato UTF-8.
encodeURIComponent difiere de encodeURI en que codifica los caracteres reservados y el número de signo Número de encodeURI
Descubrí que experimentar con los diversos métodos es una buena comprobación de la cordura, incluso después de tener un buen manejo de cuáles son sus diversos usos y capacidades.
Hacia ese fin he encontrado este sitio web extremadamente útil para confirmar mis sospechas de que estoy haciendo algo apropiadamente. También ha demostrado ser útil para decodificar una cadena codificada enURIComponent que puede ser bastante difícil de interpretar. Un gran marcador para tener:
Inspirado en la mesa de Johann , he decidido extender la mesa. Quería ver qué ASCII caracteres se codifican.
var ascii = " !\"#$%&'()*+,-./0123456789:;<=>[email protected][\\]^_`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 el original y los caracteres 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:;<=>[email protected][\\]^_`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 función ...
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 (' puede codificarse como% 27).
Si desea estar en el lado seguro, el porcentaje de codificación de caracteres no reservados también debe codificarse.
Puede 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 puede usar una tabla, reemplace console.log
con console.table
(para la salida más bonita).