Prozent-Untersucher

Prozentkodierung ist nicht eine Regel, sondern mehrere, und sie widersprechen sich bei etwa einem Dutzend Zeichen. Diese Seite führt denselben Text nebeneinander durch encodeURIComponent, encodeURI und die Serialisierung application/x-www-form-urlencoded, markiert die Zeichen, bei denen sie sich widersprechen, gibt eine Zeile je Zeichen mit seinen UTF-8-Bytes und seiner RFC-3986-Klasse aus und zeigt, wie oft eine Zeichenfolge kodiert wurde. Die Dekodierseite liest eine Zeichenfolge mit einer strikten oder einer nachsichtigen Regel und sagt Ihnen, welches Escape kaputt ist und wo, statt ein stillschweigend falsches Ergebnis zurückzugeben.
Die gesamte Verarbeitung erfolgt lokal in Ihrem Browser — Ihre Daten werden niemals auf einen Server hochgeladen.

Sie wissen nicht, was Prozentkodierung ist? Prozentkodierung in einfachem Deutsch erklärt — was sie ist, warum ein Leerzeichen zu %20 oder + wird und was es bedeutet, wenn eine URL %25 zeigt.
Was das bewirkt:
So lesen Sie die Escapes:
encodeURIComponent
encodeURI
Formular (application/x-www-form-urlencoded)
Strg+Eingabe im Eingabefeld führt den aktiven Modus aus.
Wählen Sie einen Modus und klicken Sie auf seine Aktionsschaltfläche. Kodieren & untersuchen zeigt die drei Kodierungen Ihres Textes plus eine Zeile je Zeichen; Dekodieren liest die Escapes zurück und zählt die Schichten. Die Schaltfläche Selbsttest führt jedes dokumentierte Beispiel, jedes druckbare ASCII-Zeichen und die in der Datendatei dieser Seite aufgezeichneten Schichtketten erneut aus und meldet die Anzahl hier.
Wo die Kodierer sich widersprechen:nur die unten genannten Zeichen werden von den drei Methoden unterschiedlich behandelt. Alles andere läuft durch alle drei unverändert oder wird von allen dreien identisch escapt.
Jedes Zeichen, eine Zeile je Zeichen:die UTF-8-Bytes, zu denen ein Zeichen wird, die Klasse, in die RFC 3986 es einordnet, und das Escape, das jeder Kontext schreibt. Die vier Kontextspalten sind die WHATWG-Prozent-Kodiermengen, die ein Browser beim Erzeugen eines Pfads, einer Abfrage oder eines Fragments verwendet; eine schattierte Zeile ist ein Zeichen, das die drei Kodierer unterschiedlich behandeln.
Die genaue Menge, die diese Seite für jeden Teil einer URL escapt:aus dem Kodierer selbst gedruckt, damit diese Tabelle und der Code, der die Spalten oben füllt, nicht auseinanderlaufen können. Jede Menge escapt außerdem die C0-Steuerzeichen (U+0000 bis U+001F) und jeden Codepunkt über U+007E, weshalb nicht-ASCII-Text in jedem Kontext immer escapt wird.
Diese Mengen sind von den WHATWG-Prozent-Kodiermengen abgeleitet und unterscheiden sich an zwei bewussten Stellen, die beide die Handmontage sicher machen: Eine Raute wird innerhalb einer Abfrage escapt, weil eine rohe Raute das Fragment beginnen würde; und die Komponentenmenge ist genau auf die Zeichen festgelegt, die encodeURIComponent escapt, einschließlich Apostroph, während die Formularmenge auf das festgelegt ist, was URLSearchParams escapt. Die beiden Spalten in der Tabelle oben sind daher das eigene Verhalten der Plattform und keine Nachbildung. Diese Liste erklärt auch ein Ergebnis, das viele überrascht: Ein Prozentzeichen wird von encodeURIComponent und von encodeURI escapt, steht aber in keiner der WHATWG-Kontextmengen, daher lassen die Spalten Pfad, Abfrage und Fragment der Tabelle je Zeichen es in Ruhe. Ein rohes Prozentzeichen in einer von Hand zusammengesetzten URL bleibt ein Risiko, weil der Standard erwartet, dass die Eingabe zuerst geprüft wurde: %41 in einer Abfrage ist für viele Server-Frameworks ein einzelnes A, und die strikte Lesart dieser Seite behandelt ein alleinstehendes % als kaputtes Escape. Es selbst als %25 zu escapen ist die sicherere Gewohnheit, und die Tabelle je Zeichen zeigt beide Schreibweisen nebeneinander.
Wie oft diese Zeichenfolge kodiert wurde:jede Dekodierungsrunde ist eine Schicht. Ein zweimal kodierter Wert beginnt mit%25wo eine einzelne Kodierung übrig lassen würde%20, und ein dreimal kodierter Wert beginnt mit%2525.
Die Zeichen, die eine URL unverändert tragen darf:RFC 3986 teilt den ASCII-Bereich in drei Gruppen auf, und die Escape-Regeln ergeben nur vor dieser Aufteilung Sinn.
Die reservierten Zeichen sind nicht verboten, sie sind belegt: Sie bedeuten etwas für den URL-Parser. Die Regel, die sich daraus ergibt, ist kurz — ist ein Zeichen reserviert und meinen Sie es als Daten, escapen Sie es; ist es unreserviert, müssen Sie es nie escapen.
Die drei Methoden und was jede in Ruhe lässt:
Die Listen sind die genauen Mengen, die jede Methode im ASCII-Bereich unescapt lässt; der Selbsttest prüft jedes druckbare ASCII-Zeichen dagegen, sodass die Tabelle nicht von den Kodierern abweichen kann, die sie beschreibt.
Wie groß eine Eingabe diese Seite annimmt und warum:Prozentkodierung ist ein einziger Durchlauf über den Text, daher wächst der Aufwand anders als bei den Radix-Konvertern dieser Website geradlinig statt quadratisch: Es gibt keine Länge, bei der die Rechnung selbst zum Problem wird. Die Grenzen unten bestehen, weil die Tabelle je Zeichen im Dokument gezeichnet wird, und eine Tabelle mit einer Million Zeilen ist genau das, was einen Browser tatsächlich stoppt.
Was ist Prozentkodierung?

