2015/12/28 17:50:03

mod_rewrite

mod_rewriteとは

Apacheのモジュールのひとつで、アクセスURLを正規表現で書き換えることができます。リダイレクト処理を行うのに便利なモジュールです。

モジュールの解説ドキュメントによれば

URLを操作するためのスイス製のアーミーナイフ

と例えられるほど、非常に複雑な処理を行えます。

URLからURLへ、同一サーバ内URLだろうが、別サーバURLだろうが問いません。 引数を含む動的URLを通常のHTMLファイルのような静的URLに見せることも可能です。 素晴らしく詳細なマニュアルもありますが、機能が多いだけに情報量が多く読むのも面倒だと思いますので、ここでは、mod_rewriteを使用すると便利な場面を想定して具体的に解説してみたいと思います。

mod_rewriteの基本

ひとまず、mod_rewriteはApacheのモジュールです。インストールされていなければ、サーバのroot権限が無い限り新たにインストールすることは難しいかと思います。インストールされている場合、使用するには2つの方法があります。

  • httpd.confに設定する
  • .htaccessに設定する

.htaccess による設定は処理が遅くなります。root権限があるなら、httpd.confで設定しましょう。

mod_rewriteを利用したり、設定する記述は、テキストとして書き込みます。 バーチャルサーバを使用している場合は、バーチャルサーバごとに記述する必要があります。

サイトの引越し通知

サーバの移転でサイトのURLが変わった場合、よく引越しページを用意することがあるかもしれませんが、元のサイトのページ数が多い場合、大変な作業になることがあります。そこで、ファイルが見つからない時のエラーページを用意して、一個のファイルで引越しを通知するという方法を考えるかもしれません。あわせて、refreshタグで引っ越し先に飛ばしてしまうかもしれません。しかし、どちらにしても、あるページを経由するというステップを避けることができません。

mod_rewriteはこの引越し通知に力を発揮します。

RewriteEngine on
RewriteRule ^/(.*)$ http://www.newserver.com/$1 [R=301,L] 

とすることで、あるサーバへのリクエストを http://www.newserver.com/ にリダイレクトさせることができます。この方法が有用な点は、R=301 という指定で、HTTPステータスコードの301(=Moved Permanently、永久に移動したという意味)を返した上で、URLを書き換えてジャンプさせることができるということです。人が、ブラウザで普通にアクセスしていれば、何も気にせず新しいURLにアクセスすることができます。URLの変更は、引越し先のページで告知すれば済みます。また、ロボットのアクセスには、ステータスコード301によってURLが変更されたことがわかります。Googleなら、引越し前のページにリンクしているリンク元を、引越し先に引き継ぐことができます。ほぼ、PageRankを引き継げると言えます。

サイト内で、ディレクトリ構造を変更した場合は

RewriteEngine on
RewriteRule ^/abc/(.*)$ /new/$1 [R=301,L] 

とすれば、/abc/ というディレクトリ内へのアクセスを /new/ へリダイレクトすることができます。

もしも、/abc/ の中の .html という拡張子のファイルだけ移動したいのであれば

RewriteEngine on
RewriteRule ^/abc/(.*)\.html$ /new/$1.html [R=301,L] 

とします。

RewriteEngine on
RewriteRule ^/abc/(.*)$ /new/$1 [R=301,L]
RewriteEngine on
RewriteRule ^/def/(.*)\.html$ /new2/$1.html [R=301,L]
RewriteEngine on
RewriteRule ^/ghi/(.*)\.(html|htm)$ /new3/$1.$2 [R=301,L]
RewriteEngine on
RewriteRule ^/jkl/(.*)$ http://www.sample.com/$1 [R=301,L] 

という感じで、複数の条件を連ねることもできます。正規表現を使って複雑な条件を指定することが可能です。

動的ページを静的ページに見せる

掲示板やブログツールによるページは、CGI によって動的に生成されることがままあります。その際は、URLの最後が .cgi で終る場合が多くなります。URLの末尾が .cgi で終ると検索エンジンのロボットに無視されることが多くなります。検索エンジンロボットは、引数によって些細に変化する動的ページにはあまり対応していないからです。

