GOTOU Yuuzou:
> でも、script_nameを書き換えるのはよくないような気がします。
> 例えば、#{DocumentRoot}/foo/index.html.jaがあるときの、/foo/
> へのアクセスは、
>
> filename: #{DocumentRoot}/foo/index.index.ja
> script_name: /foo/index.html.ja
> path_info: nil
>
> になって、#{DocumentRoot}/foo/bar.cgi.jaがあるときの、
> /foo/bar.cgi/bazへのアクセスは、
>
> filename: #{DocumentRoot}/foo/bar.cgi.ja
> script_name: /foo/bar.cgi.ja
> path_info: /baz
>
> になるのがいいと思いますが、どうでしょう。
はい、それがいいと思います。
[webrickja:118] のコードでは、set_filename を何度も呼び出すた
め script_name の値がどんどんおかしくなってしまうという問題
がありました。
> #{DocumentRoot}/foo.htmlと#{DocumentRoot}/foo.html.jaがある
> ときの/foo.htmlへのアクセスは、#{DocumentRoot}/foo.html.jaが
> 優先されてもいいような気がするのですが、そういうものではない
> んですね。
はい。 Apache では foo.html が優先されるので真似しました。
> > もしよければ、WEBrick 本体の FileHandler で Accept-Language:
> > に対応していただけると助かります。FileHandler のオプションに
> > :AcceptLanguage => true を指定するとAccept-Language を見る、
> > といった感じで指定できると便利だと思います。
>
> いつも有効だと困るケースってありますかねえ。
foo.html が存在しないときに foo.html.{en,ja,...} の存在をいち
いち確認するコストがもったいないと考える人はいるかもしれませ
ん。
> 言語名の登録とフォールバックの優先順位を兼ねて、
>
> :AcceptableLanguages => ["en", "ja"]
>
> とかできるといいのかもしれません。
なるほど、両方を兼ねて登録できるのはいいですね。これが空だっ
たら Multiviews 的な動作をしない、というふうにするといいかも
しれません。ファイルの存在を確認するのはここで指定された言語
だけに限定すればよさそうです。
ところで、[webrickja:118] のコードでは
@config[:DirectoryIndex] に対応するのを忘れてました。
手元では下のような方法で強引に対応しました。
WEBrick 本体をいじらずに Accept-Language に対応するのはやはり
少々無理があるようです。
module WEBrick::HTTPUtils
module_function
def mime_type(filename, mime_tab)
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
# support multiview files such as index.html.en, foo.html.ja
suffix2 = (/\.(\w+)\.[\w-]+$/ =~ filename && $1.downcase)
mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
end
end
module WEBrick
class HTTPRequest
def parse_accept_language
if self["Accept-Language"]
tmp = []
parts = self["Accept-Language"].split(/,\s*/)
parts.each {|part|
if m = /^([\w-]+)(?:;q=([\d]+(?:\.[\d]+)))?$/.match(part)
lang = m[1]
q = (m[2] or 1).to_f
tmp.push([lang, q])
end
}
@accept_language =
tmp.sort_by {|lang, q| q}.map {|lang, q| lang}.reverse
else
@accept_language = ["en"] # FIXME: should be customizable?
end
end
def accept_language
unless @accept_language
parse_accept_language
end
return @accept_language
end
end
end
module WEBrick::HTTPServlet
class MultilingualFileHandler < FileHandler
def set_filename(req, res)
original_path_info = req.path_info
original_directory_index = @config[:DirectoryIndex]
@config[:DirectoryIndex] += @config[:DirectoryIndex].map {|index|
req.accept_language.map {|lang| index + "." + lang }
}.flatten
begin
return super(req, res)
rescue HTTPStatus::NotFound => e
req.accept_language.each {|lang|
begin
req.path_info = original_path_info + "." + lang
return super(req, res)
rescue HTTPStatus::NotFound
end
}
raise e
ensure
@config[:DirectoryIndex] = original_directory_index
end
end
end
end