Wann sollten Sie Escape anstelle von encodeURI / encodeURIComponent verwenden?

1392

Wenn Sie eine Abfragezeichenfolge codieren, die an einen Webserver gesendet werden soll - wann verwenden Sie escape()und wann verwenden Sie encodeURI()oder encodeURIComponent():

Verwenden Sie Escape:

escape("% +&=");

ODER

benutze encodeURI () / encodeURIComponent ()

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

encodeURIComponent("var1=value1&var2=value2");
Adam
quelle
111
Es ist erwähnenswert, dass encodeURIComponent("var1=value1&var2=value2")ist nicht der typische Anwendungsfall. Dieses Beispiel wird das =und codieren &, was wahrscheinlich nicht beabsichtigt ist! encodeURIComponentwird normalerweise separat nur auf den Wert in jedem Schlüsselwertpaar (dem Teil nach jedem =) angewendet .
Timothy Shields
3
Müssen Sie etwas mit dem Schlüssel tun? Was ist, wenn es ein = enthält? (Ist das überhaupt möglich?)
Mala
3
@Mala Ich bin noch neu in der Webprogrammierung im Allgemeinen, aber was ich in meiner begrenzten Erfahrung verwendet habe, ist, den Schlüssel und den Wert getrennt zu codieren, um sicherzustellen, dass das '=' bleibt: var params = encodeURIComponent(key) + '=' + encodeURIComponent(value);- Vielleicht kennt jemand anderes einen besseren Weg.
Nedshares
1
@nedshares Ich habe damit gespielt, aber soweit ich das beurteilen kann, scheint der Schlüssel nicht codiert zu sein ... zumindest nicht auf die gleiche Weise. Vielleicht ist es gegen die Spezifikation, ein = im Schlüssel zu haben?
Mala
1
Erwähnenswert ist auch , dass neuere JavaScript-Implementierungen die übergeordneten Schnittstellen URL und URLSearchParams zum Bearbeiten von URLs und deren Abfragezeichenfolgen bereitstellen .
Bart Robinson

Antworten:

1914

Flucht()

Benutze es nicht! escape()ist in Abschnitt B.2.1.2 Flucht definiert und der Einführungstext von Anhang B lautet:

... Alle in diesem Anhang angegebenen Sprachmerkmale und -verhalten weisen ein oder mehrere unerwünschte Merkmale auf, und wenn keine ältere Verwendung verwendet wird, werden sie aus dieser Spezifikation entfernt. ...
... Programmierer sollten diese Funktionen und Verhaltensweisen beim Schreiben von neuem ECMAScript-Code nicht verwenden oder annehmen.

Verhalten:

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

Sonderzeichen werden mit Ausnahme von: @ * _ + - codiert. /

Die hexadezimale Form für Zeichen, deren Codeeinheitswert 0xFF oder weniger beträgt, ist eine zweistellige Escape-Sequenz : %xx.

Für Zeichen mit einer größeren Codeeinheit wird das vierstellige Format %uxxxxverwendet. Dies ist in einer Abfragezeichenfolge (wie in RFC3986 definiert ) nicht zulässig :

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

Ein Prozentzeichen ist nur zulässig, wenn direkt zwei Hexdigits folgen, Prozent gefolgt von unicht.

encodeURI ()

Verwenden Sie encodeURI, wenn Sie eine funktionierende URL wünschen. Rufen Sie an:

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

bekommen:

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

Rufen Sie encodeURIComponent nicht auf, da dies die URL zerstören und zurückkehren würde

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

encodeURIComponent ()

Verwenden Sie encodeURIComponent, wenn Sie den Wert eines URL-Parameters codieren möchten.

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

Dann können Sie die URL erstellen, die Sie benötigen:

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

Und Sie erhalten diese vollständige URL:

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

