web-development-kb-es.site

¿Cuándo se supone que debes usar escape en lugar de encodeURI/encodeURIComponent?

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");
1341
Adam

escapar()

¡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.

encodeURI ()

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

encodeURIComponent ()

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 + "&param2=99";

Y obtendrás esta URL completa:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=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

1864
Arne Evertsson

La diferencia entre encodeURI() y encodeURIComponent() son exactamente 11 caracteres codificados por encodeURIComponent pero no por encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

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);
416
Johann Echavarria

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!
46
Damien

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 "";
}
40

encodeURI (): la función de escape () es para el escape de JavaScript, no HTTP.

38
Daniel Papasian

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
17
30thh

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

11
Jerry Joseph

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 ().

10
Pseudo Masochist

Con el propósito de codificar javascript se han otorgado tres funciones incorporadas:

  1. escape (): no codifica @*/+ Este método está en desuso después del ECMA 3, por lo que debe evitarse.

  2. 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

  3. 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

7
Gaurav Tiwari

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:

http://www.the-art-of-web.com/javascript/escape/

3
veeTrain

Inspirado en la mesa de Johann , he decidido extender la mesa. Quería ver qué ASCII caracteres se codifican.

 screenshot of console.table

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.

 screenshot of console.table

<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>
2
akinuri

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;
};
1
molokoloco

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"
1
Michael

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).

1
ryanpcmcquen