RewriteRuleディレクティブ:URLのリライト/リダイレクトを行う

RewriteRule ディレクティブは、 URL のリライトを実際にどのように行うのかを定義します。クライアントからのリクエストに対して、指定した正規表現パターンにマッチした場合に URL のリライトを実行します。またフラグを設定してリライトの方法を指定することもできます。ここでは Apache の RewriteRule ディレクティブの使い方について解説します。

(Last modified: )

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

RewriteRule ディレクティブはリライトをどのように行うのかルールを定義するために使用します。書式は次のとおりです。

RewriteRule 正規表現パターン 置換URL [フラグ]

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

RewriteRule ディレクティブでは最初にクライアントからのリクエストが正規表現パターンとマッチするかどうかを調べます。マッチした場合は、置換 URL で指定した URL にリクエストを置き換えます。

リクエストのどの部分が正規表現パターンと比較されるのか

最初にクライアントからのリクエストの中で、どの部分が正規表現パターンとマッチするかどうかの対象となるのかについてです。クライアントからのリクエストが次のようなものだった場合で考えてみます。

http://www.example.com/blog/hello.html?num=10

正規表現パターンとマッチするかどうか対象となるのは、ホスト名とポート番号のあとからクエリーの前までの部分です。 RewriteRule ディレクティブが Directory ディレクティブのブロック内で記述されている場合、または .htaccess で記述されている場合に対象となるのは次の赤い文字の部分となります。

http://www.example.com/blog/hello.html?num=10

注意点として RewriteRule ディレクティブが VirtualHost ディレクティブのブロック内で記述されている場合、対象となるのは先頭の / を含めた次の赤い文字の部分となります。

http://www.example.com/blog/hello.html?num=10

どこで RewriteRule ディレクティブが記述されているのかによってパターンと比較する対象の文字列が異なるので注意してください。

また .htaccess の中で使用する場合で、 .htaccess がサブディレクトリの中に設置されている場合、そのサブディレクトリからの部分が対象となります。例えば blog ディレクトリの中に .htaccess が設置されていた場合は対象となる文字列は次の部分です。( Directory ディレクティブのブロックの中に記述する場合で、サブディレクトリが対象の場合も同じです)。

http://www.example.com/blog/hello.html?num=10

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

リクエストの中の対象の文字列が、指定した正規表現パターンとマッチした場合に URL のリライトが実行されます。 Apache で使用する正規表現は Perl 互換のものです。例えば blog/hello.html とマッチするパターンは次のように記述できます。

^blog/hello\.html$

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

正規表現パターンを次のように記述しても blog/hello.html とマッチしますが、この場合は myblog/hello.html や blog/hello.htmls などにもマッチします。

blog/hello\.html

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

置換URLを指定する

クライアントからのリクエストが正規表現パターンとマッチした場合、リクエストが置換 URLに指定したページの内容にリライト(外部のサイトの場合はリダイレクト)されます。置換 URL の記述方法は次の 4 つの方法があります。

相対パスで指定する場合は .htaccess が設置されているディレクトリからの相対パスで指定します。例えば /old ディレクトリに .htaccess がある場合に /blog/bye.html のページの内容でリライトする場合は次のように記述します。( Directory ディレクティブのブロックの中に記述する場合で、サブディレクトリが対象の場合も同じです)。

../blog/bye.html

※ 相対パスの基準となるディレクトリを RewriteBase ディレクティブを指定することもできます。詳しくは「RewriteBaseディレクティブ:リライト/リダイレクト先を相対パスで指定するときの基準ディレクトリを指定する」を参照されてください。

ドキュメントルートからの絶対パスで指定することもできます。例えば /blog/bye.html のページの内容でリライトする場合は次のように記述します。

/blog/bye.html

他のサイトの URL を指定した場合にはリライトではなくリダイレクトされます。リダイレクト先の URL を http:// などから始まる URL を指定します。現在のサイト内のページを http:// などから始まる URL で記述した場合、同じサイトだった場合にはリダイレクトではなくリライトされますのでご注意ください。

http://www.example.jp/myblog/hey.html

なお置換 URL として - を記述した場合にはリライトは行われません。フラグだけを適用する場合などに利用します。

-

リライトとリダイレクトの違い

RewriteRule ディレクティブを使用した場合、置換 URL として同じサイトのページを指定した場合にはリライトが行われ、別のサイトのページを指定した場合にはリダイレクトが行われます。

リライトというのは、ブラウザのアドレスバーに表示される URL は元のままですが、表示されるページの内容がリライト先のページの内容になります。それに対してリダイレクトというのはリダイレクト先の URL へ改めてリクエストが送信されるため、ブラウザのアドレスバーに表示される URL もリダイレクト先のものになります。

