web-dev-qa-db-ja.com

Unicode文字をURLエンコードする適切な方法は何ですか?

非標準の%uxxxxスキームは知っていますが、W3Cによってスキームが拒否されたため、賢明な選択とは思えません。

いくつかの興味深い例:

心のキャラクター。ブラウザにこれを入力すると:

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

次に、コピーして貼り付けます。このURLが表示されます

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

firefox(またはSafari)がこれを行っているように見えます。

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

トリプルドット文字など、Latin-1でエンコードできないものを除き、これは理にかなっています。

URLを入力した場合

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

ブラウザにコピーして貼り付けると、

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

バック。それはすることの結果のようです

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

…はLatin-1でエンコードできないため、これは理にかなっています。

しかし、ブラウザがUTF-8またはLatin-1でデコードするかどうかをどのように認識するかは、私にはわかりません。

これは曖昧なようだから:

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

動作するので、ブラウザがUTF-8またはLatin-1でデコードするかどうかはわかりません。

対処する必要がある特殊文字を使用するのは正しいことですか?

106
Josh Gibson

常にUTF-8でエンコードします。 パーセントエンコーディングに関するウィキペディアページ から:

汎用URI構文では、URI内の文字データの表現を提供する新しいURIスキームは、実際には翻訳なしで非予約セットの文字を表す必要があり、他のすべての文字をUTF-8に従ってバイトに変換する必要があります。それらの値をパーセントエンコードします。この要件は、2005年1月に RFC 3986 が発行されて導入されました。この日付より前に導入されたURIスキームは影響を受けません。

過去にURLエンコードを行う他の受け入れられた方法があったため、ブラウザはURIをデコードするいくつかの方法を試みますが、エンコードを行う場合はUTF-8を使用する必要があります。

63
John Biesnecker

一般的なルールは、ブラウザがフォームの提供元のページのコンテンツタイプに従ってフォームの応答をエンコードすることです。これは、サーバーが「text/xml; charset = iso-8859-1」を送信した場合、同じ形式で応答が返されることを期待していると推測されます。

URLバーにURLを入力するだけの場合、ブラウザには作業するベースページがないため、推測するだけです。したがって、この場合、常にutf-8を実行しているようです(両方の入力が3オクテットのフォーム値を生成したため)。

悲しい事実は、クエリ文字列の値を設定する文字、または実際にURLの文字を解釈する必要がある標準はないということです。少なくともクエリ文字列の値の場合、それらが必ず文字に対応していると想定する理由はありませんdo

クエリ文字列をエンコードする文字セットをサーバーフレームワークに伝える必要があることは既知の問題です。たとえば、Tomcatでは、request.setEncoding()(または同様のメソッド)を呼び出す必要があります。 before request.getParameter()メソッドのいずれかを呼び出します。この主題に関するドキュメントの不足は、おそらく多くの開発者の間で問題を認識していないことを反映しています。 (私は定期的にJava読者とReaderとInputStreamの違いは何であるかインタビューし、定期的に空白の外観になります)

9
araqnid

IRI( RFC 3987 )は、URI/URL( RFC 3986 およびそれ以前の)標準を置き換える最新の標準です。 URI/URLはネイティブにUnicodeをサポートしていません(まあ、 RFC 3986 は将来のURI/URLベースのプロトコルをサポートするための規定を追加しますが、過去のRFCは更新しません)。 「%uXXXX」スキームは、状況によってはユニコードを許可する非標準の拡張機能ですが、誰もが普遍的に実装しているわけではありません。一方、IRIはUnicodeを完全にサポートしており、テキストをUTF-8としてエンコードしてからパーセントエンコードする必要があります。

8
Remy Lebeau

IRIはURIを置き換えません。これは、HTTPを含む一部のコンテキストではURI(事実上ASCII)のみが許可されているためです。

代わりに、IRIを指定すると、ワイヤで送信されるときにURIに変換されます。

6
Mark Nottingham

最初の質問は、あなたのニーズは何ですか? UTF-8エンコーディングは、安価なエディターで作成されたテキストを取得することと、さまざまな言語をサポートすることとの間のかなり良い妥協です。エンコードを識別するブラウザーに関して、(Webサーバーからの)応答はエンコードをブラウザーに通知する必要があります。多くの場合、これは欠落しているか間違っているため、ほとんどのブラウザーは推測を試みます。彼らは、デフォルトのエンコーディングに適合しない文字が存在するかどうかを確認するために、結果ストリームの一部を読み取ることで推測します。現在、すべてのブラウザ(?これをチェックしませんでしたが、ほぼtrueです)としてutf-8をデフォルトとして使用します。

したがって、他の多くのエンコード方式のいずれかを使用する説得力のある理由がない限り、utf-8を使用してください。

0
Pat O