Prozentkodierung — auch URL-Kodierung genannt, und in älteren Dokumenten Escaping — ist die Regel, mit der eine URL Zeichen tragen kann, die sie nicht enthalten dürfte. Ein Prozent-Escape besteht aus drei ASCII-Zeichen: einem Prozentzeichen und zwei hexadezimalen Ziffern, die für ein Byte stehen. %20 ist das Byte 0x20, ein Leerzeichen. %2F ist das Byte 0x2F, ein Schrägstrich. Mehr ist nicht im Spiel: Das Escape benennt ein Byte, kein Zeichen.

Weil es Bytes benennt, muss der Text zuerst in Bytes verwandelt werden, und die Bytekodierung ist UTF-8. Daher stammen die langen Escapes: Ein chinesisches Zeichen sind drei UTF-8-Bytes und damit drei Escapes, und ein Emoji sind vier Bytes und zwölf ASCII-Zeichen.

Die Version in 30 Sekunden: Ein Leerzeichen ist %20 als URL-Wert, aber + in Formulardaten; # ist %23; ein wörtliches Prozentzeichen ist %25. Die drei Kodierer auf dieser Seite stimmen bei den Buchstaben, Ziffern und -_. überein und widersprechen sich bei etwa einem Dutzend Satzzeichen, darunter die Tilde — genau deshalb erzeugen encodeURIComponent und encodeURI für denselben Text verschiedene Zeichenfolgen, und der falsche der beiden kann einen Wert in zwei Abfrageparameter aufspalten.
Warum eine URL sie überhaupt braucht

Ein URI ist als Folge von ASCII-Zeichen definiert (RFC 3986, Abschnitt 2.1), und innerhalb dieses ASCII-Bereichs sind einige Zeichen reserviert: Sie sind die Interpunktion, die der URL ihre Struktur gibt. Ein Doppelpunkt und zwei Schrägstriche trennen das Schema, ein At-Zeichen trennt die Benutzerinformationen vom Host, ein Fragezeichen beginnt die Abfrage, eine Raute beginnt das Fragment, ein kaufmännisches Und trennt Abfrageparameter, und ein Prozentzeichen leitet ein Escape ein.

