RewriteCondディレクティブ:URLのリライト/リダイレクトを行う条件を定義する

RewriteCond ディレクティブは、 RewriteRule ディレクティブによって URL のリライトやリダイレクトが行われる条件を定義します。一つまたは複数の条件を定義し、条件が真となった場合にその直後に記述された RewriteRule ディレクティブが評価されます。ここでは Apache の RewriteCond ディレクティブの使い方について解説します。

(Last modified: )

RewriteCondディレクティブの使い方

RewriteCond ディレクティブはリライト/リダイレクト先が実行される条件を定義する場合に使用します。書式は次のとおりです。

RewriteCond 文字列|変数 正規表現パターン [フラグ]

記述できる場所は httpd.conf, VirtualHost, Directory, .htaccess です。 .htaccess で設定する場合は AllowOverride FileInfo が設定されている必要があります。

RewriteCond ディレクティブでは文字列または変数に格納された値が正規表現パターンとマッチするかどうかを調べます。マッチした場合は、直後に記述された RewriteRule ディレクティブを評価します。

RewriteEngine on
RewriteCond xxx xxxxx
RewriteRule yyy yyyyy

RewriteCond ディレクティブで設定した条件が適用されるのは、直後に記述された RewriteRule ディレクティブだけです。別の RewriteRule ディレクティブに対して条件を設定したい場合は別途 RewriteCond ディレクティブを記述する必要があります。

複数の条件をANDまたはORで記述する

一つの RewriteRule ディレクティブに対して複数の RewriteCond ディレクティブを設定することができます。

RewriteEngine on
RewriteCond xxx1 xxxxx1
RewriteCond xxx2 xxxxx2
RewriteCond xxx3 xxxxx3
RewriteRule yyy yyyyy

複数の RewriteCond ディレクティブで記述した場合、特に指定しなければ AND の扱いとなります。上記の場合であれば 3 つの RewriteCond ディレクティブがすべて真となった場合だけ RewriteRule ディレクティブが評価されます。

複数の RewriteCond ディレクティブで記述した場合に、少なくとも一つの RewriteCond ディレクティブが真となった場合に RewriteRule ディレクティブが評価されるようにするには、フラグに[OR]を指定します。

RewriteEngine on
RewriteCond xxx1 xxxxx1 [OR]
RewriteCond xxx2 xxxxx2 [OR]
RewriteCond xxx3 xxxxx3
RewriteRule yyy yyyyy

上記の場合であれば 3 つの RewriteCond ディレクティブの少なくともひとつが真となった場合に RewriteRule ディレクティブが評価されます。

使用可能な変数の一覧

RewriteCond ディレクティブでは文字列または変数をそのあとに記述した正規表現パターンとマッチするかどうかを調べますが、変数を使用する場合は次の変数が使用可能です。

サーバーおよびリクエスト変数
%{HTTP_USER_AGENT}: クライアントのユーザーエージェント
%{HTTP_REFERER}: リファラー(参照元)
%{HTTP_COOKIE}: クライアントが送信したクッキー
%{HTTP_FORWARDED}: クライアントが送信した Forwarded ヘッダー
%{HTTP_HOST}: クライアントがアクセスしているホスト名
%{HTTP_PROXY_CONNECTION}: クライアントが送信した Proxy-Connection ヘッダー
%{HTTP_ACCEPT}: クライアントが送信した Accept ヘッダー
%{REQUEST_METHOD}: リクエストのメソッド(GET, POST, PUT, DELETE など)
%{REQUEST_URI}: リクエストされた URI
%{REQUEST_FILENAME}: リクエストされたファイルのパス(ファイルシステム上のパス)
%{QUERY_STRING}: リクエストのクエリストリング
%{REMOTE_ADDR}: クライアントの IP アドレス
%{REMOTE_HOST}: クライアントのホスト名
%{REMOTE_PORT}: クライアントのポート番号
%{REMOTE_USER}: 認証されたユーザー名
%{REMOTE_IDENT}: RFC 1413 によるリモートユーザー名
%{SERVER_NAME}: サーバーのホスト名
%{SERVER_ADDR}: サーバーの IP アドレス
%{SERVER_PORT}: サーバーのポート番号
%{SERVER_PROTOCOL}: リクエストのプロトコル(HTTP/1.1, HTTP/2 など)
%{SERVER_SOFTWARE}: サーバーソフトウェアの名前とバージョン

