Rack::Request#[]でUTF-8文字列が返ってくる件
$ ruby -v ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux] $ gem list | grep rack rack (1.3.0)
という環境で:
require 'rack' class MyApp def call(env) [200, {"Content-Type" => "text/plain"}, [Rack::Request.new(env)['hoge'].encoding.to_s]] end end Rack::Handler::WEBrick.run(MyApp.new, :Port => 3000)
を実行し、http://localhost:3000/?hoge=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A (クエリストリングは「あいうえお」をUTF-8でエンコードしたもの)にアクセスしたら「UTF-8」と表示された。
「あれ、自動判別してるのか」と思い、http://localhost:3000/?hoge=%A4%A2%A4%A4%A4%A6%A4%A8%A4%AA (同じくEUC-JPでエンコード)にアクセスしても、やっぱり「UTF-8」。ためしに「Encoding.default_external = 'EUC-JP'」としても変わらなかった。
Rack::Utils#unescape が原因
解せないので Rack::Request のコードを追いかけたところ、Rack::Utils#unescape が原因と分かった。
Rack::Utils#unescape では、下記のように、URI.decode_www_form_component が第2引数なしで呼ばれている。
def unescape(s) URI.decode_www_form_component(s) end
このように第2引数を省略すると、デフォルトの「Encoding::UTF_8」がデコードに使われ、デコードされた文字列のエンコーディングも「Encoding::UTF_8」と設定される。これが原因。
これ以上は追いかけていないが、この挙動は意図せざるものだと思う。思いたい。