Das schafft ein Problem und ein Schlupfloch. Das Problem: Ein Wert, der selbst eines dieser Zeichen enthält — ein Suchfeld mit „a&b“, ein Dateiname mit einem Schrägstrich, ein Passwort mit einem Doppelpunkt — würde sonst die Struktur der URL verändern, in der er reist. Das Schlupfloch: das Prozentzeichen selbst, sodass der Kodierer sein eigenes Alphabet einfach erweitern kann. % wird als %25 geschrieben, und die zwei hexadezimalen Ziffern danach sind gewöhnliche unreservierte Zeichen.

Durchgerechnete Beispiele

Das sind die genauen Ausgaben der drei Kodierer dieser Seite, für Eingaben gewählt, weil sie sich voneinander unterscheiden. Die Seite berechnet sie vor Ihren Augen neu, und ihr Selbsttest prüft jede Zeile gegen die eigenen Implementierungen der Plattform.

Die drei Methoden und wann jede die richtige ist

Die Kurzfassung, die die meisten Fehler verhindert: Alles, was in einen einzelnen Parameterwert geht, läuft durch encodeURIComponent (oder durch einen Formularserialisierer, der dieselbe Aufgabe mit einer anderen sicheren Menge erledigt), und eine bereits zusammengesetzte vollständige URL läuft durch encodeURI, wenn sie überhaupt escapt werden muss. Das falsche der beiden Werkzeuge zu greifen ist der mit Abstand häufigste Prozentkodierungsfehler im Webcode.

Die Zeichen, die eine URL tragen darf, vollständig
Zwei Pluszeichen, zwei Bedeutungen

Ein Leerzeichen ist das einzige Zeichen, dessen Kodierung davon abhängt, wohin der Text geht, und das Pluszeichen ist der Grund dafür.

Die Falle steckt mitten in dieser Tabelle. In Formulardaten bedeutet ein Pluszeichen ein Leerzeichen; ein Wert, der tatsächlich ein Pluszeichen enthält — eine als +44 20 7946 0958 geschriebene Telefonnummer, ein arithmetischer Ausdruck, eine E-Mail-Adresse mit Plus-Tag — muss als %2B reisen. Reist er als wörtliches Pluszeichen, liest der Empfänger ihn als Leerzeichen zurück, und +44 kommt als „ 44“ an.

Zweimal kodiert, und wie man es erkennt

Eine doppelte Kodierung entsteht, wenn eine Zeichenfolge bereits escapt ist und dann erneut escapt wird. Das Prozentzeichen des ersten Escapes ist ein Zeichen wie jedes andere, wird also zu %25, und die Schicht darunter bleibt als sichtbarer Text erhalten.

Es zu erkennen ist eine Frage des Zählens: Dekodieren Sie die Zeichenfolge einmal und sehen Sie sich das Ergebnis an. Enthält es noch Escapes, die gewollt aussehen — ein gültiges %XX oder ein Formular-Pluszeichen, wo ein Leerzeichen erwartet wird — gibt es eine weitere Schicht. Folgt auf %25 noch zwei hexadezimale Ziffern, ist die nächste Schicht sicher ein Escape.

Zwei praktische Hinweise. Erstens ist zweimal dekodieren nicht harmlos: Es ist ein bekannter Weg, dafür zu sorgen, dass ein Sicherheitsfilter und der Code dahinter verschiedene Zeichenfolgen sehen, daher filtert ein Filter, der vor einer zweiten Dekodierung läuft, den falschen Text. Zweitens ist die Schichtanzahl hier eine Eigenschaft der Zeichenfolge, kein Versprechen über die Absicht: Ein legitimer Wert kann eine einzelne Schicht tief sein, und ein kaputter kann zwei sein.

