.htaccess - mod_rewrite

mod_rewrite

以下は、mod_rewrite モジュールのディレクティブの一覧です。mod_rewrite は、多くのレンタルサーバーで利用可能なモジュールで、多くの設定レシピなどに RewriteCondRewriteRule が登場します。

RewriteEngine ディレクティブ

RewriteEngine ディレクティブは、URL の書き換えを行うエンジンです。本ディレクティブを有効、または無効にすることで、URL の書き換え処理を制御できます。デフォルトの設定値は Off になっているため、URL の書き換え処理を行う場合は、On にする必要があります。

# RewriteEngine を起動
RewriteEngine On
RewriteEngine を起動する例

本ディレクティブを On にすることで、新しい環境変数 SCRIPT_URISCRIPT_URL が追加されます。

RewriteBase ディレクティブ

RewriteBase ディレクティブは、RewriteRule ディレクティブで指定するリダイレクト先の URL のベースとなるディレクトリを相対パスで指定できます。RewriteBase ディレクティブで URL を指定しない場合、RewriteRule ディレクティブのベースとなる URL は .htaccess が置かれたディレクトリからの相対パスとなります。

/www
|-- .htaccess
|
|-- /contents
    |-- index.html
    |-- index.php
RewriteBase を行う配置例
# RewriteEngineを起動
RewriteEngine On

# ベースとなる変更前の URL(.htaccessを格納しているディレクトリ)
# /www (http://murashun.jp)

# RewriteBase でベースとなる URL を変更
# /www/contents (https://murashun.jp/contents)
RewriteBase /contents

# RewriteRule で index.php にリダイレクトする。
# RewriteBase で変更された URL は index.php にのみ影響します。
RewriteRule contents/index.html index.php [R=301,L]
contents ディレクトリの index.html を index.php に書き換える

失敗しやすい記述例として、以下があります。RewriteBase が影響するのは RewriteRule のリダイレクト先のパスだけであるという点に注意して下さい。以下の例では、どのディレクトリの index.html にアクセスしても、/contents/index.php にリダイレクトされてしまいます。

# RewriteEngine を起動
RewriteEngine On

# RewriteBase でベースとなる URL を変更
RewriteBase /contents

# RewriteRule で index.php にリダイレクトする。
RewriteRule index.html index.php [R=301,L]
contents ディレクトリの index.html を index.php に書き換える失敗例

RewriteRule ディレクティブ

RewriteRule ディレクティブは、URL の書き換えを行うディレクティブです。本ディレクティブを使用することで、URLを書き換えや、別のURLに移動(リダイレクト)させることでアクセスされたリソースに対してWebサーバの挙動を制御できます。

本ディレクティブでは、条件に一致するURLを、後続の "置換文字列" で書き換えます。また、書き換え処理に関しては、挙動を制御するためのフラグがいくつか用意されており、柔軟な書き換えルールが定義できるようになっています。複数のフラグを指定する場合は、"," で区切って指定します。

# RewriteEngine を起動
RewriteEngine On