Beachten Sie, dass encodeURIComponent dem 'Zeichen nicht entgeht . Ein häufiger Fehler besteht darin, damit HTML-Attribute zu erstellen, z. B. href='MyUrl'die einen Injektionsfehler verursachen können. Wenn Sie HTML aus Zeichenfolgen erstellen , verwenden Sie entweder "anstelle von 'Attributanführungszeichen oder fügen Sie eine zusätzliche Codierungsebene hinzu ( 'kann als% 27 codiert werden).

Weitere Informationen zu dieser Art der Codierung finden Sie unter: http://en.wikipedia.org/wiki/Percent-encoding

Arne Evertsson
quelle
31
@Francois Abhängig vom empfangenden Server wird möglicherweise nicht ordnungsgemäß dekodiert, wie Escape-Zeichen obere ASCII- oder Nicht-ASCII-Zeichen codieren, z.
Ray
22
@Francois Escape () codiert die unteren 128 ASCII-Zeichen mit Ausnahme von Buchstaben, Ziffern und *@-_+./, während unescape () die Umkehrung von Escape () ist. Soweit ich das beurteilen kann, handelt es sich um Legacy-Funktionen zum Codieren von URLs, die nur aus Gründen der Abwärtskompatibilität noch implementiert sind. Im Allgemeinen sollten sie nur verwendet werden, wenn sie mit einer für sie entwickelten App / einem Webdienst / usw. interagieren.
Anthony DiSanti
3
Es sei denn, Sie versuchen natürlich, eine URL als URI-Komponente zu übergeben. Rufen Sie in diesem Fall encodeURIComponent auf.
Tom
4
Warum wird das einfache Anführungszeichen nicht behandelt?
Eric
11
@Eric Es wird kein einfaches Anführungszeichen codiert, da das einfache Anführungszeichen ein vollständig gültiges Zeichen ist, das in einem URI ( RFC-3986 ) vorkommt. Das Problem tritt auf, wenn Sie einen URI in HTML einbetten, wobei ein einfaches Anführungszeichen kein gültiges Zeichen ist. Daraus folgt dann, dass URIs sollte auch „HTML-codiert“ sein (was würde ersetzen 'mit ') , bevor sie in ein HTML - Dokument platziert werden.
Lee
441

Der Unterschied zwischen encodeURI()und encodeURIComponent()besteht aus genau 11 Zeichen, die von encodeURIComponent, jedoch nicht von encodeURI codiert werden:

Tabelle mit den zehn Unterschieden zwischen encodeURI und encodeURIComponent

Ich habe diese Tabelle einfach mit console.table in Google Chrome mit folgendem Code generiert:

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

Johann Echavarria
quelle
Ist dieser Browser nicht abhängig?
Pacerier
4
@bladnman encodeURI und encodeURIComponent sollten in allen gängigen Browsern auf diese Weise funktionieren. Sie können den obigen Code in Chrome und Firefox testen, da beide console.table unterstützen. In anderen Browsern (einschließlich Firefox und Chrome) können Sie den folgenden Code verwenden: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
Ich meinte @Pacerier :)
Johann Echavarria
@ Pacerier sollte in verschiedenen Browsern identisch sein, es sei denn, die ursprüngliche Spezifikation ist zu mehrdeutig ... siehe auch stackoverflow.com/questions/4407599/…
Christophe Roussy
2
Ich muss diese mehreren Male verbessern! Kann leider nur einmal upvoten.
Ramazan Polat
46

Ich fand diesen Artikel aufschlussreich: Javascript Madness: Query String Parsing

Ich fand es, als ich versuchte zu verstehen, warum decodeURIComponent '+' nicht richtig decodierte. Hier ist ein Auszug:

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!
Damien
quelle
11
Der Artikel, auf den Sie verlinken, enthält viel Unsinn. Es scheint mir, der Autor selbst hat nicht verstanden, wofür die Funktionen richtig verwendet werden ...
Christoph
2
@Christoph Für mich sieht alles vernünftig aus. Insbesondere stimme ich ihm zu, dass encodeURIes nur in einem ziemlich dunklen Fall nützlich zu sein scheint und wirklich nicht existieren muss. Ich habe einige Meinungsverschiedenheiten mit ihm, aber ich sehe dort nichts völlig Falsches oder Idiotisches. Was genau denkst du ist Unsinn?
Mark Amery
1
Das enctypeAttribut des FORMElements gibt den Inhaltstyp an, der zum Codieren des Formulardatensatzes zur Übermittlung an den Server verwendet wird. application / x-www-form-urlencoded Dies ist der Standardinhaltstyp. Mit diesem Inhaltstyp eingereichte Formulare müssen wie folgt codiert werden: [...] Leerzeichen werden durch "+" ersetzt, und [...] nicht alphanumerische Zeichen werden durch "% HH" ersetzt, [...] Ref: HTML4 Sepc
Cychoi
2
encodeURIComponent ('A + B'). replace (/ \% 20 / g, '+') + '\ n' + decodeURIComponent ("A +% 2B + B" .replace (/ \ + / g, '% 20') ));
Zlatin Zlatev
39