Die Fehler, die diese Seite aufdecken soll
  • Ein mit encodeURI kodierter Wert. Die Trennzeichen bleiben erhalten, daher wird ein Wert mit & oder = auf der anderen Seite in mehrere Parameter gespalten. Vergleichen Sie die beiden Spalten oben auf dieser Seite mit der Eingabe a&b=c: Die Komponentenspalte escapt beide Zeichen, die encodeURI-Spalte behält sie.
  • Ein wörtliches Pluszeichen, als Formulardaten gesendet. Es kommt als Leerzeichen an. Verwenden Sie %2B.
  • Ein zweimal escapter Wert „sicherheitshalber“. Das ist nicht sicherer. Der Empfänger dekodiert einmal und erhält eine Zeichenfolge, die noch Prozent-Escapes enthält — derselbe Fehler wie ein falscher Zeichensatz, nur eine Schicht tiefer.
  • Dekodieren, was nie kodiert wurde. Ein wörtliches Prozentzeichen im Text — 100% sicher — ist kein Escape. In einer strikten Lesart ist es ein kaputtes, an der Stelle, die diese Seite meldet; in einer nachsichtigen Lesart bleibt es erhalten, deshalb ist nachsichtig hier der Standard und nicht umgekehrt.
  • Die Annahme, das Escape müsse großgeschrieben sein. Die Dekodierung behandelt %2f und %2F als dasselbe Byte, und beide sind gültig. Großschreibung ist nur die kanonische Schreibweise, die RFC 3986 empfiehlt und die andere Werkzeuge erzeugen.
  • Die Annahme, Prozentkodierung mache Text sicher. Sie macht Text innerhalb einer URL eindeutig. Sie verhindert keine Injection, sie ist keine Verschlüsselung und kein Bereiniger: Das Escaping muss der letzte Schritt vor dem Zusammensetzen sein, für den Kontext, in den der Text gelangt.
Kurze Antworten

„Ist ein Pluszeichen in einer URL ein Leerzeichen?“

Nur in Formulardaten und nur im Abfrageteil einer Formularübermittlung. Im Pfad, im Fragment und in der Abfrage eines einfachen Links ist ein Pluszeichen ein wörtliches Pluszeichen. Deshalb hat diese Seite einen Schalter dafür, statt zu raten.

„Warum zeigt mein Link %25?“

Weil etwas ein Prozentzeichen kodiert hat. Entweder ist ein wörtliches Prozentzeichen durch einen Kodierer gelaufen — 100% sicher wird zu 100%25%20sicher — oder eine Zeichenfolge, die bereits ein Escape enthielt, wurde ein zweites Mal kodiert. Dekodieren Sie die Zeichenfolge einmal und sehen Sie sich an, was zurückkommt: Wenn das Ergebnis noch %XX enthält, gibt es eine weitere Schicht.

„Macht es einen Unterschied, ob ein Schrägstrich in einem Abfragewert %2F oder / ist?“

Für den URL-Parser nein: Beides erreicht den Server als Schrägstrich, und die WHATWG-Abfragemenge lässt einen Schrägstrich in Ruhe. Für die Interoperabilität manchmal ja: Viele Server-Frameworks führen eigene Dekodierung über einen rohen Abfragestring aus, und einige widersprechen sich bei Zeichen, die nie escapt wurden. Wenn ein Wert von Hand statt von einem Serialisierer zusammengesetzt wird, ist es die sicherere Gewohnheit, die reservierten Zeichen ausdrücklich zu escapen.

„Warum escapt die Formularspalte eine Tilde, die die beiden anderen in Ruhe lassen?“

Weil der sichere Zeichensatz des Formularkodierers enger ist: nur Buchstaben, Ziffern und -_.*. Der WHATWG-Formularkodierer escapt ~ ! ' ( ), obwohl RFC 3986 die ~ als unreserviert auflistet. Beide Schreibweisen dekodieren zum selben Wert; der Unterschied zählt nur beim byteweisen Vergleich von Zeichenfolgen.

„Können dieselben Zeichen unescapt in der Adressleiste eines Browsers erscheinen?“

Ja, und das ist die Adressleiste, nicht die URL. Browser zeigen eine lesbare Form einer URL an und kodieren sie beim Senden, daher wird 中文 in einem Link auf der Leitung zu %E4%B8%AD%E6%96%87. Wenn Sie die URL aus der Adressleiste kopieren, bekommen Sie je nach Browser eine der beiden Formen.

„Jedes Escape hier sieht gültig aus, aber das herauskommende Zeichen ist nicht das, das ich erwartet habe. Warum?“

