Rewrite (URL書き換え)

RewriteEngine (Rewriteの有効化)

書き換えを有効にするには、最初にRewriteEngineディレクティブの設定で[on]を指定する必要があります。

RewriteEngine on|off
RewriteEngine Directive - mod_rewrite - Apache HTTP Server

RewriteCond (書き換えを実行する条件の指定)

RewriteRuleの実行に条件を付けられます。

RewriteCond TestString CondPattern [flags]
RewriteCond Directive - mod_rewrite - Apache HTTP Server

TestStringの文字列がCondPatternの条件に一致する場合のみ、書き換えが実行されます。

TestString

TestStringには%{HTTP_HOST}のような、サーバー変数などを指定できます。

サーバー変数 (Server-Variables)
HTTP headers 内容
HTTP_USER_AGENT  
HTTP_REFERER  
HTTP_COOKIE  
HTTP_FORWARDED  
HTTP_HOST  
HTTP_PROXY_CONNECTION  
HTTP_ACCEPT  
connection & request 内容
 
server internals 内容
 
date and time 内容
 
specials 内容
HTTPS SSL/TLSで接続されているならば"on"、さもなくば"off"
 
その他の変数
  内容
%{ENV:variable} 環境変数の値
%{SSL:variable} SSL環境変数の値
%{HTTP:header} HTTPヘッダの値
%{LA-U:variable}  
%{LA-F:variable}  

CondPattern

CondPatternPerl互換の正規表現で記述します。この条件の先頭を「!」から始めると、条件の意味が反転します。また正規表現で指定する以外に、下表のような特別な記述法が用意されています。

CondPatternの代替値
指定方法 一致する条件
<CondPattern  
>CondPattern  
=CondPattern  
-d ディレクトリ
-f 通常のファイル
-s ファイルサイズが0より大きい、通常のファイル
-l シンボリック リンク
-x 実行可能ファイル
-F  
-U  

たとえばファイルやディレクトリが存在するときに適用するCondPatternに「!」を付加することで、それらが存在しないときにのみ書き換えを実行できます。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

flags

flagsでは特別な機能を追加できます。この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

複数のRewriteRuleに適用する場合

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]

参考

  • useful examples - Apache HTTP Server
  • more useful examples - Apache HTTP Server

RewriteRule (書き換えパターン)

RewriteRule Pattern Substitution [flags]
RewriteRule Directive - mod_rewrite - Apache HTTP Server

Patternは、たとえばURLが「http://www.example.com/path/to/file.html」ならば、この太字部分と比較されます

flags引数
キーワード※1 説明
NC (nocase) 大文字と小文字を区別しない
NE (noescape) URLエスケープを行わない
R[=code] (redirect) ※2 リダイレクトを強制する。オプションでHTTPのステータスコードを明示できる
L (last) ※3 書き換えを終了し、これ以上書き換えルールが適用されないようにする
 
RewriteRule Flags - Apache HTTP Server
※1 キーワードは、かっこ内のものでも可
※2 設定を誤ると、リダイレクトがループします
※3 apache - RewriteRule Last [L] flag not working? - Stack Overflow

複数のフラグを指定する場合は、カンマで区切ります。

特殊文字のエスケープの防止

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

利用例

静的URL (static URLs)

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が相対パスの基準となります。そのため画像や他ページへのリンクが相対パスで記述されている場合には、パスがずれます。