Was ist der richtige Weg, um Unicode-Zeichen per URL zu codieren?

107

Ich kenne das nicht standardmäßige% uxxxx-Schema, aber das scheint keine kluge Wahl zu sein, da das Schema vom W3C abgelehnt wurde.

Einige interessante Beispiele:

Der Herzcharakter. Wenn ich dies in meinen Browser eingebe:

http://www.google.com/search?q=♥

Dann kopiere und füge es ein, ich sehe diese URL

http://www.google.com/search?q=%E2%99%A5

Das lässt es so aussehen, als ob Firefox (oder Safari) dies tut.

urllib.quote_plus(x.encode("latin-1"))
'%E2%99%A5'

Das macht Sinn, außer für Dinge, die nicht in Latin-1 codiert werden können, wie das Dreifachpunktzeichen.

Wenn ich die URL eingebe

http://www.google.com/search?q=…

in meinen Browser dann kopieren und einfügen, bekomme ich

http://www.google.com/search?q=%E2%80%A6

zurück. Welches scheint das Ergebnis des Tuns zu sein

urllib.quote_plus(x.encode("utf-8"))

Das macht Sinn, da… nicht mit Latin-1 codiert werden kann.

Aber dann ist mir nicht klar, woher der Browser weiß, ob er mit UTF-8 oder Latin-1 dekodieren soll.

Da dies nicht eindeutig zu sein scheint:

In [67]: u"…".encode('utf-8').decode('latin-1')
Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6'

funktioniert, daher weiß ich nicht, wie der Browser herausfindet, ob er das mit UTF-8 oder Latin-1 dekodieren soll.

Was ist das Richtige, um mit den Sonderzeichen umzugehen, mit denen ich mich befassen muss?

Josh Gibson
quelle
19
Ihre beiden Beispiele sind als UTF-8 codiert. Das erste sicherlich nicht Latin-1, da es drei Bytes lang ist ...
Jakob Borg
2
% E2% 99% A5 ist hexadezimal für die Bytewerte des "Black Heart Suit" in UTF-8 . Dieses schwarze Herz ist nicht Teil des Latin-1-Zeichensatzes .
Hawkeye Parker
Um genau zu sehen, wie und was ein Browser codiert (und viele andere nützliche Informationen), verwenden Sie die in den meisten modernen Browsern integrierten Entwicklertools oder erwerben Sie einen kostenlosen HTTP-Debugger wie Fiddler .
Hawkeye Parker

Antworten:

65

Ich würde immer in UTF-8 codieren. Von der Wikipedia-Seite zur prozentualen Codierung :

Die generische URI-Syntax schreibt vor, dass neue URI-Schemata, die die Darstellung von Zeichendaten in einem URI ermöglichen, tatsächlich Zeichen aus dem nicht reservierten Satz ohne Übersetzung darstellen müssen und alle anderen Zeichen gemäß UTF-8 in Bytes konvertieren müssen Prozentcodierung dieser Werte. Diese Anforderung wurde im Januar 2005 mit der Veröffentlichung von RFC 3986 eingeführt . URI-Schemata, die vor diesem Datum eingeführt wurden, sind nicht betroffen.

Es scheint, als ob Browser in der Vergangenheit andere akzeptierte Methoden zur URL-Codierung gab. Browser versuchen verschiedene Methoden zum Dekodieren eines URI. Wenn Sie jedoch die Codierung durchführen, sollten Sie UTF-8 verwenden.

John Biesnecker
quelle
8
UTF-8 sollte auch verwendet werden, da es die einzige vom neueren IRI-Standard (RFC 3987, tools.ietf.org/html/rfc3986 ) zugelassene Codierung ist, die den älteren URL-Standard ersetzt.
Remy Lebeau
3
Falls andere so überrascht sind wie ich, erwähnt der Text in @ RemyLebeaus Kommentar RFC3987, aber der Link verweist auf die ältere Spezifikation 3896. Die korrekte URL lautet offensichtlich tools.ietf.org/html/rfc3987
Tripleee
Ja, tut mir leid. URI wird durch RFC 3986 definiert, IRI wird durch RFC 3987 definiert.
Remy Lebeau
10