Hinter „es wurde falsch dekodiert“ verbergen sich zwei verschiedene Fehler, und die Seite meldet sie unterschiedlich. Der erste ist ein kaputtes Escape: ein Prozentzeichen, auf das nicht zwei hexadezimale Ziffern folgen, etwa ein abschließendes 100% oder ein %zz. Das ist ein Syntaxproblem; die strikte Lesart lehnt es ab und sagt, wo es sitzt, während die nachsichtige Lesart es als wörtlichen Text behält und auflistet. Der zweite ist ein Escape, dessen Byte völlig legal ist, dessen Bytes aber kein gültiges UTF-8-Zeichen ergeben, etwa %FF allein oder ein dreibyteiges Zeichen, das als %E4%B8 abgeschnitten ist. Das ist kein Syntaxproblem; daher geben beide Lesarten den Text zurück, ersetzen die nicht dekodierbaren Bytes durch das Ersatzzeichen U+FFFD ("�") und listen eine Warnung dazu. Diese Warnung ist der nützliche Teil: Text, der als Ersatzzeichen ankommt, bedeutet meist, dass der Absender einen anderen Zeichensatz verwendet hat oder die Zeichenfolge eine Kodierung zu viel erhalten hat. Prozentkodierung benennt Bytes, und diese Seite liest diese Bytes wie der URL-Standard immer als UTF-8.

„Was macht diese Seite nicht?“

Sie zerlegt eine URL nicht in Schema, Host, Pfad und Abfrage — dafür ist der URL-Parser da. Sie prüft nicht, ob ein Link sicher zu öffnen ist, sie kontaktiert nichts, und sie errät nicht den Zeichensatz der Bytes hinter einem Escape: Sie liest sie immer als UTF-8, wie es der URL-Standard verlangt.

„Welche Ersatzregel braucht die Dekodierung, und woher weiß ich, dass sie richtig ist?“

Drücken Sie Selbsttest. Er vergleicht die eigenen Kodierer der Seite für jedes druckbare ASCII-Zeichen mit encodeURIComponent, encodeURI und URLSearchParams der Plattform, führt jedes Beispiel in den obigen Tabellen erneut aus, prüft die aufgezeichneten Schichtketten erneut und meldet die Anzahl der Prüfungen hier.

Standards und Umfang

Prozentkodierung ist in RFC 3986, Abschnitt 2.1 festgelegt, mit der Definition reservierter und unreservierter Zeichen in den Abschnitten 2.2 und 2.3 und der Großschreibungsregel in Abschnitt 6.2.2.1. Die Mengen, die ein Browser beim Erzeugen einer URL tatsächlich verwendet, stehen im WHATWG-URL-Standard, der sie nach Kontext aufteilt: eine für das Fragment, eine für die Abfrage, eine für die besondere Abfrage, eine für den Pfad, eine für Benutzerinformationen und die engere für eine einzelne Komponente. Die Formularübermittlung einschließlich des Pluszeichens steht im HTML-Standard unter application/x-www-form-urlencoded. Die beiden Funktionen encodeURI und encodeURIComponent sind Teil von ECMAScript selbst.

Diese Seite füllt die Spalten Pfad, Abfrage und Fragment aus ihren eigenen kontextbezogenen Mengen und gibt für jeden Kontext die genaue Liste neben dem Ergebnis aus. Diese Mengen sind von den WHATWG-Mengen abgeleitet und unterscheiden sich an zwei bewussten Stellen: Eine Raute wird innerhalb einer Abfrage escapt, weil eine rohe Raute das Fragment beginnen würde, und die Komponentenmenge ist genau auf die Zeichen festgelegt, die encodeURIComponent escapt. Wo eine Plattformfunktion die Definition der Antwort ist — encodeURIComponent, encodeURI und die Formularserialisierung — wird diese Funktion direkt aufgerufen, sodass diese Spalten das eigene Verhalten des Browsers zeigen und keine Nachbildung davon sind.

Der Seitentext wurde für diese Website geschrieben. Jeder Wert in den obigen Tabellen wird beim Laden vom eigenen Code der Seite erzeugt und gegen die Implementierungen der Plattform in den Testwerkzeugen dieser Website geprüft; der Selbsttest wiederholt diesen Vergleich in Ihrem Browser.