URLのパス名に日本語を使う場合に問題になること


URLのパス名に日本語を使ってみるの続き。


前回は、(1)URLの一部に日本語を使うことの意義、(2)ローカルで日本語のディレクトリ名で保存した状態で、サーバ側でも日本語のディレクトリ名を使えるようにする方法について、検討しました。


今回は、データベースに保存した情報をもとにURLのパス名を動的に生成する際に、日本語を使うと問題になることを検討しようと思います。




URLの正規化とcanonical属性、canonical URL」、「Amazonのパラメータによる動作の違いと、最短のURL」は、この記事を書きはじめたら長くなったので、独立させたものです。
うーん、理解したものをアウトプットしていったら、書くだけですごい時間が(^^;

URLの正規化

URLのパス名に日本語を使う場合、ほぼ確実に問題になるので。


この点は「URLの正規化とcanonical属性、canonical URL」で書いたとおりです、はい。
canonical属性か、当分リダイレクトを併用するかはご自分の状況にあわせてどうぞ。


URLの長さの制限

URLの長さって制限があった記憶があったのですが、少なくともRFC上はないそうです。

RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1 (ftp://ftp.isi.edu/in-notes/rfc2616.txt) では、URL の長さに関する要件は取り決められていません。


▽[IE] URL に使用可能な文字数は最大 2,083 文字(Microsoftサポートオンライン)
 http://support.microsoft.com/kb/208427/ja


ただしこの記事にもあるとおり、Internet Explorer 6.0では、URLに使用できる最大文字数は 2,083 文字だそうです。
まぁ普通はこの文字数は超えないでしょうし、超えるような場合はPOSTメソッドを使えってことですね。


あとはWebサーバ側のハードルがあるようですね。
Apache(バージョン不明)は、4000byteとのこと。


▽URLの長さ制限(仕事を早く片付けて遊ぶための技術メモ)
 http://shrine-bell.seesaa.net/article/104165361.html


▽URLの長さ制限(@IT会議室)
 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=23098&forum=6&5



だんだんハードルがあがってきましたが、これがとどめです。


はてブで255文字以上のURLをブックマークしたらURLが切られる(F.Ko-Jiの「一秒後は未来」)
 http://blog.fkoji.com/2009/01221826.html


全然関係ないですが、SharePoint Server 2007というソフトでもリンク列に登録できるのは最大255文字だそうです。


▽リンクリストのURL文字数制限(SharePoint MANIACS)
 http://sharepoint.boo.jp/index.php?e=25


はてブについては2年以上前に解決してるっぽいのですが、なんで再発してしまったのか


▽URLの長さが255文字を超えると、勝手に後ろを切られてしまう。長いURLを許容してほしい。せめて長いURLにはエラーが出て登録できないようにしてほしい。
 http://i.hatena.ne.jp/idea/2120


そういえば、GETメソッドの初期の仕様も255バイトまででしたね


そうすると、とりあえず255文字に押さえた方がよさそうですね。
255文字というとたくさんあるようですが、URLのパス名に日本語を使う場合、そうとも言い切れないんですよ。


UTF-8による符号化では、漢字や仮名などの表現に3バイトを要する」(wikipedia)わけですが、漢字をURLエンコードすると3バイトでもとどまらず、9バイトも必要になってしまいます。


具体例。
(なんで薔薇なのかはともかく)前半を書名、後半を著者名だと思ってくださいな。

http://www.testtest.jp/item/薔薇薔薇薔薇薔薇薔薇-薔薇薔薇薔薇薔薇薔薇/dp/1111111111111/


これをURLエンコードすると

http://www.testtest.jp/item/%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87-%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87%E8%96%94%E8%96%87/dp/1111111111111/


となって228バイトになってしまいます。
書名と著者名でそれぞれ10文字使うだけであっという間にボーダー。恐ろしい。
UTF-8を使わなければ減らせますが、今更文字コードの混在で悩むのは嫌なので、この方法で回避することもできません。


URLをメール等に貼り付けたとき、URLエンコードされた訳のわからない記号が長々と並ぶのは見苦しいのでもっと短くしたいところですが、おそらくこれぐらいが下限であり、上限なのでしょう。


……見苦しい問題は、貼り付け用に日本語抜きのURLを画面下部等で提供することで解決するべきなんでしょうね。もしくはURLのパス名に日本語を使うのをそもそもやめるか(^^;


そしておそらく長い書名の場合、一定の文字数以下は無視する他ないと思います。
Amazonの場合、255文字というボーダーは無視してますね。まあ、そりゃそうか(URLの正規化でも無視するぐらいだし)。



rawurlencodeとmb_substr

URLエンコードは、RFC1738に基づいてURLエンコードするrawurlencode、もしくは同じくURL エンコードするするものの、半角スペースを%20に変換するrawurlencodeと異なり+にする点が異なるurlencodeを使うことで、簡単にできます。


ですからURLエンコードの結果をデータベースに保存する必要は原則、ありません(当然)。


ちなみにrawurlencodeurlencodeの違いについて疑問を持つ人は多いようですが、上記に書いたとおりスペースの違いだけのようです。


▽二つのURLエンコード・デコード(PHP基礎)(MindLocalWeb)
 http://meerweb.blog7.fc2.com/blog-entry-22.html



上記記事に掲載されている「二つのエンコード・デコード変換ツール」で試させていただきましたが、実際違いがわかったのは半角スペースだけでした。
マニュアルにも、「歴史的な理由により、この関数は ≫ RFC 1738 エンコードとは異なり、 空白を + 記号にエンコードします」とあるぐらいですから、互換性のために残っているものと考えるべきで、原則はrawurlencodeでいいのでしょう。


また日本語を含む10文字で切ることも、mb_substrで簡単にできることがわかりました。
マルチバイトの文字をバイト数できると途中で文字化けして困るねなんて話を昔聞いた記憶があるのですが、文字コードの矛盾が生じなければ(もしくは生じても明示的に指定してあれば)、問題なく処理できるのですね。


phpは、本当に簡単で素晴らしいなぁ。


phpのmb_substrで発生する文字化けの対処方法(camelmasaの開発日記)
 http://d.hatena.ne.jp/camelmasa/20090804/1249344248


phpで文字列の切り取りが上手く行きません。(人力検索はてな
 http://q.hatena.ne.jp/1184424540