Quando dovresti usare escape invece di encodeURI / encodeURIComponent?


1392

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("% +&=");

O

usa encodeURI () / encodeURIComponent ()

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

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

111
Vale la pena sottolineare che nonencodeURIComponent("var1=value1&var2=value2") è il tipico caso d'uso. Quell'esempio codificherà e , che probabilmente non è quello che era previsto! viene in genere applicato separatamente solo al valore in ciascuna coppia di valori chiave (la parte dopo ciascuna ). =&encodeURIComponent=
Timothy Shields,

3
devi fare qualcosa per la chiave? Cosa succede se contiene un =? (è anche possibile?)
Mala,

3
@Mala Sono ancora nuovo nella programmazione web in generale, ma quello che ho usato nella mia esperienza limitata è codificare la chiave e il valore separatamente, assicurandomi che '=' rimanga: var params = encodeURIComponent(key) + '=' + encodeURIComponent(value);- Forse qualcun altro conosce un modo migliore.
nedshares,

1
@nedshares Ci stavo giocando, ma per quanto ne so la chiave non sembra essere codificata ... almeno non allo stesso modo. Forse è contro le specifiche avere un = nella chiave?
Mala,

1
Vale anche la pena sottolineare che le recenti implementazioni JavaScript forniscono le interfacce di livello superiore URL e URLSearchParams per manipolare gli URL e le loro stringhe di query.
Bart Robinson il

Risposte:


1914

fuga()

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

... Tutte le caratteristiche del linguaggio e i comportamenti specificati in questo allegato hanno una o più caratteristiche indesiderabili e in assenza di un uso legacy verrebbero 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 ad eccezione di: @ * _ + -. /

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

Per i caratteri con un'unità di codice maggiore, %uxxxxviene utilizzato il formato a quattro cifre . Ciò 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 cifre esadecimali, mentre la percentuale seguita da unon è consentita.

encodeURI ()

Usa encodeURI quando desideri un URL funzionante. Fai 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 tornerebbe

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

encodeURIComponent ()

Utilizzare encodeURIComponent quando si desidera codificare il valore di un parametro URL.

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

Quindi è possibile creare l'URL necessario:

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

Nota che encodeURIComponent non sfugge al 'personaggio. Un bug comune è usarlo per creare attributi html come href='MyUrl', che potrebbero subire un bug di iniezione. Se stai costruendo html dalle stringhe, usa "invece che '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, è possibile consultare: http://en.wikipedia.org/wiki/Percent-encoding


31
@Francois, a seconda del server ricevente, potrebbe non decodificare correttamente il modo in cui escape codifica i caratteri ASCII o non ASCII superiori come: âềểễếệêềểễếệ Ad esempio, la classe FieldStorage di Python non decodificherà correttamente la stringa sopra se codificata bye escape.
Ray,

22
@Francois escape () codifica i 128 caratteri ASCII inferiori ad eccezione di lettere, cifre e *@-_+./ mentre unescape () è l'inverso di escape (). Per quanto ne so, sono funzioni legacy progettate per la codifica degli URL e sono ancora implementate solo per la compatibilità con le versioni precedenti. In genere, non dovrebbero essere utilizzati a meno che non interagiscano con un'app / un servizio Web / ecc. Progettati per loro.
Anthony DiSanti,

3
A meno che ovviamente non si stia tentando di passare un URL come componente URI, nel qual caso chiamare encodeURIComponent.
Tom,

4
Perché non gestisce la singola citazione?
Eric,

11
@Eric Non codifica la virgoletta singola, poiché la virgoletta singola è un carattere completamente valido che si verifica all'interno di un URI ( RFC-3986 ). Il problema si verifica quando si incorpora un URI in HTML, in cui la virgoletta singola non è un carattere valido. Ne consegue quindi che gli URI dovrebbero anche essere "codificati in HTML" (che sostituiranno 'con ') prima di essere inseriti in un documento HTML.
Lee,

441

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

Tabella con le dieci differenze tra encodeURI e encodeURIComponent

Ho generato questa tabella facilmente 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);


Questo browser non dipende?
Pacerier,

4
@bladnman encodeURI e encodeURIComponent dovrebbero funzionare in questo modo in tutti i principali browser. Puoi testare il codice sopra in Chrome e Firefox come entrambi support console.table. In altri browser (inclusi Firefox e Chrome) è possibile utilizzare il seguente codice:var arr=[]; for(var i=0;i<256;i++){var char=String.fromCharCode(i); if(encodeURI(char)!==encodeURIComponent(char)) console.log("character: "+char + " | encodeURI: " +encodeURI(char) + " |encodeURIComponent: " + encodeURIComponent(char) ) }
Johann Echavarria,

1
Intendevo @Pacerier :)
Johann Echavarria,

@Pacerier dovrebbe essere identico in vari browser a meno che le specifiche originali non siano troppo ambigue ... vedi anche stackoverflow.com/questions/4407599/…
Christophe Roussy,

2
DEVO AGGIORNARE QUESTI TEMPI PIÙ! Sfortunatamente può solo una volta votare.
Ramazan Polat,

46

Ho trovato questo articolo illuminante: Javascript Madness: Query String Parsing

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!

11
L'articolo a cui ti colleghi contiene molte sciocchezze. Mi sembra che lo stesso autore non abbia capito a cosa servano correttamente le funzioni ...
Christoph