ただ RewriteRule ディレクティブで置換 URL として同じサイトのページを指定した場合でも、フラグで [R=301] のように指定することでリライトではなくリダイレクトにすることができます。(詳しくはフラグの箇所で解説します)。

# リライト
RewriteRule ^index\.html$ /new/index.html

# リダイレクト
RewriteRule ^index\.html$ /new/index.html [R=301]

# リダイレクト
RewriteRule ^index\.html$ http://www.example.com/

RewriteRuleディレクティブの動作確認

それでは実際に RewriteRule ディレクティブを記述してみます。今回はドキュメントルートに設置した .htaccess の中で記述します。リライトする内容は /old/hello.html を /new/hello.html へリライトし、 /old/search を https://www.google.co.jp/ へリダイレクトしてみます。

まずドキュメントルートに .htaccess を作成します。( .htaccess の中でリライトに関する設定が有効となるように httpd.conf にて AllowOverride ディレクティブの設定が必要です。詳しくは「AllowOverrideディレクティブ:.htaccessを使った設定の上書きを許可する」を参照されてください)。

RewriteRuleディレクティブを記述する(1)

.htaccess には次のように記述しました。

RewriteEngine on
RewriteRule ^old/hello\.html$ /new/hello.html
RewriteRule ^old/bye\.html$ /new/bye.html [R=301,L]
RewriteRule ^old/search$ https://www.google.co.jp/

※ RewriteEngine ディレクティブはリライト機能を有効にするためのディレクティブです。

クライアントからアクセスする /blog ディレクトリにはファイルは何も含まれていません。 /new ディレクトリには hello.html と bye.html が設置されています。

それでは最初に http://www.example.com/old/hello.html へアクセスしてください。

RewriteRuleディレクティブを記述する(2)

置換 URL が同じサイト内のページなので、リライトが行われます。その為、アクセスした URL はそのままで、置換 URL で指定した /new/hello.html のページの内容が画面に表示されます。

RewriteRuleディレクティブを記述する(3)

次に http://www.example.com/old/bye.html へアクセスしてください。

RewriteRuleディレクティブを記述する(4)

置換 URL が同じサイト内のページですが、フラグで [R=301] が指定されているのでリダイレクトが行われます。その為、置換 URL で指定した /new/bye.html のページが画面に表示されます。(アドレスバーに表示される URL はリダイレクト先の URL になります)。

RewriteRuleディレクティブを記述する(5)

最後に http://www.example.com/old/search へアクセスしてください。

RewriteRuleディレクティブを記述する(6)

置換 URL が別のサイトのページのためリダイレクトが行われます。その為、置換 URL で指定した https://www.google.co.jp/ のページが画面に表示されます。

RewriteRuleディレクティブを記述する(7)

このように RewriteRule ディレクティブを使用することで、リライトだけでなくリダイレクトも行うことができます。

複数のRewriteRuleディレクティブが記述されている場合に連続してリライトが行われるかどうか

複数の RewriteRule ディレクティブが記述されている場合、リクエストに対して一度だけではなく複数回リライトやリダイレクトが行われる場合があります。 例として /blog ディレクトリに .htaccess を設置し、次のような設定を記述した場合で試してみます。

RewriteEngine on
RewriteRule ^index_A\.html$ /blog/index_B.html [R=301]
RewriteRule ^index_B\.html$ /blog/index_C.html [R=301]

ブラウザから http://www.example.com/blog/index_A.html へアクセスすると、 .htaccess に記述された順番に正規表現パターンとマッチするかどうか調べていきます。今回の場合はまず最初の RewriteRule ディレクティブにマッチするため /blog/index_B.html へリダイレクトされたあと、二番目の RewriteRule ディレクティブにマッチするため /blog/index_C.html へリダイレクトされます。

複数のRewriteRuleディレクティブが記述されている場合に連続してリライトが行われるかどうか(1)

複数のRewriteRuleディレクティブが記述されている場合に連続してリライトが行われるかどうか(2)

次に .htaccess を次のように変更します。先ほどとは RewriteRule ディレクティブが記述された順序が変わっています。

RewriteEngine on
RewriteRule ^index_B\.html$ /blog/index_C.html [R=301]
RewriteRule ^index_A\.html$ /blog/index_B.html [R=301]

ブラウザから http://www.example.com/blog/index_A.html へアクセスすると、今回の場合はまず二番目の RewriteRule ディレクティブにマッチするため /blog/index_B.html へリダイレクトされたあと、それ以降には RewriteRule ディレクティブが存在しないためこれで終わりになるように思われますが、実際には今回も /blog/index_C.html へリダイレクトされます。