encodeURIComponent codiert nicht -_.!~*'(), was zu Problemen beim Posten von Daten in PHP in einer XML-Zeichenfolge führt.

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

Allgemeine Flucht mit 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

Sie können sehen, dass ein einfaches Anführungszeichen nicht codiert ist. Um das Problem zu beheben, habe ich zwei Funktionen zur Lösung des Problems in meinem Projekt für die Codierungs-URL erstellt:

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

Für die Dekodierung der 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 "";
}
Kirankumar Sripati
quelle
5
Das # -Zeichen (Pfund / Hash / Zahl),% 23, wird ebenfalls nicht ausgeführt.
xr280xr
1
@ xr280xr Was meinst du? encodeURIComponent codiert # in% 23 (vielleicht nicht im Jahr 2014?)
David Balažic
38

encodeURI () - Die Funktion Escape () dient zum Escaping von Javascript und nicht zu HTTP.

Daniel Papasian
quelle
Wenn ich eine URL wie diese habe: var url = "http://kuler-api.adobe.com/rss/get.cfm?startIndex=0&itemsPerPage=20&timeSpan=0&listType=rating"... und ich über die Google Ajax-API darauf zugreifen möchte, wie folgt: var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;... dann muss ich verwenden escape(url). encodeURI(url)funktioniert anscheinend nicht mit solchen Parametern.
Lance Pollard
15
Sie sollten ecnodeURIComponent (url)
Ustaman Sangat
2
Alle 3 Funktionen haben ihre Probleme. Es ist besser, eine eigene Funktion zu erstellen, die die Arbeit erledigt.
Jerry Joseph
17

Kleine Vergleichstabelle 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
30thh
quelle
12

Ich empfehle, eine dieser Methoden nicht so zu verwenden, wie sie ist. Schreiben Sie Ihre eigene Funktion, die das Richtige tut.

MDN hat ein gutes Beispiel für die unten gezeigte URL-Codierung gegeben.

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

Jerry Joseph
quelle
1
Was für eine großartige Antwort (wenn es über Chrome Edge und Firefox kompatibel ist, ohne Fehler zu machen)
Yan Bellavance
10

Denken Sie auch daran, dass alle unterschiedliche Zeichensätze codieren, und wählen Sie den gewünschten aus. encodeURI () codiert weniger Zeichen als encodeURIComponent (), das weniger (und auch andere als dannyps) Zeichen codiert als Escape ().

Pseudo-Masochist
quelle
8

Zum Zwecke der Codierung hat Javascript drei eingebaute Funktionen gegeben -

  1. escape()- kodiert nicht @*/+ Diese Methode ist nach dem ECMA 3 veraltet und sollte daher vermieden werden.

  2. encodeURI()- codiert nicht ~!@#$&*()=:/,;?+' Es wird davon ausgegangen, dass der URI ein vollständiger URI ist, daher werden keine reservierten Zeichen codiert, die im URI eine besondere Bedeutung haben. Diese Methode wird verwendet, wenn die vollständige URL anstelle eines speziellen URL-Segments konvertiert werden soll. Beispiel - encodeURI('http://stackoverflow.com'); gibt - http://stackoverflow.com

  3. encodeURIComponent()- - _ . ! ~ * ' ( ) codiert nicht Diese Funktion codiert eine URI-Komponente (Uniform Resource Identifier), indem jede Instanz bestimmter Zeichen durch eine, zwei, drei oder vier Escape-Sequenzen ersetzt wird, die die UTF-8-Codierung des Zeichens darstellen. Diese Methode sollte verwendet werden, um eine Komponente der URL zu konvertieren. Zum Beispiel müssen einige Benutzereingaben angehängt werden. Beispiel - encodeURIComponent('http://stackoverflow.com'); gibt - http% 3A% 2F% 2Fstackoverflow.com