しかし、それなりにコンテンツとして価値のある動的ページは検索エンジンにクロールさせたいものです。現時点では、おおまかに、引数付きのCGIへのリンクはクロールされる可能性が高いようです。中でも、クエリー式(/sample.cgi?a=123&b=456)よりも、PATH_INFO式(/sample.cgi/123/456)の方が、クロールされやすいと言われています。

しかし、それらは、小細工でしかありません。

mod_rewriteを使えば、完全に静的ファイルへのアクセスで動的ファイルの結果を返すようにすることが可能です。

例えば、http://www.sample.com/cgi-bin/sample/sample.cgi?a=123&b=456

というURLを静的なアドレスでアクセスできるように以下のように設定します。

RewriteEngine on
RewriteRule ^/cgi-bin/sample/([0-9A-Za-z]+)/([0-9A-Za-z)]+)\.html$ /cgi-bin/sample/sample.cgi?a=$1&b=$2 [L]

すると、http://www.sample.com/cgi-bin/sample/123/456.html にアクセスすると、

http://www.sample.com/cgi-bin/sample/sample.cgi?a=123&b=456 にアクセスしたのと同じ結果が返るようになります。

ポイントは、クエリーに含まれるはずの引数データを、静的ファイルのURLパス内に含む形にしてアクセスを受け、mod_rewriteによってその情報を正規のクエリーに変換している点です。見せかける静的アドレスはいか様でもかまいません。mod_rewriteによって、変換できれば問題ありません。

実例集

apache で処理する URI を思いのままに操ろうと思えば、mod_rewrite が良い武器になる。
たとえば、以下のようなニーズを簡単に満たしてくれる。

  • ある条件でアクセスを拒否したい
  • URLが変更になったので、一括でリダイレクトしたい
  • 動的アドレスを静的アドレスに見せたい

ある条件でアクセスを拒否したい

.htaccess ファイルへのアクセスを 403 Forbidden にします。

RewriteEngine On
RewriteRule \.htaccess - [F]

/foo/* へのアクセスを 403 Forbidden にします。

RewriteEngine On
RewriteRule ^/foo/.* [F]

/bar/* へのアクセスを 410 Gone にします。

RewriteEngine On
RewriteRule ^/bar/.* [G]

USER_AGENT が MSIE のアクセスで、かつ /bar/* へのアクセスを 410 Gone にします。

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^/bar/.* [G]

ある bot のアクセスを 403 Forbidden にします。

RewriteCond %{HTTP_USER_AGENT}   ^foobot.*
RewriteCond %{REMOTE_ADDR}       ^123\.45\.67\.[0-9]+$
RewriteRule ^/.* - [F]

URLが変更になったので、一括でリダイレクトしたい

/foo/ へのアクセスを、 /bar/ で返します。(URI のパスは /foo/ のまま)

RewriteEngine on
RewriteRule ^/foo/$ /bar/

/foo/ へのアクセスを、 /bar/ にリダイレクトします。(URI のパスは /bar/ に書き換わります)
[R=301] をつけると、HTTPステータスコード「301 Moved Permanently」を吐き出してリダイレクトします。

RewriteEngine on
RewriteRule ^/foo/$ /bar/ [R=301]

/foo/ へのアクセスを、 /bar/ にリダイレクトします。(URI のパスは /bar/ に書き換わります)
[R=302] をつけると、HTTPステータスコード「302 Found」を吐き出してリダイレクトします。

RewriteEngine on
RewriteRule ^/foo/$ /bar/ [R=302]

リダイレクト先をURLで指定すると、「302 Found」でリダイレクトされる。

RewriteEngine on
RewriteRule ^/foo/$ http://www.example.com/bar/

R=301 とすることで、「301 Moved Permanently」を明示できる。

RewriteEngine on
RewriteRule ^/foo/$ http://www.example.com/bar/ [R=301]

動的アドレスを静的アドレスに見せたい

RewriteEngine on
RewriteRule ^/([0-9A-Za-z]+)/([0-9A-Za-z]+)$ /cgi-bin/example.cgi?q=$1&opt=$2

See also

サイト内検索