mod_rewriteでURLを書き換える

先日やったテンプレート変更の時に、カテゴリーを任意の順番で並べるPluginというのを入れ直したのだけど、その関係で今まで大文字小文字混在だったURLが

https://www.downtown.jp/~soukaku/archives/Yota_Banashi/Camera/2008/08/27-2257.html

小文字に統一

https://www.downtown.jp/~soukaku/archives/yota_banashi/camera/2008/08/27-2257.html

されてしまったので、それを何とか補正しようと考えて、apacheのモジュールのひとつであるmod_rewriteを使ったURL書き換えを試してみた。
サーバ上には、どちらのURLでアクセスされても、表示すべきファイルはあるのだけど、大文字小文字混在の方は古いテンプレートはき出されているし、一部のエントリーに文字化けが残ったままだったりというのもあって、新しい小文字で統一されたURLの方に誘導しようと思った次第。
トラックバックした先のリンクとか、検索エンジンのクロールの結果が切り替わりを、こちらから制御出来ないというのも,やってみようと思った理由ではあります。


mod_rewriteの準備と設定

Debianでフツーにapache2が動いている環境であれば、追加パッケージは必要なくて、root権限のコンソール上で

a2enmod rewrite

を実行すると、apacheの起動時に、mod_rewriteが読み込まれるようになります。が、その前に/etc/apache2/site-enable/000-default


RewriteEngine on
RewriteLock   /tmp/rewrite_map.lock
RewriteMap    A2a-map prg:/etc/apache2/scripts/A2a.pl
RewriteRule   ^/~soukaku/archives/([A-Z].*)$  /~soukaku/archives/${A2a-map:$1} [R,L]

の4行を追加します。
それぞれのディレクティブの機能と引数の意味は、次の通り。

  • RewriteEngine
    • Onを指定して、URLの書き換えを有効にします。
  • RewriteLock
    • 外部Rewriteエンジンとなるプログラムへの同時アクセスが発生しないように排他制御するためのロックファイルの指定。
  • RewriteMap
    • 第一引数:マップ名
    • 第二引数:外部マップの指定。
      今回はスゴく簡単なPerlスクリプトを使って大文字→小文字変換を行うので、プログラムを表す"prg:"に続けて変換に使うスクリプトの位置と名前を"/etc/apache2/scripts/A2a.pl"の絶対PATHで指定。
  • RewriteRule
    • 第一引数:書き換えをしたいURLのパターンを指定。
      今回は~soukaku/archives/以下にあるエントリーアーカイブのうち、大文字から始まるパスの書き換えをしたいので、書き換え対象のパターンを"^/~soukaku/archives/([A-Z].*)$"と指定。
      "([A-Z].*)$"の中身が、第二引数の"$1"に代入される。
    • 第二引数:書き換え後のURL。
      ~soukaku/archives/は共通、それ以下を"${A2a-map:$1}"と指定することで、"$1"に代入された第一引数の"([A-Z].*)$"の中身をRewriteMapで指定した外部マップを使って変換した結果に置き換える。
    • 第三引数:RewriteRuleのオプションを指定するためのフラグ。
      今回指定した"[R,L]"は、"R"が強制リダイレクト、"L"はルールの最後であることを示す。

大文字→小文字の変換は、こんな感じのスクリプトで行うことに。

# cat /etc/apache2/scripts/A2a.pl
#!/usr/bin/perl
open (STDIN) ;
while (<STDIN>) {
  chop ;
  tr/[A-Z]/[a-z]/;
  print $_."\n" ;
} ;
close (STDIN) ;

もちろん、単体で実行して

# echo "AbCdEfGhIjKl" | /etc/apache2/scripts/A2a.pl
abcdefghijkl

問題がないことを確認して、apacheを再起動すれば、OK。

今回の落とし穴

なはずだったのだけど、どうしてもうまく大文字小文字混在URLから小文字のみのURLへのリダイレクトが行われないので、あれやこれや調べていたら、

入出力にBuffered I/Oを使用しない(Perlなら$|を使う)

mod_rewrite - RewriteMap - とみぞーノート

という記述のあるページを発見!

早速、A2a.plを次のように

# cat /etc/apache2/scripts/A2a.pl
#!/usr/bin/perl
$| = 1;
while (<STDIN>) {
  chop ;
  tr/[A-Z]/[a-z]/;
  print $_."\n" ;
} ;

書き換えて、apache再起動したところ、想定どおりの動きをしてくれるようになりました。

今回のURL書き換えのパターンは、非常に簡単だったので変換のためのスクリプトも簡単な内容だったけど、変換スクリプトをうまく作れば、結構色んなことが出来そうです。

トラックバック(0)

コメントする