その他の変数
%{TIME_YEAR}: 現在の年(4 桁)
%{TIME_MON}: 現在の月(2 桁)
%{TIME_DAY}: 現在の日(2 桁)
%{TIME_HOUR}: 現在の時間(2 桁、24 時間表記)
%{TIME_MIN}: 現在の分(2 桁)
%{TIME_SEC}: 現在の秒(2 桁)
%{TIME_WDAY}: 曜日(0 = 日曜日, 6 = 土曜日)
%{TIME}: 現在の時刻(UNIX タイムスタンプ)

環境変数
%{ENV:変数名}: 環境変数の値

サーバー定義変数
%{DOCUMENT_ROOT}: サーバーのドキュメントルートディレクトリ
%{SCRIPT_FILENAME}: 実行されるスクリプトのファイル名
%{SCRIPT_NAME}: 実行されるスクリプトのパス

リクエストヘッダー
%{HTTP:ヘッダー名}: 特定の HTTP リクエストヘッダーの値

上記に記載した変数名の一覧の中から使用する変数名を %{変数名} として記述します。例えばリクエスト先のサーバ名が www.example.com と一致するか調べる場合は次のように記述します。

RewriteCond %{HTTP_HOST} ^www\.example\.com$

正規表現パターンを指定する

文字列または変数の値が、指定した正規表現パターンとマッチした場合に真となり直後に記述された RewriteRule が評価されます。 Apache で使用する正規表現は Perl 互換のものです。例えば www.example.com とマッチするパターンは次のように記述できます。

^www\.example\.com$

^ は先頭とマッチし、 $ は末尾とマッチします。この正規表現は、先頭から www.example.com で始まり、そしてこの文字列の後には何も記述されていない文字列とマッチします。

※ 正規表現を使った詳しいパターンの記述方法については「正規表現入門」を参照されてください。

正規表現パターンで利用可能な構文

正規表現パターンの箇所には正規表現のパターンを記述するだけでなく次の構文を記述することもできます。

!パターン       マッチしない場合にtrue
<パターン       文字列として比較、辞書順で小さい場合にtrue
>パターン       文字列として比較、辞書順で大きい場合にtrue
=パターン       文字列として比較、辞書順で等しい場合にtrue
<=パターン      文字列として比較、辞書順で等しいか小さい場合にtrue
>=パターン      文字列として比較、辞書順で等しいか大きい場合にtrue
-eqパターン     数値として比較、等しい場合にtrue
-geパターン     数値として比較、等しいか大きい場合にtrue
-gtパターン     数値として比較、大きい場合にtrue
-leパターン     数値として比較、等しいか小さい場合にtrue
-ltパターン     数値として比較、小さい場合にtrue
-neパターン     数値として比較、値が異なる場合にtrue(!-eqと同じ)

-d           実際に存在しディレクトリだった場合にtrue
-f           実際に存在しファイルの場合にtrue
-F           アクセス可能な有効なパスの場合にtrue
-h           -l と同じ(-lを使うとまぎらしい場合に使用)
-l           シンボリックリンクの場合にtrue
-L           -l と同じ(-lを使うとまぎらしい場合に使用)
-s           サイズが0でないファイルの場合にtrue
-U           アクセス可能な有効なURLの場合にtrue
-x           実行権限がある場合にtrue

フラグを設定する

RewriteCond ディレクティブではフラグを設定することで条件を判定する場合の挙動を変更することができます。

RewriteCond 文字列|変数 正規表現パターン [フラグ]

RewriteCond ディレクティブで用意されているフラグは 3 つですが、複数のフラグを設定する場合はカンマ(,)で区切って記述します。空白などをいれないようにご注意ください。

[フラグA,フラグB]

それぞれのフラグの使い方についてご説明します。

