URLエスケープされた文字列にスラッシュが含まれている場合

URLエスケープとは簡単に言うと、wikipediaのページのURLに含まれている文字列で、「%」なんちゃらというやつである。URLエンコードと呼ばれているときもあって、実際どちらが正しいのかわからん。

で、そのURLエスケープの意図としては以下のとおり。

フォームから問い合わせ文字列を受け取ったり、クッキーを発行するとき、 HTTPプロトコルCGIが適正に処理できるデータ形式に変更する必要があります。
http://www.kinet.or.jp/hiromin/cgi_introduction/appendix/url_encode.html

ということで、サーバへ文字列を送信する場合にはURLエスケープして送信し、受信側で復元する処理をするのが通常。perlでは、CGI.pmを通せば自動的にアンエスケープ処理をしてくれるので特に意識することはなかったりする。

だが、Apacheの設定によっては、たとえ適切にURLエスケープしていても駄目なときがある。
それがこの「スラッシュが含まれている場合」である。


例えば、はてなブックマークの「これはすごい」タグのURL。
http://b.hatena.ne.jp/t/%E3%81%93%E3%82%8C%E3%81%AF%E3%81%99%E3%81%94%E3%81%84
全く問題なく見れる。


では、これではどうか「これは/すごい」
http://b.hatena.ne.jp/t/%E3%81%93%E3%82%8C%E3%81%AF/%E3%81%99%E3%81%94%E3%81%84
エントリが存在しないが、タグ「これは/すごい」が認識されているという点では正常に見える。


では、これはどうか。「これは%2fすごい」
http://b.hatena.ne.jp/t/%E3%81%93%E3%82%8C%E3%81%AF%2f%E3%81%99%E3%81%94%E3%81%84
「Not Found」と文字化けした文字列が表示されたハズ。これ。これが問題。


この問題はApacheの仕様のようで、設定を変更することで対応できるようだ。

apacheの設定がデフォルト状態だと404エラーになります。

これを解消するにはAllowEncodedSlashesをOnにします。
http://kawama.jp/archives/2007/04/path_info2f404a.html

とあり、Apacheのドキュメントにも

AllowEncodedSlashes ディレクティブは符号化された パス分離文字 (/ は %2F、さらにシステムによっては \ に対応する %5C) が存在する URL の使用を 許可するかどうかを決定します。通常はそのような URL は 404 (Not found) エラー で拒否されます。

core - Apache HTTP サーバ バージョン 2.2

(↑文字化けしちゃってるけどw)

ということで、この設定を行えば問題なくURLエスケープされた文字列を受信側で受けとれるハズ。そして、Apacheのドキュメントにあるように環境変数PATH_INFOを使用して使うとめちゃ便利に使えますね。
さぁみんなPATH_INFO使ってRESTしよう!!!!


となるハズなんだけど、ちょっと古いApacheではPATH_INFOのURLエスケープされた文字列がアンエスケープされてしまって使いものにならないバグがあり、しかたなしにREQUEST_URIを使用するハメになってしまう。
最新版のApacheでは修正されているようだ。
35256 – %2F will be decoded in PATH_INFO (Documentation to AllowEncodedSlashes says no decoding will be done)


ということで、RESTしたかったら、

  1. AllowEncodedSlashesをOnにすること
  2. PATH_INFOのバグが治っているバージョンかどうか確認すること
  3. バグがあるならREQUEST_URIを使ってなんとかすること

という点を確認しておくべき。


とはいえ、AllowEndcodedSlashesがOffの場合、サーバ設定ファイルやVirtualHost設定が弄れる環境でないとどうしようもないけれども、、、