2
@Christoph Mi sembra tutto ragionevole. In particolare, concordo con lui sul fatto che encodeURIsembra utile solo in un caso abbastanza oscuro e che non è necessario che esista. Ho alcune differenze di opinione con lui, ma non vedo nulla di completamente falso o idiota lì dentro. Cosa pensi esattamente di essere senza senso?
Mark Amery,

1
L' enctypeattributo FORMdell'elemento specifica il tipo di contenuto utilizzato per codificare il set di dati del modulo per l'invio al server. application / x-www-form-urlencoded Questo è il tipo di contenuto predefinito. I moduli inviati con questo tipo di contenuto devono essere codificati come segue: [...] i caratteri spaziali sono sostituiti da `` + ', e i [...] caratteri non alfanumerici sono sostituiti da `% HH', [...] Rif: HTML4 settembre
cychoi

2
encodeURIComponent ('A + B'). sostituisci (/ \% 20 / g, '+') + '\ n' + decodificaURIComponent ("A +% 2B + B" .replace (/ \ + / g, '% 20' ));
Zlatin Zlatev,

39

encodeURIComponent non codifica -_.!~*'(), causando problemi nella pubblicazione di dati in 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 virgoletta singola non è codificata. Per risolvere il problema ho creato due funzioni per risolvere il problema nel mio progetto, per l'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 "";
}

5
Inoltre, non esegue il segno # (cancelletto / hash / numero), che è% 23.
xr280xr,

1
@ xr280xr Cosa intendi? encodeURIComponent codifica # in% 23 (forse no nel 2014?)
David Balažic,

38

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


Se ho un URL come questo: var url = "http://kuler-api.adobe.com/rss/get.cfm?startIndex=0&itemsPerPage=20&timeSpan=0&listType=rating"... E voglio accedervi tramite l'API Ajax di Google, in questo modo: var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;... allora devo usare escape(url). encodeURI(url)non funziona con parametri come quello sembra.
Lance Pollard,

15
dovresti usare ecnodeURIComponent (url)
Ustaman Sangat

2
Tutte e 3 le funzioni hanno i loro problemi. È meglio creare la tua funzione che fa il lavoro.
Jerry Joseph,

17

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

12

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

MDN ha fornito un buon esempio di 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


1
che risposta eccezionale (se compatibile con Chrome Edge e Firefox senza errori)
yan bellavance,

10

Ricorda inoltre che tutti codificano diversi set di caratteri e selezionano quello che ti serve in modo appropriato. encodeURI () codifica un numero inferiore di caratteri rispetto a encodeURIComponent (), che codifica un numero minore di caratteri (e anche diverso, a livello di dannyp) rispetto a escape ().


8

Ai fini della codifica javascript ha fornito tre funzioni integrate:

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

  2. encodeURI()- non codifica ~!@#$&*()=:/,;?+' Presuppone 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 si intende convertire l'URL completo anziché 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 deve essere utilizzato per convertire un componente di URL. Ad esempio, è necessario aggiungere alcuni input dell'utente Esempio - encodeURIComponent('http://stackoverflow.com'); fornirà - http% 3A% 2F% 2Fstackoverflow.com

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

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


3

Ho scoperto che sperimentare con i vari metodi è un buon controllo di integrità anche dopo avere una buona conoscenza di quali sono i loro vari usi e capacità.

A tal fine, ho trovato questo sito estremamente utile per confermare i miei sospetti che sto facendo qualcosa di appropriato. Si è anche rivelato utile per decodificare una stringa codificata da COMPUENT che può essere piuttosto difficile da interpretare. Un ottimo segnalibro per avere:

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


2

La risposta accettata è buona. Per estendere l'ultima parte:

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

Se vuoi essere al sicuro, codifica in percentuale i caratteri senza prenotazione prenotazione.

Puoi usare questo metodo per sfuggirli (fonte Mozilla )

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

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

2

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

O se è possibile utilizzare una tabella, sostituirla console.logcon console.table(per l'output più bello).


2

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

screenshot di console.table

La tabella mostra solo i caratteri codificati. Le celle vuote indicano che i caratteri originali e codificati sono uguali.


Giusto per essere in più, sto aggiungendo un altro tavolo per urlencode()vs rawurlencode(). L'unica differenza sembra essere la codifica del carattere spaziale.

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

1

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

4
@ChristianVielma escape () è obsoleto ma non fa mai riferimento a w3schools.com. vedi w3fools.com
Jerry Joseph,

4
@Christian Vielma - Alcuni ritengono che il materiale di riferimento di W3Schools sia meno controverso e utile . Non tutti sono d'accordo sul fatto che W3Schools non dovrebbe mai essere referenziato.
DavidRR,

2
W3Schools ha un brutto rap. Sicuramente non sono sempre precisi, ma poi ho trovato molti post sul blog che sono decisamente sbagliati. Per me a volte è un ottimo punto di partenza solo per imparare un po 'della terminologia e poi mi tuffo un po' più in profondità con altre risorse. La cosa più importante è che una singola risorsa non dovrebbe mai essere biblica quando si tratta di questo tipo di cose.
Ryandlf,

Sembra che @molokoloco abbia scritto questa funzione come fallback alle versioni in cui encodeURInon esiste ma escapeesiste.
SOFe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.