NCフラグ

文字列または変数の値と正規表現パターンを比較するときに大文字と小文字を区別せずに比較します。

RewriteCond 文字列|変数 正規表現パターン [NC]

ORフラグ

複数の RewriteCond ディレクティブを記述するときに、 AND ではなく OR で真か偽かを判定する。つまり複数のディレクティブのいずれか一つでも真だった場合は、直後にある RewriteRule ディレクティブを評価する。

RewriteCond 文字列|変数 正規表現パターン [OR]

NVフラグ

RewriteCond ディレクティブの変数名で HTTP ヘッダーを指定した場合に、レスポンスの Vary ヘッダーに HTTP ヘッダを設定します。

RewriteCond 文字列|変数 正規表現パターン [NV]

RewriteCondの使用例

RewriteCond ディレクティブの実際の使用例についてみていきます。

例えばクライアントの IP アドレスが 192.168.10.0/24 だった場合に、エラー画面を表示する場合は、次のように記述します。

RewriteEngine On
RewriteCond %{REMOTE_ADDR} "192\.168\.10\.\d+"
RewriteRule ^(.*)$ - [F]

www なしの URL へアクセスがあった場合に、 www 付の URL へリダイレクトする場合は次のように記述します。

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

また時刻の時が 00 時から 04 時までに /blog/ ディレクトリの中のファイルへアクセスがあった場合は、メンテナンス用のページにリダイレクトする場合は次のように記述します。

RewriteEngine On
RewriteCond %{TIME_HOUR} ^0[0-4]
RewriteRule ^blog/(.*)$ /maintenance/index.html [R=301,L]

では実際に試してみます。ドキュメントルートに .htaccess ファイルを作成し、先ほどの最後の例を記述しました。

RewriteCondディレクティブの使い方(1)

httpd.conf ファイルで、ドキュメントルートのディレクトリに対してはデフォルトで次のように設定されています。

<Directory "${SRVROOT}/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

次のように修正してください。修正が終わりましたら httpd.conf ファイルを保存し、 Apache を再起動しておいてください。

<Directory "${SRVROOT}/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride FileInfo
    Require all granted
</Directory>

それではブラウザから時刻の時が 00 時から 04 時ではない時間に http://localhost/blog/hello.html へアクセスしてください。

RewriteCondディレクティブの動作確認(2)

アクセスしたページがそのまま表示されました。今度は時刻の時が 00 時から 04 の間に同じ URL へアクセスしてください。

RewriteCondディレクティブの動作確認(3)

RewriteCond ディレクティブが真となるためその直後に記述された RewriteRule ディレクティブが評価され、指定したページへリダイレクトされました。

正規表現パターンで後方参照を使用する

RewriteCond ディレクティブの正規表現パターンの中で括弧()で囲んだパターンとマッチした文字列を、 RewriteRule ディレクティブの置換 URL の中で参照して使用することができます。次の例をみてください。

RewriteEngine on
RewriteCond %{QUERY_STRING} page=(.*)
RewriteRule ^index.html$ /%1/index.html? [R=301,L]

ドキュメントルートに設置した .htaccess に記述しました。 RewriteCond ディレクティブの正規表現パターンの中の括弧で囲まれた .* の部分にマッチした文字列を、 RewriteRule ディレクティブの置換 URL の中で %1 として参照しています。

今回の場合は、リクエストの中のクエリー文字列の page に対する値の部分が .* の部分にマッチします。そして直後の RewriteRule ディレクティブの中で、リダイレクト先のディレクトリとして参照した値を使用しています。なおリダイレクト先の最後に ? が記述してあるのは、リクエストにあったクエリー文字列をリダイレクト先では付けないようにするためです。

例えば http://localhost/index.html?page=blog へアクセスしてみます。

正規表現パターンで後方参照を使用する(1)

括弧で囲まれた .* の部分には blog がマッチするため、 http://localhost/blog/index.html へリダイレクトされます。

正規表現パターンで後方参照を使用する(2)

-- --

Apache の RewriteCond ディレクティブの使い方について解説しました。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。