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 headers】 HTTP_ACCEPT クライアントがサポート可能なMIMEタイプ HTTP_COOKIE クッキーに関するデータ HTTP_FORWARDED プロキシのURI HTTP_HOST リクエスト先のサーバ名 HTTP_PROXY_CONNECTION プロキシの接続形態 HTTP_REFERER 参照元のURL HTTP_USER_AGENT ユーザーエージェント 【connection & request】 AUTH_TYPE 認証方式 CONN_REMOTE_ADDR ピアIPアドレス CONTEXT_PREFIX CONTEXT_DOCUMENT_ROOT IPV6 IPv6ならon、そうでないならoff PATH_INFO パス情報 QUERY_STRING クエリ文字列 REMOTE_ADDR リモートアドレス REMOTE_HOST リモートホスト REMOTE_IDENT IDENTによるユーザー名 REMOTE_PORT ポート番号 REMOTE_USER 認証されたユーザー名 REQUEST_METHOD HTTPリクエストメソッド(GETなど) SCRIPT_FILENAME REQUEST_FILENAMEと同じ 【server internals】 DOCUMENT_ROOT DocumentRootディレクティブの値 SCRIPT_GROUP スクリプトグループのグループ名 SCRIPT_USER スクリプトオーナーのユーザー名 SERVER_ADDR サーバアドレス SERVER_ADMIN ServerAdminディレクティブ SERVER_NAME ServerNameディレクティブ SERVER_PORT ServerNameディレクティブのポート番号 SERVER_PROTOCOL リクエストのプロトコル名とバージョン SERVER_SOFTWARE サーバのソフトウェア情報 【date and time】 TIME_YEAR 現在の年(2021) TIME_MON 現在の月(01,02,...,12) TIME_DAY 現在の日(01,02,...,31) TIME_HOUR 現在の時(00,01,...,23) TIME_MIN 現在の分(00,01,...,59) TIME_SEC 現在の秒(00,01,...,59) TIME_WDAY 現在の曜日(0,1,...6) 0=Sunday TIME 日付と時刻(20211231235959) 【specials】 API_VERSION APIバージョン CONN_REMOTE_ADDR ピアIPアドレス HTTPS HTTPSならonそうでないならoff IS_SUBREQ サブリクエストならtrue REMOTE_ADDR リモートホストのIPアドレス REQUEST_FILENAME リクエストに一致するファイルやスクリプトのパス REQUEST_SCHEME リクエストスキーマ REQUEST_URI リクエストURIのパス部分 THE_REQUEST 完全なリクエストライン(GET /index.html HTTP/1.1)
上記に記載した変数名の一覧の中から使用する変数名を %{変数名} として記述します。例えばリクエスト先のサーバ名が www.example.com と一致するか調べる場合は次のように記述します。
RewriteCond %{HTTP_HOST} ^www\.example\.com$
また次の変数も利用可能です。
%{ENV:variable} 指定した環境変数の値 %{SSL:variable} 指定したSSL環境変数の値 %{HTTP:header} 指定したHTTPリクエストヘッダの値
リクエストに対して各変数に実際にどのような値が格納されるのかを簡単に確認してみます。下記は //www.example.com/old/hello.html?num=10 へアクセスした場合に各変数に格納された値です。
%{HTTP_HOST} www.example.com %{HTTP_USER_AGENT} Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/88.0.4324.104%20Safari/537.36 %{IPV6} off %{QUERY_STRING} num=10 %{REMOTE_ADDR} 192.168.10.104 %{REQUEST_METHOD} GET %{SCRIPT_FILENAME} D:/pg/Apache/Apache24/htdocs/old/hello.html %{DOCUMENT_ROOT} D:/pg/Apache/Apache24/htdocs %{SERVER_PROTOCOL} HTTP/1.1 %{SERVER_SOFTWARE} Apache/2.4.43%20(Win64)%20PHP/7.4.7 %{TIME_YEAR} 2021 %{TIME_MON} 02 %{TIME_DAY} 07 %{TIME_HOUR} 21 %{TIME_MIN} 39 %{TIME_SEC} 56 %{TIME_WDAY} 0 %{TIME} 20210207213956 %{API_VERSION} 20120211:92 %{HTTPS} off %{REMOTE_ADDR} 192.168.10.104 %{REQUEST_FILENAME} D:/pg/Apache/Apache24/htdocs/old/hello.html %{REQUEST_SCHEME} http %{REQUEST_URI} /old/hello.html %{THE_REQUEST} GET%20/old/hello.html%3fnum=10%20HTTP/1.1 %{HTTP:Accept-Encoding} gzip,%20deflate %{HTTP:Accept-Language} ja,en;q=0.9,en-US;q=0.8
正規表現パターンを指定する
文字列または変数の値が、指定した正規表現パターンとマッチした場合に真となり直後に記述された 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
例えば 2020/12/31 23:59:59 までは //example.com/ へリダイレクトを行い、それ以降は //www.example.jp/ へリダイレクトする場合は次のように記述します。
RewriteEngine On RewriteCond %{TIME} <20201231235959 RewriteRule ^(.*)$ //example.com/$1 [R=301,L] RewriteCond %{TIME} >=20210101000000 RewriteRule ^(.*)$ //example.jp/$1 [R=301,L]
※ 上記の例ですが実際には 2 つ目の RewriteCond ディレクティブは記載しなくても同じ結果になるのですが、分かりやすいようにあえて記載してあります。
フラグを設定する
RewriteCond ディレクティブではフラグを設定することで条件を判定する場合の挙動を変更することができます。
RewriteCond 文字列|変数 正規表現パターン [フラグ]
RewriteCond ディレクティブで用意されているフラグは 3 つですが、複数のフラグを設定する場合はカンマ(,)で区切って記述します。空白などをいれないようにご注意ください。
[フラグA,フラグB]
それぞれのフラグの使い方についてご説明します。
NCフラグ
文字列または変数の値と正規表現パターンを比較するときに大文字と小文字を区別せずに比較します。
RewriteCond 文字列|変数 正規表現パターン [NC]
ORフラグ
複数の RewriteCond ディレクティブを記述するときに、 AND ではなく OR で真か偽かを判定する。つまり複数のディレクティブのいずれか一つでも真だった場合は、直後にある RewriteRule ディレクティブを評価する。
RewriteCond 文字列|変数 正規表現パターン [OR]
NVフラグ
RewriteCond ディレクティブの変数名で HTTP ヘッダーを指定した場合に、レスポンスの Vary ヘッダーに HTTP ヘッダを設定します。
RewriteCond 文字列|変数 正規表現パターン [OR]
※ Vary ヘッダーについては少し古い記事ですがこちらが参考になりました。「」
RewriteCondディレクティブの動作確認
それでは実際に RewriteCond ディレクティブを記述してみます。今回はドキュメントルートに設置した .htaccess の中で記述します。今回は wwww なしの example.com へアクセスがあった場合に www 付きの www.example.com へリダイレクトする処理を記述します。その為に、 RewriteCond ディレクティブを使って www なしの example.com へアクセスがあったかどうかの条件判断を記述します。
まずドキュメントルートに .htaccess を作成します。( .htaccess の中でリライトに関する設定が有効となるように httpd.conf にて AllowOverride ディレクティブの設定が必要です。詳しくは「AllowOverrideディレクティブ:.htaccessを使った設定の上書きを許可する」を参照されてください)。
.htaccess には次のように記述しました。
RewriteEngine on RewriteCond %{HTTP_HOST} ^example\.com$ RewriteRule ^(.*)$ //www.example.com/$1 [R=301,L]
※ RewriteEngine ディレクティブはリライト機能を有効にするためのディレクティブです。
それでは www なしの //example.com/new/hello.html へアクセスしてください。
RewriteCond ディレクティブが真となるためその直後に記述された RewriteRule ディレクティブが評価され、 www 付きの www.example.com へリダイレクトされます。
正規表現パターンで後方参照を使用する
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 ディレクティブの中で、リダイレクト先のディレクトリとして参照した値を使用しています。なおリダイレクト先の最後に ? が記述してあるのは、リクエストにあったクエリー文字列をリダイレクト先では付けないようにするためです。
例えば //www.example.com/index.html?page=old へアクセスしてみます。
括弧で囲まれた .* の部分には old がマッチするため、 //www.example.com/old/index.html へリダイレクトされます。
-- --
Apache の RewriteCond ディレクティブの使い方について解説しました。
( Written by Tatsuo Ikura )

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