書き換えを有効にするには、最初にRewriteEngineディレクティブの設定で[on]を指定する必要があります。
RewriteEngine on|offRewriteEngine Directive - mod_rewrite - Apache HTTP Server
RewriteRuleの実行に条件を付けられます。
RewriteCond TestString CondPattern [flags]RewriteCond Directive - mod_rewrite - Apache HTTP Server
TestStringの文字列がCondPatternの条件に一致する場合のみ、書き換えが実行されます。
TestStringには%{HTTP_HOST}のような、サーバー変数 (Server-Variables) などを指定できます。
変数 | 内容 |
---|---|
HTTP_USER_AGENT | |
HTTP_REFERER | |
HTTP_COOKIE | |
HTTP_FORWARDED | |
HTTP_HOST | |
HTTP_PROXY_CONNECTION | |
HTTP_ACCEPT |
変数 | 内容 |
---|---|
︙ |
変数 | 内容 |
---|---|
︙ |
変数 | 内容 |
---|---|
︙ |
変数 | 内容 |
---|---|
THE_REQUEST | ブラウザからサーバへ送られたHTTPリクエストであり、"GET /index.html HTTP/1.1" のような内容 |
REQUEST_URI | リクエストURIのパスの部分であり、"/index.html" のような内容 |
REQUEST_FILENAME | リクエストに一致する、ファイルまたはスクリプトへのローカル ファイルシステムへのフルパス (full local filesystem path) |
HTTPS | SSL/TLSで接続されているならば"on" 、さもなくば"off" |
︙ |
内容 | |
---|---|
%{ENV:variable} | 環境変数の値 |
%{SSL:variable} | SSL環境変数の値 |
%{HTTP:header} | HTTPヘッダの値 |
%{LA-U:variable} | |
%{LA-F:variable} |
CondPatternはPerl互換の正規表現で記述します。この条件の先頭を「!」から始めると、条件の意味が反転します。また正規表現で指定する以外に、下表のような特別な記述法が用意されています。
指定方法 | 一致する条件 |
---|---|
<CondPattern | |
>CondPattern | |
=CondPattern | |
-d | ディレクトリ |
-f | 通常のファイル |
-s | ファイルサイズが0より大きい、通常のファイル |
-l | シンボリック リンク |
-x | 実行可能ファイル |
-F | |
-U |
たとえばファイルやディレクトリが存在するときに適用するCondPatternに「!」を付加することで、それらが存在しないときにのみ書き換えを実行できます。
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f
flagsでは特別な機能を追加できます。このflagsは、必ず[]の中に記述します。
キーワード | 意味 |
---|---|
NC (nocase) | 大文字と小文字を区別しない |
OR (ornext) | 続く条件をORで判定する |
NV (novary) |
RewriteCondを複数記述すると、それらが一致した場合のみ書き換えが実行されます。
RewriteCond testString1 condPattern1 RewriteCond testString2 condPattern2
これをいずれかの条件が一致した場合のみとするには、flagsにORを指定します。
RewriteCond testString1 condPattern1 [OR] RewriteCond testString2 condPattern2
ORの指定は、それを指定しない場合よりも優先して判定され、
RewriteCond A [OR] RewriteCond B RewriteCond C [OR] RewriteCond D
は、「(A OR B) AND (C OR D)」の条件となります。mod rewrite - how to use "AND", "OR" for RewriteCond on Apache? - Stack Overflow
RewriteCondは、直後に記述された1つのRewriteRuleにしか作用しません。よって、
RewriteBase / RewriteCond %{REQUEST_URI} bb RewriteRule aa zz [R] RewriteRule cc yy [R]
とした場合、「http://example.com/aacc」のURLでも、2番目のRewriteRuleが適用されてしまいます。これは正しくは、
RewriteBase / RewriteCond %{REQUEST_URI} bb RewriteRule aa zz [R] RewriteCond %{REQUEST_URI} bb RewriteRule cc yy [R]
とします。
RewriteBase / RewriteCond %{REQUEST_URI} bb RewriteRule aa zz [R]
このとき「http://example.com/aacc」のURLでは、RewriteRuleのパターンは一致するものの、RewriteCondの条件が不一致のため、書き換えは起こりません。一方で次のURLならば、書き換えられます。
http://example.com/aabbcc ↓ http://example.com/zz
サブドメインを統一するには修正するホスト名をRewriteCondでマッチさせ、そのサブドメイン部を書き換えます。
RewriteBase / RewriteCond %{HTTP_HOST} ^example\.com [NC,OR] RewriteCond %{HTTP_HOST} ^www2\.example\.com [NC] RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteRule Pattern Substitution [flags]RewriteRule Directive - mod_rewrite - Apache HTTP Server
PatternはPerl互換の正規表現で、たとえばURLが「http://www.example.com/path/to/file.html」ならば、この太字部分と比較されます。
キーワード※1 | 説明 |
---|---|
NC (nocase) | 大文字と小文字を区別しない |
NE (noescape) | URLエスケープを行わない |
R[=code] (redirect) ※2 | リダイレクトを強制する。オプションでHTTPのステータスコードを明示できる |
F (forbidden) | 403 (Forbidden) ステータスコードを返す。Denyディレクティブより柔軟に条件を適用できる。Lが暗黙的に指定され、他の規則は評価されない |
G (gone) | 410 (Gone) ステータスコードを返す。Lが暗黙的に指定され、他の規則は評価されない |
L (last) ※3 | 書き換えを終了し、これ以上書き換えルールが適用されないようにする |
︙ |
複数のフラグを指定する場合は、カンマで区切ります。
FやGフラグを指定するときはSubstitutionを"-"とします。これはURLを書き換えないことを意味します。要求を拒否するときには、書き換える理由はありません。F|forbidden - RewriteRule Flags - Apache HTTP Server Version 2.2
RewriteRuleは書き換え時にURLエンコード (パーセントエンコード) を行います。そのためクエリ文字列に特殊文字を含むとき、URLが書き換えられた場合とそうではない場合でクエリが異なってしまいます。
http://example.com/index.html?q=%E3%81%82 ↓ (クエリの「%E3%81%82」をURLエンコード。「%」の部分が「%25」になる) http://example.com/index.html?q=%25E3%2581%2582
この問題はNE (noescape) フラグを指定して、エスケープを抑制することで解決できます。Pukiwiki移転の際に便利なmod_rewriteの設定メモ
RewriteRule ^(.*)$ http://example.com/$1 [NE]NE|noescape - RewriteRule Flags - Apache HTTP Server
PatternがURLのパスに一致した場合、ドキュメントルート以下のすべてのURLがSubstitutionに書き換えられます。よってルールが、
RewriteRule bb zz [R]
の場合、URLに「bb」が含まれているならば、ドキュメントルート以下のURLが「zz」となります。
http://example.com/aabbcc ↓ http://example.com/home/aaa/www/zz
このときPatternによって書き換えられる範囲は、RewriteBaseディレクティブで設定できます。RewriteBase Directive - mod_rewrite - Apache HTTP Server
RewriteBase / RewriteRule bb zz [R]
この場合は、次のようになります。
http://example.com/aabbcc ↓ http://example.com/zz
Patternは正規表現として評価されるため、
RewriteBase / RewriteRule ^[0-9]+ z$0 [R]
とすると、次のように書き換えられます。
http://example.com/123A ↓ http://example.com/z123
RewriteRule \.exe - [F]
拡張子が.exeであるファイルへのアクセスを禁止し、403を返します。
RewriteRule oldproduct - [G]
パスにoldproductが含まれるならば、410を返します。
URLのクエリ ストリングを、パス名の一部であるかのように偽装します。このようにして作成されたURLを、静的URLと呼称します。
この方法を用いると、たとえば
http://example.com/?a=1&b=2(動的URL)
のようなクエリを含むURLを
http://example.com/a=1/b=2/(静的URL)
のように表せます。
これを実現するにはアクセスされたときに本来のURLに書き換えるように、RewriteRuleで次のように指定します。この例ではクエリの数が変化することも考慮して、2パターンの書き換え規則を定義しています。
RewriteRule ^([^/]+)/ ?$1 [L] RewriteRule ^([^/]+)/([^/]+)/ ?$1&$2 [L]
なおこのようにしてURLを書き換えた場合、静的URLが相対パスの基準となります。そのため画像や他ページへのリンクが相対パスで記述されている場合には、パスがずれます。
example.com/a//b/のようなURLを、example.com/a/b/に書き換える方法を考えます。
RewriteCond %{THE_REQUEST} //+ RewriteRule ^(.*)$ /$1 [R=301,L]
%{THE_REQUEST}はHTTPリクエストの"GET /a//b/ HTTP/1.1"のような内容であり、そこに正規表現の"//+"が一致したならば、パス全体を書き換えます。そしてRewriteRuleで書き換えるときに、複数のスラッシュは1つに切り詰められます。
書き換えず、削除したものとして通知するならば次のようにします。
RewriteCond %{THE_REQUEST} //+ RewriteRule .? - [G]
連続するスラッシュへの対応は、サイトによって異なります。