Die allgemeine Regel scheint zu sein, dass Browser Formularantworten entsprechend dem Inhaltstyp der Seite codieren, von der aus das Formular bereitgestellt wurde. Dies ist eine Vermutung, dass der Server, wenn er uns "text / xml; charset = iso-8859-1" sendet, Antworten im gleichen Format erwartet.

Wenn Sie nur eine URL in die URL-Leiste eingeben, verfügt der Browser nicht über eine Basisseite, an der Sie arbeiten können, und muss daher nur raten. In diesem Fall scheint es also die ganze Zeit utf-8 zu geben (da beide Eingaben drei Oktettformwerte erzeugten).

Die traurige Wahrheit ist, dass es bei AFAIK keinen Standard gibt, für welchen Zeichensatz die Werte in einer Abfragezeichenfolge oder tatsächlich alle Zeichen in der URL interpretiert werden sollten. Zumindest im Fall von Werten in dem Query - String, gibt es keinen Grund anzunehmen , dass sie unbedingt tun entsprechen Zeichen.

Es ist ein bekanntes Problem, dass Sie Ihrem Server-Framework mitteilen müssen, für welchen Zeichensatz die Abfragezeichenfolge als --- codiert werden soll. In Tomcat müssen Sie beispielsweise request.setEncoding () (oder eine ähnliche Methode) vor Ihnen aufrufen Rufen Sie eine der request.getParameter () -Methoden auf. Der Mangel an Dokumentation zu diesem Thema spiegelt wahrscheinlich das mangelnde Bewusstsein vieler Entwickler für das Problem wider. (Ich frage regelmäßig Java-Befragte, was der Unterschied zwischen einem Reader und einem InputStream ist, und bekomme regelmäßig leere Blicke.)

araqnid
quelle
6
RFC 3987 ( tools.ietf.org/html/rfc3986 ) definiert eine Standardcodierung - UTF-8 muss verwendet werden, wenn Zeichen codiert werden, die ansonsten nicht uncodiert zulässig sind.
Remy Lebeau
8

IRI ( RFC 3987 ) ist der neueste Standard, der die URI / URL- Standards ( RFC 3986 und älter) ersetzt. URI / URL unterstützen Unicode nicht nativ ( RFC 3986 fügt Bestimmungen für zukünftige URI / URL-basierte Protokolle hinzu, um dies zu unterstützen, aktualisiert jedoch frühere RFCs nicht). Das "% uXXXX" -Schema ist eine nicht standardmäßige Erweiterung, um Unicode in bestimmten Situationen zuzulassen, wird jedoch nicht von jedem universell implementiert. IRI hingegen unterstützt Unicode vollständig und erfordert, dass Text als UTF-8 codiert wird, bevor er prozentual codiert wird.

Remy Lebeau
quelle
Ich möchte ein Update der Protokolle sehen, damit Unicode in URLs nicht nur über die Prozentcodierung vollständig unterstützt wird.
Mathieu J.
1
IRIs ermöglichen nicht codierte Unicode-Zeichen, außer in den wenigen Fällen, in denen reservierte Zeichen codiert werden müssen.
Remy Lebeau
6

IRIs ersetzen keine URIs, da in einigen Kontexten - einschließlich HTTP - nur URIs (effektiv ASCII) zulässig sind.

Stattdessen geben Sie eine IRI an, die beim Ausgehen auf der Leitung in eine URI umgewandelt wird.

Mark Nottingham
quelle
0

Die erste Frage ist, was sind Ihre Bedürfnisse? Die UTF-8-Codierung ist ein ziemlich guter Kompromiss zwischen der Verwendung von Text, der mit einem billigen Editor erstellt wurde, und der Unterstützung einer Vielzahl von Sprachen. In Bezug auf den Browser, der die Codierung identifiziert, sollte die Antwort (vom Webserver) dem Browser die Codierung mitteilen. Dennoch werden die meisten Browser versuchen zu raten, da dies in so vielen Fällen entweder fehlt oder falsch ist. Sie raten, indem sie einen Teil des Ergebnisstroms lesen, um festzustellen, ob ein Zeichen vorhanden ist, das nicht in die Standardcodierung passt. Derzeit verwenden alle Browser (? Ich habe dies nicht überprüft, aber es ist ziemlich nahe an true) utf-8 als Standard.

Verwenden Sie also utf-8, es sei denn, Sie haben einen zwingenden Grund, eines der vielen anderen Codierungsschemata zu verwenden.

Pat O.
quelle