これは .htaccess に記述された RewriteRule ディレクティブのいずれかにマッチした場合、次の行からマッチしないか調べるのではなく改めて .htaccess の先頭からマッチするかどうか調べていくためです。その為、まず /blog/index_B.html へリダイレクトされたあと、あらためて最初の RewriteRule ディレクティブにマッチして /blog/index_C.html へリダイレクトされます。

なお正規表現にマッチしてリライトやリダイレクトが行われたあと、これ以上他の RewriteRule ディレクティブとマッチするかどうか調べないようにするためのフラグとして [L] が用意されているのですが、 .htaccess ではフラグ [L] が動作しません。

RewriteEngine on
RewriteRule ^index_A\.html$ /blog/index_B.html [R=301,L]
RewriteRule ^index_B\.html$ /blog/index_C.html [R=301,L]

そのため、ブラウザから http://www.example.com/blog/index_A.html へアクセスすると、 [L] フラグが記述されていても複数回のリダイレクトが実行されて /blog/index_C.html へリダイレクトされます。

フラグを設定する

RewriteRule ディレクティブではフラグを設定することでリライトを行う挙動を変更することができます。

RewriteRule 正規表現パターン 置換URL [フラグ]

複数のフラグを設定する場合はカンマ(,)で区切って記述します。空白などをいれないようにご注意ください。

[フラグA,フラグB]

数多くのフラグが用意されていますが、ここではよく使用するフラグに限定して開設します。

Lフラグ

これ以上のリライトを行いません。(ただし先に解説したように実際には適用されない場合があります)。

RewriteRule 正規表現パターン 置換URL [L]

Nフラグ

最後にリライトが行われた URL を対象として .htaccess (やその他の設定)の先頭から RewriteRule ディレクティブの正規表現パターンとマッチするものがないか調べます。

RewriteRule 正規表現パターン 置換URL [N]

R[=code]フラグ

リライトではなくリダイレクトを行います。 code には HTTP ステータスコードを指定できます。例えば永続的なリダイレクトを表す 301 リダイレクトを行いたい場合は R=301 、一時的なリダイレクトを表す 302 リダイレクトを行いたい場合は R=302 を指定します。 code を省略した場合は 302 でリダイレクトが行われます。

RewriteRule 正規表現パターン 置換URL [R=301]

NEフラグ

& や # などの特殊な文字を 16 進数のコードにエスケープしないようにします。例えば置換 URL にハッシュ(#)が含まれている場合、 NE フラグを設定していないと # が %23 にエスケープされてしまいリライトが正常に行われません。

RewriteRule 正規表現パターン 置換URL [NE]

例えば /blog ディレクトリに .htaccess を設置し次のように記述します。

RewriteEngine on
RewriteRule ^index_A\.html$ /blog/index_C.html#section1 [R=301]
RewriteRule ^index_B\.html$ /blog/index_C.html#section2 [R=301,NE]

ブラウザから /blog/index_A.html へアクセスすると /blog/index_C.html#section1 へリダイレクトされるのですが、 NE フラグが記述されていないためハッシュ(#)が %23 にエスケープされてしまいリダイレクト先が見つからなくなります。

フラグを設定する(1)

ブラウザから /blog/index_B.html へアクセスすると /blog/index_C.html#section2 へリダイレクトされるのですが、 NE フラグが記述されているためハッシュ(#)がエスケープされず目的の URL へリダイレクトされます。

フラグを設定する(2)

NCフラグ

[NC] フラグは正規表現パターンがマッチするかどうかを評価するときに大文字と小文字を区別しません。

RewriteRule 正規表現パターン 置換URL [NC]

[F] フラグを記述した場合はクライアントには 403 Forbidden が返されます。 [G] フラグを記述した場合はクライアントには 410 Gone が返されます。

Fフラグ、Gフラグ

[F] フラグと [G] フラグはリライトを実行する代わりにエラーを返す場合に使用します。置換 URL として - を記述します。

RewriteRule 正規表現パターン - [F]
RewriteRule 正規表現パターン - [G]

[F] フラグを記述した場合はクライアントには 403 Forbidden が返されます。 [G] フラグを記述した場合はクライアントには 410 Gone が返されます。

例えば /blog ディレクトリに .htaccess を設置し次のように記述します。

RewriteEngine on
RewriteRule ^index_A\.html$ - [F]
RewriteRule ^index_B\.html$ - [G]

ブラウザから /blog/index_A.html へアクセスすると 403 Forbidden が返されます

フラグを設定する(3)

ブラウザから /blog/index_B.html へアクセスすると 410 Gone が返されます。

フラグを設定する(4)

QSA

[QSA] フラグとリクエストに付けられていたクエリー文字列と置換 URL に指定したクエリー文字列をまとめてリライトまたはリダイレクト先に付加する場合に使用します。