Alle diese Codierungen werden in UTF 8 ausgeführt, dh die Zeichen werden in das UTF-8-Format konvertiert.

encodeURIComponent unterscheidet sich von encodeURI darin, dass es reservierte Zeichen und das Nummernzeichen # von encodeURI codiert

Gaurav Tiwari
quelle
3

Ich habe festgestellt, dass das Experimentieren mit den verschiedenen Methoden eine gute Überprüfung der geistigen Gesundheit ist, selbst wenn man die verschiedenen Verwendungszwecke und Fähigkeiten gut beherrscht.

Zu diesem Zweck fand ich diese Website äußerst nützlich, um meinen Verdacht zu bestätigen, dass ich etwas angemessen mache. Es hat sich auch als nützlich zum Dekodieren einer Zeichenfolge mit encodeURIComponent erwiesen, deren Interpretation ziemlich schwierig sein kann. Ein tolles Lesezeichen:

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

veeTrain
quelle
2

Die akzeptierte Antwort ist gut. Um den letzten Teil zu erweitern:

Beachten Sie, dass encodeURIComponent dem Zeichen 'nicht entgeht. Ein häufiger Fehler besteht darin, damit HTML-Attribute wie href = 'MyUrl' zu erstellen, bei denen ein Injektionsfehler auftreten kann. Wenn Sie HTML aus Zeichenfolgen erstellen, verwenden Sie entweder "anstelle von" für Anführungszeichen oder fügen Sie eine zusätzliche Codierungsebene hinzu ("kann als% 27 codiert werden).

Wenn Sie auf der sicheren Seite sein möchten, codieren Sie nicht reservierte Zeichen in Prozent codiert werden.

Sie können diese Methode verwenden, um ihnen zu entkommen (Quelle Mozilla )

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

// fixedEncodeURIComponent("'") --> "%27"
Michael
quelle
2

Modernes Umschreiben der Antwort von @ 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
        )
)

Oder wenn Sie eine Tabelle verwenden können, ersetzen Sie diese console.logdurch console.table(für die schönere Ausgabe).

ryanpcmcquen
quelle
2

Inspiriert von Johanns Tisch habe ich beschlossen, den Tisch zu erweitern. Ich wollte sehen, welche ASCII-Zeichen codiert werden.

Screenshot von console.table

Die Tabelle zeigt nur die codierten Zeichen. Leere Zellen bedeuten, dass das Original und die codierten Zeichen identisch sind.


Um extra zu sein, füge ich eine weitere Tabelle für urlencode()vs hinzu rawurlencode(). Der einzige Unterschied scheint die Kodierung des Leerzeichens zu sein.

Screenshot von 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>
Akinuri
quelle
1

Ich habe diese Funktion ...

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;
};
Molokoloco
quelle
4
@ChristianVielma Escape () ist veraltet, verweist aber niemals auf w3schools.com. siehe w3fools.com
Jerry Joseph
4
@Christian Vielma - Einige finden das Referenzmaterial bei W3Schools sein weniger umstritten und nützlich . Nicht alle sind sich einig, dass auf W3Schools niemals verwiesen werden sollte.
DavidRR
2
W3Schools bekommt einen schlechten Ruf. Sicher, sie sind nicht immer genau, aber andererseits bin ich auf so manchen Blog-Beitrag gestoßen, der auch völlig falsch ist. Für mich ist es manchmal ein guter Ausgangspunkt, nur um etwas von der Terminologie zu lernen, und dann tauche ich mit anderen Ressourcen ein wenig tiefer ein. Am wichtigsten ist, dass eine einzelne Ressource niemals biblisch sein sollte, wenn es um solche Dinge geht.
Ryandlf
Es scheint, dass @molokoloco diese Funktion als Fallback für Versionen geschrieben encodeURIhat, die nicht existieren, aber escapeexistieren.
SOFe