it-swarm.it

Quando dovresti usare l'escape invece di encodeURI/encodeURIComponent?

Quando si codifica una stringa di query da inviare a un server Web, quando si utilizza escape() e quando si utilizza encodeURI() o encodeURIComponent():

Usa fuga:

escape("% +&=");

OR

usa encodeURI ()/encodeURIComponent ()

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

encodeURIComponent("var1=value1&var2=value2");
1323
Adam

fuga()

Non usarlo! escape() è definito nella sezione B.2.1.2 escape e il testo introduttivo dell'allegato B afferma:

... Tutte le caratteristiche e i comportamenti linguistici specificati in questo allegato hanno una o più caratteristiche indesiderabili e in assenza di un uso legacy sarebbero rimossi da questa specifica. ...
... I programmatori non dovrebbero usare o assumere l'esistenza di queste caratteristiche e comportamenti quando scrivono un nuovo codice ECMAScript ....

Comportamento:

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

I caratteri speciali sono codificati con l'eccezione di: @ * _ + -. /

La forma esadecimale per i caratteri, il cui valore unitario di codice è 0xFF o inferiore, è una sequenza di escape a due cifre: %xx.

Per i caratteri con un'unità di codice maggiore, viene utilizzato il formato a quattro cifre %uxxxx. Questo non è consentito all'interno di una stringa di query (come definito in RFC3986 ):

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

Un segno di percentuale è consentito solo se è seguito direttamente da due caratteri esadecimali, la percentuale seguita da u non è consentita.

encodeURI ()

Usa encodeURI quando vuoi un URL funzionante. Effettua questa chiamata:

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

ottenere:

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

Non chiamare encodeURIComponent poiché distruggerebbe l'URL e restituirebbe

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

encodeURIComponent ()

Usa encodeURIComponent quando vuoi codificare il valore di un parametro URL.

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

Quindi puoi creare l'URL di cui hai bisogno:

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

E otterrai questo URL completo:

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

Si noti che encodeURIComponent non sfugge al carattere '. Un bug comune è usarlo per creare attributi html come href='MyUrl', che potrebbero subire un bug di injection. Se stai costruendo html da stringhe, usa " invece di ' per le virgolette degli attributi, oppure aggiungi un ulteriore livello di codifica (' può essere codificato come% 27).

Per ulteriori informazioni su questo tipo di codifica puoi controllare: http://en.wikipedia.org/wiki/Percent-encoding

1847
Arne Evertsson

La differenza tra encodeURI() e encodeURIComponent() sono esattamente 11 caratteri codificati da encodeURIComponent ma non da encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

Ho generato facilmente questa tabella con console.table in Google Chrome con questo codice:

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

411

Ho trovato questo articolo illuminante: Madness Javascript: analisi stringa di query

L'ho trovato quando stavo cercando di capire perché decodeURIComponent non stava decodificando '+' correttamente. Ecco un estratto:

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

encodeURIComponent non codifica -_.!~*'(), causando problemi nel postare dati su php nella stringa xml.

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

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

Puoi vedere, la citazione singola non è codificata . Per risolvere il problema, ho creato due funzioni per risolvere il problema nel mio progetto, per URL di codifica:

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

Per l'URL di decodifica:

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

encodeURI () - la funzione escape () è per l'escaping javascript, non HTTP.

37
Daniel Papasian

Piccola tabella di confronto 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
16
30thh

Raccomando di non usare uno di quei metodi così com'è. Scrivi la tua funzione che fa la cosa giusta.

MDN ha dato un buon esempio sulla codifica url mostrata di seguito.

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

Ricorda inoltre che tutti codificano diversi set di caratteri e selezionano quello che ti serve in modo appropriato. encodeURI () codifica meno caratteri di encodeURIComponent (), che codifica meno (e anche diversi, per i punti di dannyp) di escape ().

10
Pseudo Masochist

Ai fini della codifica javascript ha dato tre funzioni integrate -

  1. escape () - non codifica @*/+ Questo metodo è deprecato dopo ECMA 3 quindi dovrebbe essere evitato.

  2. encodeURI () - non codifica [email protected]#$&*()=:/,;?+' Suppone che l'URI sia un URI completo, quindi non codifica i caratteri riservati che hanno un significato speciale nell'URI . Questo metodo viene utilizzato quando l'intento è di convertire il completo URL invece di un segmento speciale di URL . Esempio - encodeURI('http://stackoverflow.com'); Darà - http://stackoverflow.com

  3. encodeURIComponent () - non codifica - _ . ! ~ * ' ( ) Questa funzione codifica un componente URI (Uniform Resource Identifier) ​​sostituendo ogni istanza di determinati caratteri con una, due, tre o quattro sequenze di escape che rappresentano la codifica UTF-8 del carattere. Questo metodo dovrebbe essere usato per convertire un componente di URL. Ad esempio, è necessario aggiungere un input utente Esempio - encodeURI('http://stackoverflow.com'); Restituirà - http% 3A% 2F% 2Fstackoverflow.com

Tutta questa codifica viene eseguita in UTF 8 i caratteri verranno convertiti in formato UTF-8. 

encodeURIComponent differisce da encodeURI in quanto codifica caratteri riservati e numero di segno # di encodeURI

6
Gaurav Tiwari

Ho scoperto che sperimentare con i vari metodi è un buon test di integrità anche dopo aver avuto una buona idea di quali siano i loro vari usi e capacità.

A tal fine ho trovato questo sito web estremamente utile per confermare i miei sospetti che sto facendo qualcosa in modo appropriato. Si è anche dimostrato utile per decodificare una stringa encodeURIComponent che può essere piuttosto difficile da interpretare. Un grande segnalibro da avere:

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

3
veeTrain

Ho questa funzione ...

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 risposta accettata è buona . Per estendere l'ultima parte:

Nota che encodeURIComponent non sfugge al carattere. Un comune bug è usarlo per creare attributi html come href = 'MyUrl', che potrebbe soffrire di un bug di iniezione. Se stai costruendo html da stringhe, usate "invece di" per le virgolette degli attributi, o aggiungete un ulteriore strato di codifica ('può essere codificato come% 27).

Se vuoi essere sicuro, la codifica per cento dei caratteri non riservati dovrebbe essere codificata. 

Puoi usare questo metodo per sfuggire a loro (source Mozilla )

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

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

Riscrittura moderna della risposta di @ 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
        )
)

Oppure, se puoi usare una tabella, sostituisci console.log con console.table (per l'output più carino).

1
ryanpcmcquen

Ispirato da il tavolo di Johann , ho deciso di allungare il tavolo. Volevo vedere quali caratteri ASCII vengono codificati.

 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 tabella mostra solo i caratteri codificati. Le celle vuote indicano che l'originale e i caratteri codificati sono gli stessi.


Solo per essere extra, sto aggiungendo un'altra tabella per urlencode() vs rawurlencode() . L'unica differenza sembra essere la codifica del carattere dello spazio.

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