.htaccessによるURL書き換え「Rewrite(リライト)」で転送する方法
目次
ドメインやURLの変更による転送
.htaccessに記述することにより、外部から要求されたリクエストURLを書き換えてリダイレクトすることができます。
サイト移転、ファイル名の変更、ディレクトリ変更、更にはアクセス拒否まで絶大な効果を発揮します。
具体的には、外部から要求されたリクエストURLをApacheのmod_rewrite拡張モジュール(URL書き換えエンジン)を使用し、 正規表現を使って書き換えます。Redirectと異なり、リクエストの URL が実在しなくても転送が可能です。
注意:サーバーの環境
Apache1.2 以降で使用可能。 Apache のhttpd.confで、mod_rewriteモジュールが利用可能になっている必要があります。
.htaccess ファイルにおける Rewrite の記述方法
一般的な書式
RewriteEngine on RewriteBase / #WWWありで統一 RewriteCond %{HTTP_HOST} ^(example\.com)(:80)? [NC] RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L] #WWWなしで統一 RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ https://%1/$1 [R=301,L] #HTTPSを強制 RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] #ディレクトリの移転 RewriteRule ^old_dir(.*)$ /new_dir$1 [R=301,L] #ファイルの移転 RewriteRule ^old_dir/index\.html$ /new_dir/index.html [R=301,L] #クローラのアクセス禁止 RewriteCond %{HTTP_USER_AGENT} Badbot-1 [NC, OR] RewriteCond %{HTTP_USER_AGENT} Badbot-2 [NC] RewriteRule !^robots\.txt$ - [F] RewriteEngine off
注意すること
- 書き換え対象に正規表現の特殊文字が含まれている場合は、
\
(日本語環境では円マーク)でエスケープします。 - 書き換え対象
old_dir
が、/
から始まっていないことに注意してください。 - 書き換え後
/new_dir
が、/
から始まっていることに注意してください。
よく使うHTTPSとWWWなしにリダイレクトするルール
以下の2つはどちらも同じ動作をします。
それぞれ書く方法
RewriteEngine On # httpをhttpsにリダイレクト RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # wwwありをwwwなしにリダイレクト RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ https://%1/$1 [L,R=301]
同時に書く方法
RewriteEngine On # httpとwwwありの両方をhttpsとwwwなしにリダイレクト RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ https://%1%{REQUEST_URI} [L,R=301]
HTTPとWWWありで同時にアクセスがあった場合、複数のリダイレクト条件が連続して適用されることになり、サーバーからリダイレクト回数が多いという理由でで404エラーが返される場合があります。対処方法は今のところ不明です。
ファイルの移転
ファイル名や階層を変更したとき、古いURLにアクセスがあったら新しいURLに転送します。
RewriteRule ^old_dir/index\.html$ /new_dir/index.html [R=301,L]
解説
old_dir/index.html
のアクセスを/new_dir/index.html
にリダイレクトし、ここではファイルが永久に移転したことを通知しています。書き換えが行われたら処理終了。301
は恒久的なリダイレクトで、一時的なリダイレクトは302
を指定します。
ディレクトリの移転・転送
リクエストに対して、ディレクトリ全体が移転したことを知らせます。http://~
から記述することにより、外部ドメインへのリダイレクトも可能です。サイトの引っ越しなど、旧ドメインから新ドメインに転送に使います。
内部移転
階層を変更したときなどに使います。
RewriteRule ^old_dir(.*)$ /new_dir$1 [R=301,L]
外部移転
ドメイン変更した際、旧ドメインにアクセスがあった場合、新しいドメインのサイトに転送したいときに使います。工事中など、一時的な転送の場合は302
を使用します。
書式
RewriteRule ^old_dir(.*)$ https://www.example.com/new_dir$1 [R=301,L]
使用例
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L] RewriteRule (.*)$ https://www.example.com [R=301,L]
解説
は任意の1文字0回以上の繰り返しを意味しています。.*
(.*)
に該当する文字列が、後方参照$1
に入ります。
拡張子の変更
リクエストに対して、ファイルの拡張子を書き換えてリダイレクトします。
# 拡張子が .html のファイルを、全て .phpl に変更する RewriteRule ^(.*)\.html$ /$1.php [R=301,L] # 特定のディレクトリに対して、ファイルの拡張子を変更する RewriteCond %{REQUEST_URI} ^/example/ [NC] RewriteRule ^(.*)\.html$ /$1.php [R=301,L] # 特定のディレクトリを除いて、ファイルの拡張子を変更する RewriteCond %{REQUEST_URI} !^/example/ [NC] RewriteRule ^(.*)\.html$ /$1.php [R=301,L]
解説
特定のディレクトリに関しては、(行頭から)/example/
の大小を問わない文字を含む(もしくは含まない)アクセスに対して、拡張子.html
を.php
に書き換えてリダイレクトしています。
ここではファイルが永久に移転したことを通知しています。書き換えが行われたら処理終了。
サーバ移転(サイトの引越し)
リクエスト全体を、新しいドメインへリダイレクトします。
RewriteRule ^(.*)$ http://www.new-example.com/$1 [R=301,L]
解説
HTTPステータスコードR=301
(Moved Permanently) を付加することにより、URLが永久に移動したことを検索サイトのクローラに通知します。
この処理で、旧サイトのページランクを自動的にほぼ引き継ぐことができます。 検索サイトへの反映は、クローラにもよりますが、1週間から1ヶ月ほどかかります。
ドメインの統一
サーバーは1つのドメイン、例えばexample.comに対して、www.example.comでもリクエストを受け付けます。
host.comがサブドメインを使用している場合は、更にexample.host.comとwww.example.host.comでも閲覧可能になり、合計4つのサイトにアクセスが分散することになります。
これは、 SEO 対策上あまり好ましいことではありません。ここでは、Rewrite
を使って、www.example.comに統一する場合を記述します。
RewriteCond %{HTTP_HOST} ^(example\.com)(:80)? [NC] RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]サブドメインを使用している場合
RewriteCond %{HTTP_HOST} ^(example\.com)(:80)? [NC,OR] RewriteCond %{HTTP_HOST} ^(example\.host\.com)(:80)? [NC,OR] RewriteCond %{HTTP_HOST} ^(www\.example\.host\.com)(:80)? [NC] RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
アクセス制限
サーバ変数を取得して、アクセス制限を掛けます。
アクセス制限は、サーバに思わぬ負荷をかけることがあります。 不必要なアクセス制限はできるだけ掛けないようにしてください。十分にアクセス情報を解析してから設定してください。設定によっては正当な訪問者もアクセスできなくなる可能性があります。
[F]
は、「Forbidden(アクセス禁止)」を意味します。- 特殊文字の前に
\
(日本語環境では円マーク)を付加する事に注意してください。 REMOTE_HOST
は、サーバーによっては取得できない場合があります。
特定のホストからのアクセスを全て禁止する
RewriteCond %{REMOTE_HOST} ^example\.com$ [NC, OR] RewriteCond %{REMOTE_ADDR} ^192\.168\.1\. RewriteRule ^.* - [F]
解説
REMOTE_HOST
が取得できない場合は、REMOTE_ADDR
を使用してアクセス制限をかけます。
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/4\.0 \(compatible; MSIE 6\.0\)$ [NC] RewriteRule ^.* - [F]
特定の Referer からのアクセスを全て禁止する
RewriteCond %{HTTP_REFERER} ^http://www\.example\.com/bad\.html$ [NC] RewriteRule ^.* - [F]
特定の Referer 以外からのアクセスを全て禁止する(=特定の Referer からのみアクセスを全て許可する)
RewriteCond %{HTTP_REFERER} !^http://www\.example\.com/good\.html$ [NC] RewriteRule ^.* - [F]
直リンクを全て禁止する
RewriteCond %{HTTP_REFERER} !example\.com [NC] RewriteRule ^.* - [F]
解説
Referer がexample.comを含まないリクエストに対して、全てのアクセスを禁止します。
画像の直リンクを禁止する
RewriteCond %{HTTP_REFERER} !example\.com [NC] RewriteRule \.(jpg|png|gif)$ - [F]
解説
Referer がexample.comを含まないリクエストに対して、拡張子が.jpg
または.png
または.gif
へのアクセスを禁止します。
特定のホスト & 特定のブラウザからのアクセスを禁止する
RewriteCond %{REMOTE_ADDR} ^192\.168\.1\. RewriteCond %{HTTP_USER_AGENT} ^Mozilla/4\.0 \(compatible; MSIE 6\.0\)$ RewriteRule ^.* - [F]
特定の検索ロボット(クローラ)に対して、robots.txt以外のアクセスを禁止する
クローラのアクセス禁止は、サーバの負荷を伴います。そこで先に、ここに記述する全てのクローラをrobots.txt
で拒否しておきます。それを無視した悪質クローラだけを、最終的にここでアクセス禁止にします。
RewriteCond %{HTTP_USER_AGENT} Badbot-1 [NC, OR] RewriteCond %{HTTP_USER_AGENT} Badbot-2 [NC, OR] RewriteCond %{HTTP_USER_AGENT} Badbot-3 [NC, OR] RewriteCond %{HTTP_USER_AGENT} Badbot-n [NC] RewriteRule !^robots\.txt$ - [F]
解説
HTTP_USER_AGENT
が、Badbot-1
, からBadbot-n
の文字(文字の大小を区別しない)を含むクローラに対して、robots.txt
以外のアクセスを禁止します。
※悪質クローラに対する対策の詳細は:検索ロボット対策をご覧ください。
説明
ディレクティブ
ディレクティブと書式 | 初期値 | 説明 |
RewriteEngine on/off | off | 書き換えの可否を設定。 |
RewriteOptions inherit | - | inherit : 現在の設定値を親ディレクトリの設定値から強制的に継承する。 |
RewriteBase / | / | 書き換えのベースとなるパス(ベースが明白な場合は不要)。 |
RewriteCond テスト文字列 条件 パターン。 | - | 条件によるテスト文字列とパターンの比較。 |
RewriteRule パターン 置換対象。 | - | パターンを置換対象で置き換える。 |
オプション
[R] | 強制的にリダイレクト (Redirect) する。 [R=301] : 永久的に移動。HTTP レスポンスの「301 : Moved Permanently」を返します。 [R=302] : 一時的な移動。HTTP レスポンスの「302 : Moved Temporarily」を返します、デフォルト。 |
[F] | 強制的にアクセス禁止 (Forbidden) にする。 HTTP レスポンスの「403 : Forbidden」を返します。 |
[G] | 強制的に消去済み (Gone) にする。 HTTP レスポンスの「410 : Gone」を返します。 もはや存在しないページを消去済みとしてマークします。 |
[L] | 書き換えが行われたら終了 (Last) にする。 現在の書き換え後の URL が後続のルール によってそれ以上書き換えられることを防止します。 |
[NC] | パターンについて、文字の大小を区別しない(No Case)。 つまり、"A-Z" と "a-z" は区別されません。 |
[OR] | または。 |
正規表現
文字 | 説明 |
! | 否定。 |
. | 任意の1文字。 |
[ ] | 括弧内のいずれかの文字。 |
[^ ] | 括弧内のいずれかの文字以外。 |
| | または。 |
? | 直前の文字の0回または1回の繰り返し |
* | 直前の文字の0回以上の繰り返し。 |
+ | 直前の文字の1回以上の繰り返し。 |
( ) | 選択範囲の境界を明示する、もしくは後方参照を作成する。 |
^ | 行頭。 |
$ | 行末。 |
$n | (0 <= n <= 9) 後方参照。 n番目の( )内の値が入ります。 |
%{ } | サーバ変数の取得。 |
\ | (日本語環境では円マーク)正規表現の特殊文字をエスケープする。 |
サーバ変数
変数名 | 説明 |
HTTP_USER_AGENT | ブラウザの種類とバージョン。 |
HTTP_REFERER | 参照元の URL 。 |
HTTP_COOKIE | 設定されているクッキー情報。 |
HTTP_FORWARDED | プロキシサーバ情報。 |
HTTP_HOST | 接続要求しているホスト名。 |
HTTP_PROXY_CONNECTION | 接続先プロキシサーバとの接続状態。 |
HTTP_ACCEPT | ブラウザが認識可能なデータ形式。 |
DOCUMENT_ROOT | サイトのルートディレクトリ。 |
SERVER_ADMIN | サーバ管理者のメールアドレス情報。 |
SERVER_NAME | サーバのホスト名、ドメイン名、またはIPアドレス情報。 |
SERVER_ADDR | サーバのIPアドレス。 |
SERVER_PORT | 送信に使われたサーバのポート番号。 |
SERVER_PROTOCOL | 送信に使われたプロトコルの名前とレビジョン情報。 |
SERVER_SOFTWARE | 起動したサーバソフトウエアの名前とバージョン情報。 |
REMOTE_ADDR | リモートホストのIPアドレス情報。 |
REMOTE_HOST | リモートホストのドメイン名。 |
REMOTE_USER | ユーザの認証名。 |
REMOTE_IDENT | リモートホストのユーザ名。 |
REQUEST_METHOD | リクエストを送信した方法。 |
REQUEST_URI | リクエストされたURI。 |
SCRIPT_FILENAME | 現在実行しているスクリプト名。 |
PATH_INFO | クライアントから送られるパス情報。 |
QUERY_STRING | URL に付加して渡された "?" 以降の文字列。 |
AUTH_TYPE | ユーザを認証するときに使用する認証方法。 |
TIME_YEAR | サーバのシステム日付・年 |
TIME_MON | サーバのシステム日付・月 |
TIME_DAY | サーバのシステム日付・日 |
TIME_HOUR | サーバのシステム日付・時 |
TIME_MIN | サーバのシステム日付・分 |
TIME_SEC | サーバのシステム日付・秒 |
TIME_WDAY | サーバのシステム日付・曜日 |
TIME | サーバのシステム日付・Unix タイムスタンプ。 |