RewriteRule 正規表現パターン - [QSA]

詳しい使い方はこのあとのクエリー文字列の扱いの箇所をご覧ください。

E=[!環境変数名][:値]

[E=環境変数名] フラグは正規表現パターンがマッチした場合に環境変数名に対して値を設定します。

RewriteRule 正規表現パターン 置換URL [E=環境変数名]

例えば次のような使い方をすることができます。

RewriteEngine on
RewriteCond AAA ^BBB(CCC)$
RewriteRule ^(.*)$ - [E=TEST:%1]
RewriteCond %{ENV:TEST} DDD
RewriteRule EEE FFF [L]

最初の RewriteCond ディレクティブでリクエストの一部の値を取得し、次の RewriteRule ディレクティブで後方参照を使って環境変数 TEST に取得した値を設定します。続いて次の RewriteCond ディレクティブで環境変数 TEST の値が DDD とマッチした場合、その次の記述された RewriteRule ディレクティブを評価します。

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

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

RewriteEngine on
RewriteRule ^old/(.*)$ /new/$1 [R=301]

ドキュメントルートに設置した .htaccess に記述しました。正規表現パターンの中の .* の部分にマッチした文字列を、置換 URL の中で $1 として参照しています。

例えば /old/hello.html へアクセスがあった場合、 .* の部分には hello.html がマッチするため、 /new/hello.html へリダイレクトされます。また /old/bye.html へアクセスがあった場合、 .* の部分には bye.html がマッチするため /new/bye.html へリダイレクトされます。

後方参照を使用することで、ディレクトリに含まれるすべてのファイルを別のディレクトリに同じ名前でリダイレクトさせたい場合などに一つの RewriteRule ディレクティブで記述することができます。

クエリー文字列の扱いについて

リクエストにクエリー文字列が含まれる場合、リライトやリダイレクトされたときに同じクエリー文字列が付加されます。次の例をみてください。

RewriteEngine on
RewriteRule ^old/hello.html$ /new/hello.html [R=301]

ドキュメントルートに設置した .htaccess に記述しました。

それではクエリー文字列付きの http://www.example.com/old/hello.html?num=8 へアクセスします。

クエリー文字列の扱いについて(1)

リクエストに付いていたクエリー文字列はリダイレクト先の URL にもクエリー文字列がそのまま付加されるので http://www.example.com/new/hello.html?num=8 へリダイレクトされます。

クエリー文字列の扱いについて(2)

クエリー文字列をリライトやリダイレクト先に付加しない

リクエストに付いていたクエリー文字列をリライトやリダイレクト先に付加しないようにするには、置換 URL の最後にはてな(?)を記述します。

RewriteEngine on
RewriteRule ^old/hello.html$ /new/hello.html? [R=301]

それでは先ほどと同じようにクエリー文字列付きの http://www.example.com/old/hello.html?num=8 へアクセスしてください。

クエリー文字列の扱いについて(3)

今度はリダイレクト先にはクエリー文字列が付加されずに http://www.example.com/new/hello.html へリダイレクトされます。

クエリー文字列の扱いについて(4)

リライトやリダイレクト先に新しいクエリー文字列を付加する

リライトやリダイレクト先に新しいクエリー文字列を付加することは可能です。その場合、リクエストに付加されていたクエリー文字列は付加されません。次の例ではリダイレクト先に指定したクエリー文字列を付加しています。

RewriteEngine on
RewriteRule ^old/hello.html$ /new/hello.html?userid=7 [R=301]

それでは先ほどと同じようにクエリー文字列付きの http://www.example.com/old/hello.html?num=8 へアクセスしてください。

クエリー文字列の扱いについて(5)

リダイレクト先には置換 URL で指定したクエリー文字列だけが付加されて、リクエストのクエリー文字列は付加されずに http://www.example.com/new/hello.html?userid=7 へリダイレクトされます。

クエリー文字列の扱いについて(6)

リクエストのクエリー文字列にリライトやリダイレクト先で指定したクエリー文字列を追加して付加することも可能です。フラグの [QSA] を指定します。

RewriteEngine on
RewriteRule ^old/hello.html$ /new/hello.html?userid=7 [R=301,QSA]

それでは先ほどと同じようにクエリー文字列付きの http://www.example.com/old/hello.html?num=8 へアクセスしてください。

クエリー文字列の扱いについて(7)

リダイレクト先にはリクエストのクエリー文字列に加えて置換 URL で指定したクエリー文字列が追加されて http://www.example.com/new/hello.html?userid=7&num=8 へリダイレクトされます。

クエリー文字列の扱いについて(8)

-- --

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

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

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