# RewriteRule 条件 置換文字列 [フラグ]
RewriteRule sample1.html sample2.html [L]
sample1.html を sample2.html に書き換える
RewriteRule で利用可能なフラグ一覧
フラグシンタックス説明
B書き換え処理の前に英数字以外の文字をエスケープ(パーセントエンコーディング)します。
Cchain条件に一致したら、次の行に書かれた処理を連続して行います。これは通常の動作となるため、このフラグの用途は、条件が不一致の場合に後続の条件をスキップするために使われます。
CO=NAME:VALCookieCookie を設定できます。
DPIdiscardpathURI の PATH_INFO を破棄します。このフラグは、Apache 2.2.12 以降で利用可能です。
EENV環境変数の値を設定できます。値を設定する場合は [E=VAR:VAL]、値を削除する場合は [E=!VAL] とします。VAR は変数名、VAL は変数です。(例:[E=hoge:123])
FforbiddenHTTP 403(Forbidden:閲覧禁止)エラーを返します。以降のルールは実行しません。
Gclose[3] 404と410の違い
HTTP 410(Gone:消滅)エラーはHTTP 404(Not Found:未検出)エラーとよく似ています。410は二度と復活しない場合に使われ、404は単純に見つからない場合に使われます。
gone
HTTP 410(Gone:消滅)エラー [3] を返します。以降のルールは実行しません。
H=Content-handlerHandler実行するアプリケーションのハンドラを強制的に指定します。例えば、拡張子のないファイルをすべて php アプリケーションとして実行するには、以下のように記述します。
RewriteRule !\. - [H=application/x-httpd-php]
LlastURLの書き換え処理を終了します。以降のルールは実行しません。
Nnext書き換え処理を先頭から再実行します。その際にマッチングされる URL は最後に書き換えられた URL となります。無限ループを引き起こさないように注意して下さい。
NCnocase条件を評価する時、英字の大文字小文字を区別しません。
NEnoescape&% をエスケープせずそのままの文字列として扱います。
NSnosubreqサーバ内部で発生するサブリクエストには、書き換え処理を行いません。
Pproxy強制的に置換対象部を内部的にプロキシリクエストとして、プロキシモジュールを通して出力します。置換文字列は、http:// から始まるようなプロキシモジュールで扱える有効な URI である必要があります。無効な URI を指定した場合は、エラーが返されます。ただし、このフラグを使用する場合は、mod_proxy が組み込まれている必要があります。
PTpassthroughRewriteRule ディレクティブのターゲット(または、置換文字列)は、ファイルパスを想定していますが、代わりに URI として処理を行います。Alias、Redirect、ScriptAlias ディレクティブを利用する際に指定します。
QSAqsappend書き換え前の URL と置換文字列に、それぞれクエリ文字列(URL の ? 以降の文字列)が存在する場合、置換文字列の末尾に & と書き換え前の URL に指定されたクエリ文字列を追加します。本フラグを指定しない場合、クエリ文字列は置換文字列で上書きされます。
R[=code]redirect指定したURLにリダイレクトします。[R=301] のようにレスポンスコードを指定することもできます。指定できるレスポンスコードの範囲は 300 ~ 399 までとなります。それ以外のレスポンスコードを指定した場合は、置換文字列が破棄されます。レスポンスコードを指定しない場合は 302(Found) になります。また、temp(デフォルト値)、permanentseeother のシンボル名も指定できます。
S=numskip指定した数のルールをスキップします。例えば、[S=2] と指定すると、条件に一致した場合、以降のルールを 2 つスキップします。
T=MIME-typetypeターゲットファイルを強制的に指定した MIME-type にします。

本ディレクティブの処理順は、先頭行から条件に一致する行を探索していきます。条件に一致した場合は、先頭行に戻り、再度条件に一致する行を探索します。例えば、下記の書き方では、index1.html にアクセスすると index2.html に書き換わった後、再度探索を行い最終的に index3.html に書き換わります。

# RewriteEngine On | Off
RewriteEngine On

# index1.html → index2.html → index3.html
RewriteRule index1.html index2.html
RewriteRule index2.html index3.html
RewriteRule は条件に一致すると先頭行から再探索を行う

以下のような書き方では無限ループを引き起こし、500 internal server error が発生するため注意が必要です。特に RewriteRule では正規表現によるURL指定が可能であるため、意図せずに無限ループを引き起こすケースがあります。

# RewriteEngine On | Off
RewriteEngine On

# index1.html → index2.html → index1.html → ...
RewriteRule index1.html index2.html
RewriteRule index2.html index1.html
無限ループする場合は 500 internal server error が発生する

上記のように無限ループを防ぐためには、[L] フラグを設定すればよいかと思うかもしれません。しかし、以下の例では index1.html にアクセスしても最終的には index3.html に書き換わってしまいます。

# RewriteEngine On | Off
RewriteEngine On

# index1.html → index2.html に書き換わった時点で終了しない
RewriteRule index1.html index2.html [L]
RewriteRule index2.html index3.html [L]
最終的に index3.html に書き換わる

