Pergunta

Ao codificar uma string de consulta para ser enviada a um servidor web - quando você usa escape() e quando você usa encodeURI() ou encodeURIComponent():

Usar escape:

escape("% +&=");

OU

use encodeURI() / encodeURIComponent()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");
Foi útil?

Solução

escapar()

Não use isso!escape() é definido na seção B.2.1.2 fuga e a texto de introdução do Anexo B diz:

...Todos os recursos e comportamentos de linguagem especificados neste anexo possuem uma ou mais características indesejáveis ​​e, na ausência de uso legado, seriam removidos desta especificação....
...Os programadores não devem usar ou presumir a existência desses recursos e comportamentos ao escrever novo código ECMAScript....

Comportamento:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

Caracteres especiais são codificados com exceção de:@*_+-./

A forma hexadecimal para caracteres cujo valor da unidade de código é 0xFF ou menos, é uma sequência de escape de dois dígitos: %xx.

Para caracteres com unidade de código maior, o formato de quatro dígitos %uxxxx é usado.Isso não é permitido em uma string de consulta (conforme definido em RFC3986):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

Um sinal de porcentagem só é permitido se for seguido diretamente por dois dígitos hexadecimais, porcentagem seguida por u não é permitido.

codificarURI()

Use encodeURI quando quiser um URL funcional.Faça esta ligação:

encodeURI("http://www.example.org/a file with spaces.html")

obter:

http://www.example.org/a%20file%20with%20spaces.html

Não chame encodeURIComponent, pois isso destruiria o URL e retornaria

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

codificarURIComponent()

Use encodeURIComponent quando desejar codificar o valor de um parâmetro de URL.

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

Então você pode criar o URL necessário:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

E você obterá este URL completo:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

Observe que encodeURIComponent não escapa do ' personagem.Um bug comum é usá-lo para criar atributos HTML como href='MyUrl', que pode sofrer um bug de injeção.Se você estiver construindo HTML a partir de strings, use " em vez de ' para aspas de atributos ou adicione uma camada extra de codificação (' pode ser codificado como% 27).

Para mais informações sobre este tipo de codificação você pode verificar: http://en.wikipedia.org/wiki/Percent-encoding

Outras dicas

A diferença entre encodeURI() e encodeURIComponent() são exatamente 11 caracteres codificados por encodeURIComponent, mas não por encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

Eu gerei essa tabela facilmente com console.tabela no Google Chrome com 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);

Achei este artigo esclarecedor:Loucura Javascript:Análise de string de consulta

Eu descobri quando estava tentando entender por que decodeURIComponent não estava decodificando '+' corretamente.Aqui está um extrato:

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 não codifica -_.!~*'(), causando problema na postagem de dados para php na string xml.

Por exemplo:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

Fuga geral com 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

Você pode ver que aspas simples não estão codificadas.Para resolver o problema criei duas funções para resolver o problema no meu projeto, para URL de codificação:

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 URL de decodificação:

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() - a função escape() é para escape de javascript, não para HTTP.

Pequena tabela de comparação Java vs.Javascript versusPHP.

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

Eu recomendo não usar um desses métodos como está.Escreva sua própria função que faça a coisa certa.

MDN deu um bom exemplo de codificação de URL mostrado abaixo.

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

Lembre-se também de que todos eles codificam diferentes conjuntos de caracteres e selecione aquele que você precisa de forma adequada.encodeURI() codifica menos caracteres do que encodeURIComponent(), que codifica menos caracteres (e também diferentes, na opinião de dannyp) do que escape().

Para fins de codificação, o javascript forneceu três funções integradas -

  1. escape() - não codifica @*/+Este método está obsoleto após o ECMA 3, portanto deve ser evitado.

  2. encodeURI() - não codifica ~!@#$&*()=:/,;?+'Ele assume que o URI é um URI completo, portanto não codifica caracteres reservados que tenham significado especial no URI.Este método é usado quando a intenção é converter o URL completo em vez de algum segmento especial de URL.Exemplo - encodeURI('http://stackoverflow.com');darei - http://stackoverflow.com

  3. encodeURIComponent() -não codifica - _ . ! ~ * ' ( )Esta função codifica um componente URI (Uniform Resource Identifier), substituindo cada instância de determinados caracteres por uma, duas, três ou quatro sequências de escape que representam a codificação UTF-8 do caractere.Este método deve ser usado para converter um componente de URL.Por exemplo, alguma entrada do usuário precisa ser anexada por exemplo - encodeURI('http://stackoverflow.com');vai dar - http%3A%2F%2Fstackoverflow.com

Toda essa codificação é realizada em UTF 8 ou seja, os caracteres serão convertidos para o formato UTF-8.

encodeURIComponent difere de encodeURI porque codifica caracteres reservados e sinal numérico # de encodeURI

Descobri que experimentar os vários métodos é uma boa verificação de sanidade, mesmo depois de ter uma boa noção de quais são seus vários usos e capacidades.

Para esse fim eu descobri esse site extremamente útil para confirmar minhas suspeitas de que estou fazendo algo de maneira adequada.Também se mostrou útil para decodificar uma string encodeURIComponent que pode ser bastante desafiadora de interpretar.Um ótimo marcador para ter:

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

Inspirado por mesa de João, decidi estender a tabela.Eu queria ver quais caracteres ASCII são codificados.

screenshot of console.table

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

A tabela mostra apenas os caracteres codificados.Células vazias significam que os caracteres originais e codificados são iguais.


Só para complementar, estou adicionando outra tabela para urlencode() contra rawurlencode().A única diferença parece ser a codificação do caractere de espaço.

screenshot of console.table

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

eu tenho essa função...

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

A resposta aceita é boa.Para estender a última parte:

Observe que encodeURIComponent não escapa do caractere '.Um bug comum é usá -lo para criar atributos HTML como href = 'myurl', o que pode sofrer um bug de injeção.Se você estiver construindo html a partir de strings, use "em vez de" para citações de atributo ou adicione uma camada extra de codificação ("pode ​​ser codificada como %27).

Se você quiser estar do lado seguro, porcentagem de codificação de caracteres não reservados também deve ser codificado.

Você pode usar este método para escapar deles (fonte Mozilla)

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

// fixedEncodeURIComponent("'") --> "%27"

Reescrita moderna da resposta 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 se você puder usar uma tabela, substitua console.log com console.table (para uma saída mais bonita).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top