88171.net

RewriteMapとQUERY_STRING

このWebサイトは歴史だけは無駄に長く、各エントリのURIをごっそり変えたことが何度かあった。 他所様から古いURIにリンクしてもらっているケースがあるので、気づいたものは片っ端からデータベースに突っ込んで、mod_rewriteで新しいURIにリダイレクトしている。

具体的にはこんなイメージ。 クールなURIを装うための涙ぐましい努力。

RewriteCond %{REQUEST_URI} ^(/.+)$
RewriteCond ${map:%1} !=""
RewriteRule .* ${map:%1} [R=permanent,L]

ただ最近、tDiaryを使っていた頃の/d/?date=YYYYMMDDという形式のURIをマッピングしようとしたら、うまくいかなかった。 調べてみると理由は単純で、REQUEST_URIにはquery stringが含まれていなかった。

REQUEST_URI
The path component of the requested URI, such as "/index.html". This notably excludes the query string which is available as its own variable named QUERY_STRING.

mod_rewrite - Apache HTTP Server Version 2.4

つまり"%{REQUEST_URI}?%{QUERY_STRING}"をキーにすればいいんじゃないの、ということなのだけど、少しだけ工夫が必要。

RewriteCond "%{REQUEST_URI}?%{QUERY_STRING}" ^(/.+?)\??$
RewriteCond ${map:%1} !=""
RewriteRule .* ${map:%1} [QSD,R=permanent,L]

QUERY_STRINGが空だった場合に?が残らないようなパターンにした。 あとQSDフラグを追加して、リダイレクト先にquery stringを渡さないようにした。

正規表現がPerl互換なおかげで最短一致が使えた。 RewriteCondでゴリゴリせずに済んで本当に良かった。