カラクリスタ

『輝かしい青春』なんて失かったヒトのブログ

Win32なApacheでPATH_INFOがShift_JISになる

なんかここの所Wikiネタばっかりなので、役に立ちそうで立つのか分からないネタ。

WindowsでApache使ってサーバ立てるのはオススメできないという話。

なんでもShift_JIS

仕様なのかバグなのか分かりませんが、Win32なApacheでは PATH_INFO 等が Shift_JIS に強制変換されるみたいです。 WindowsXP + Apache1.3.34 で確認しました。というかまあ僕の開発環境なんですが、他の環境でもそうなるかと思います。 Apache PATH_INFO 文字化け なんかで検索すると同じようなエントリが出てきます。

具体的にはどういうことかと言うと、CGIの PATH_INFO に日本語(マルチバイト?)な文字列を、 URIエスケープして渡すと、なぜか Shift_JIS に変換されます。 なので場合によっては文字化けして PATH_INFO が使い物にならなくなります。 ちなみにこれは mod_rewrite を使ったURI書き換えでも起こります。

僕が遭遇したのはmod_rewriteで化けたほうが先で、PATH_INFO がおかしくなるのに気づいたのはWiki書き始めた時です。

まあ、遭遇した順番はどうでもいいですが、このままだと PATH_INFO が使えないので解決策を考えてみます。

環境変数 REQUEST_URI , SCRIPT_NAME を使う

REQUEST_URISCRIPT_NAMEを使えば意外と簡単にできます。 というわけで例。コードはPerlです。

my ($request_uri,$script_name) =
    ( $ENV{'REQUEST_URI'} , $ENV{'SCRIPT_NAME'});
my $path_info = $request_uri;
$path_info =~ s!^$script_name!!;
$path_info =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;

こんな感じです。これでばっちり……と言いたい所ですが問題があったりします。 このコードそのまま使うと mod_rewrite なんかでURI書き換えた時動かねぇという事態に陥ります。

簡単なURIの書き換え、例えばCGIファイル名を隠すというリライトなら

my ($request_uri,$script_name,$script_filename) =
    ( $ENV{'REQUEST_URI'} , $ENV{'SCRIPT_NAME'} , $ENV{'SCRIPT_FILENAME'});
my @tmp_filename = split m{/},$script_filename;
my $filename = pop @tmp_filename;
my $path_info = $request_uri;
if ($path_info !~ m/$filename$/){
    $script_name =~ s!/$filename$!!;
}
path_info =~ s!^$script_name!!;
$path_info =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;

こんな感じのコードで対応できると思います。ただこれ以外のリライトになると、 どう対応していいのか分かりません。解決策ねぇって言う状態です。 Win32でApache使うのやめるぐらいしか選択肢がないように思います。

まとめ

この問題を回避する選択肢としては、

  1. PATH_INFO に日本語突っ込むのをやめる
  2. WindowsでApache使うのやめる
  3. Windowsを窓から投げ捨てろ

ぐらいでしょうか。1か2が妥当でしょう。3はネタなので気にしない。 いや本当に投げ捨ててもいいと思いますが。問題ないのならば。

2に関してはlighttpdという最近はやり?のやつがあるので、 そっちを試してみるのもいいかもしれません。試したこと無いので問題起こるかどうか知りませんが。

おまけ

自作Wikiの公開のためのサイトですが全然できてません。 記法作るのに時間がかかってるよ。今月中には公開したい。

asin-4873113814-detail