mod_rewrite:色々な設定

■シンプルなリダイレクト例

    RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?key=$1
!-f は存在するファイル名にはルールを適用しない
!-d は存在するディレクトリ名にはルールを適用しない

FLAG

[NC] - 大文字小文字を区別せずにパターンと一致するかどうかをテストします。
[OR] - いずれかのRewriteCondにあてはまる場合にRewriteRuleを適用します。[OR]を明示しない場合、
自動でANDになります。
[L] - Rewrite機能による変換を打ち切ることを示す。
以降にRewriteがあっても飛ばす
[PT] -「Path Through」させる。つまり、[L]と似ているが、
Rewrite による変換を終りにして、Rewrite 以外の変換(ScriptAliasなど)に渡す。
[R] - Redirect させる。つまり、変換されたURLを「Redirect」するものとして、
「HTTP/1.1 302 Moved Temporary」のレザルトコードと、
Loacation ヘッダに変換されたURLがセットされたレスポンスを返す。
このフラグは結果として変換結果を確定し、[L]フラグを指定したのと同様に、
以降のルールの適用をキャンセルする。
[F] - FORBIDDEN を返す。つまり、アクセスが禁止されていることを示すために、
「HTTP/1.1 403 FORBIDDEN」のレスポンスを返す。
このフラグは結果として変換結果を確定し、[L]フラグを指定したのと同様に、
以降のルールの適用をキャンセルする。
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^TRACE [OR]
RewriteCond %{REQUEST_METHOD} ^TRACK [OR]
RewriteCond %{REQUEST_METHOD} ^OPTIONS
RewriteRule .* - [F]
■/hoge/ を /fuga/ に rewrite(リダイレクト)する。
RewriteEngine on
RewriteRule ^/hoge/$ /fuga/
■/hoge/ 以下を /fuga/ 以下にまとめて rewrite(リダイレクト)する。
RewriteEngine on
RewriteRule ^/hoge/(.*)$ /fuga/$1
■/hoge/ 以下で末尾が .jpg のリクエストのみを /fuga/ 以下に rewrite(リダイレクト)する。
RewriteEngine on
RewriteRule ^/hoge/(.*.jpg)$ /fuga/$1
■/hoge/ 以下で末尾が .jpg か .gif のリクエストのみを /fuga/ 以下に rewrite(リダイレクト)する。
RewriteEngine on
RewriteRule ^/hoge/(.*).(jpg|gif)$ /fuga/$1.$2
■/cgi-bin/hoge/fuga を /cgi-bin/example.cgi?q=hoge&opt=fuga に rewrite(リダイレクト)
(いわゆる、動的アドレスを静的アドレスに変換するってやつ)
RewriteEngine on
RewriteRule ^/cgi-bin/([0-9A-Za-z]+)/([0-9A-Za-z]+)$ /cgi-bin/example.cgi?q=$1&opt=$2
■リダイレクト時のブラウザのURL欄
mod_rewrite で rewrite(リダイレクト)処理を行ったとき、以下のようにサーバパスで
rewrite(リダイレクト)させると、ブラウザのURL欄は書き換わらない。
RewriteEngine on
RewriteRule ^/hoge/$ /fuga/
例えば、
http://www.example.com/hoge/ にアクセスすると、
http://www.example.com/fuga/ の中身が、
URL欄は http://www.example.com/hoge/ のまま表示される。

しかし、以下の例では、リダイレクトと同時にURL欄が書き換わる。

RewriteEngine on
RewriteRule ^/hoge/$ /fuga/ [R=301]
RewriteEngine on
RewriteRule ^/hoge/$ /fuga/ [R=302]
RewriteEngine on
RewriteRule ^/hoge/$ http://www.example.com/fuga/
最後の URL にリダイレクトさせるパターンは、同じサーバ内の URL であっても、飛び先を URL で記述するとブラウザのURL欄が書き換わります。
同一サーバ内であれば、URLにリダイレクトさせると無駄にログも増えるのであまりオススメしません。

■%2F問題

Apache1.X 系で mod_rewrite を使う場合、URLに「%2F」が含まれると思い通りに動作しない問題があります。
(Apache2.X 系でも同様ですが、Apache2.0.46 以降では「AllowEncodedSlashes On」により回避できます。)

例えば、以下のような書き換えを記述したとします。