これは RewriteRule の機能を提供しているモジュール mod_rewrite の問題ですが .htaccess では [L] フラグが有効になりません。.htaccess の上位ファイルである httpd.conf では [L] フラグが正常に動作しますが .htaccess では再探索が優先されます。そのため、無限ループを防ぐには次章の "RewriteCond" を使用する方法が一般的です。

RewriteCond ディレクティブ

RewriteCond ディレクティブは、RewriteRule ディレクティブの書き換えルールの条件を定義できます。本ディレクティブは、RewriteRule ディレクティブの前に 1 つ以上設置できます。複数設置する場合は、オプションによって OR 条件にするか選択できます。オプションを省略した場合は、AND 条件として処理されます。本ディレクティブの条件を満たした場合、直後の RewriteRule ディレクティブの書き換えが行われます。条件を満たさない場合は、直後の RewriteRule ディレクティブが実行されないため、無限ループを防ぐ方法として有効です。

# Rewriteエンジンを起動
RewriteEngine On

# RewriteCond テスト文字列 条件 オプション
RewriteCond %{HTTP_HOST} ^(www\.)?murashun\.sakura\.ne\.jp$ [NC]

# RewriteRule 条件 置換文字列 [フラグ]
RewriteRule .* http://murashun.jp%{REQUEST_URI} [R=301,L]
sakura.ne.jp のドメインを murashun.jp に書き換える

RewriteRule と RewriteCond を組み合わせた処理順は、一般的な上から下に流れるプログラムとは異なります。基本的な処理順としては、以下になります。

  1. URL が 条件A にマッチし、かつ
  2. 文字列B が 条件C にマッチする場合
  3. URL を 文字列D に書き換える
RewriteCondの処理順
RewriteCondの処理順

プログラムで表現する場合は、以下になります。

if( URL =~ A && B =~ C){
  URL = D;
}
RewriteRule と RewriteCond の処理順

A は URL を書き換えるかの条件であるため、文字列 A を 文字列 D で書き換えるということではありません。

RewriteCond で使用できるパターンとオプションは以下のとおりです。

条件に利用できるパターン
パターン説明
!テスト文字列が条件と不一致である場合、true を返す
<テスト文字列を数値、または辞書順として大小比較を行い小さい場合、true を返す
>テスト文字列を数値、または辞書順として大小比較を行い大きい場合、true を返す
=テスト文字列を数値、または辞書順として等価比較を行い等しい場合、true を返す
-dテスト文字列のディレクトリが存在する場合、true を返す
-fテスト文字列のファイルが存在する場合、true を返す
-sテスト文字列のファイルが存在し、サイズが0byteでない場合、true を返す
-lテスト文字列がシンボリックリンクである場合、true を返す
-xテスト文字列に対して実行権限がある場合、true を返す
-Fテスト文字列に対してアクセス可能なパスである場合、true を返す
-Uテスト文字列に対してアクセス可能なURLである場合、true を返す
条件を評価する時のオプション
オプション説明
[OR]連続する RewriteCond のいずれかが true の場合に実行する。
省略時は、連続する RewriteCond がすべて true の場合に実行する。
[NC]条件を評価する時、大文字小文字を区別しない。

RewriteOptions ディレクティブ

RewriteOptions ディレクティブは、サーバ単位、またはディレクトリ単位にオプションを設定できます。指定できるオプションの文字列と効果は以下の通りです。

RewriteOptions ディレクティブに指定可能な値
説明
inherit上位ディレクトリの設定の継承が強制されるため、上位ディレクトリの設定が下位ディレクトリより優先して実行されます。
AllowAnyURIどのような URI も書き換えることが可能になります。mod_rewrite の脆弱性の修正を行ったことで発生した互換性の問題を回避するためのオプションです。特別な事情がない限り、使用することは非推奨です。
MergeBaseRewriteBaseの設定が下位ディレクトリにも継承されます。

関連記事

Category:
プログラミング
公開日:
更新日:
Pageviews:
33
Shares:
0
Tag:
.htaccess
Apache
HTTP
Server