RewriteEngine on
RewriteRule ^/keyword/(.*)$ /cgi-bin/script.cgi?k=$1
想定としては、
http://www.example.com/keyword/hogefuga というアクセスに対して
http://www.example.com/cgi-bin/script.cgi?k=hogefuga の結果を返します。

hogefuga の部分が色々と変化するわけです。

この際、
http://www.example.com/keyword/hogefuga/hage
http://www.example.com/cgi-bin/script.cgi?k=hogefuga/hage となりますが、

http://www.example.com/keyword/hogefuga%2Fhage
http://www.example.com/cgi-bin/script.cgi?k=hogefuga%2Fhage とならず、404エラーになります。

直接、
http://www.example.com/cgi-bin/script.cgi?k=hogefuga%2Fhage にアクセスするとこの問題は起きません。

先にも書きましたが、Apache2.0.46 以降では httpd.conf に「AllowEncodedSlashes On」を記述することにより回避できます。
しかし、Apache1.X の環境ではなかなか回避できずにはまる要素だと思います。
■アクセスを拒否する
どこかにリダイレクトするのではなく、特定のアクセスにエラーを返せます。

.htaccess へのアクセスを拒否する。

RewriteEngine On
RewriteRule .htaccess - [F]
■/hoge/ 以下へのアクセスに 403 Forbidden を返します。
RewriteEngine On
RewriteRule ^/hoge/.* [F]
■/hage/ 以下へのアクセスに 410 Gone を返します。
RewriteEngine On
RewriteRule ^/hage/.* [G]
■複数の RewriteRule
RewriteRule は複数かけます。

■/hoge/ 以下を /fuga/ 以下にリダイレクとした上に /fuga/hage/ 以下のものは /foo/ 以下にリダイレクトする。

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1
RewriteRule ^/fuga/hage/(.*) /foo/$1
上の例で、/hoge/ 以下を /fuga/ 以下にリダイレクとさせた時点で処理を終わらせる、つまり次のリダイレクトを実行させないようにするには [L] を付加します。
RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [L]
RewriteRule ^/fuga/hage/(.*) /foo/$1
■RewriteRule のオプション
これ以外にもいろいろありますが。

HTTPステータスコードを吐く [R=ステータスコード]

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [L,R=301]

RewriteRule ^/fuga/hage/(.*) /foo/$1

■大文字、小文字を区別しない [NC]
RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [NC,L]
RewriteRule ^/fuga/hage/(.*) /foo/$1
■ある条件が揃ったらリダイレクト
RewriteCond を使えば、ある条件に合致したときだけリダイレクトするということも、もちろん可能です。

■HTTP_HOST が www.example.com だったら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^/(.*) /$1
■HTTP_HOST が www.example.com じゃなかったら RewriteRule を適用する。
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.example.com$
RewriteRule ^/(.*) /$1
■HTTP_HOST が www.example.com で HTTP_USER_AGENT に MSIE が含まれていたら RewriteRule を適用する。
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^/(.*) /$1
RewriteCond を複数並べると AND でつながっていく。OR にしたい場合は [OR] をつける。

■HTTP_HOST が www.example.com であるか、または HTTP_USER_AGENT に MSIE が含まれていたら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$ [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^/(.*) /$1
RewriteCond の条件で大文字、小文字を区別しない場合は [NC] をつける。

■HTTP_USER_AGENT に MSIEmsieMsIeMSiE などが含まれていたら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} MSIE [NC]
RewriteRule ^/(.*) /$1
VirtualHost配下であっても
DocumentRoot配下であっても

どこでもかんでも.htaccessを設置したい場所は

AllowOverride FileInfo Options

これ書いてやらんと有効にならんね。

で、その.htaccessを内には


RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^$ http://www.microsoft.com/japan/windows/products/winfamily/ie/default.mspx
RewriteCond %{HTTP_USER_AGENT} Mozilla
RewriteRule ^$ http://mozilla.jp/firefox/ [R=302]
こんな風に書いたらリライトさる。

これは例えばVH切っていて、
その設定ファイル内にrewriteが記述してあってあったとしても

その跳び先のディレクトリをAllowOvewriteで
FileInfoの設定してやることで
リライトでそのディレクトリに跳んで
またそのディレクトリ内の.htaccessをを見て更に跳んでくれるという
そういう寸法らしい

よく出来てらっしゃる