【Apache】.htaccessを使ってリダイレクトする方法と書き方(リダイレクトループの注意)

Apache

Apacheを制御できる.htaccessを使ってリダイレクトする方法と書き方を紹介します。
また設定の仕方によってリダイレクトループになってしまうので、なぜそうなるのかその注意点を説明します。

リダイレクト[Redirect]とは

リダイレクト[Redirect]とは、異なるURLへ転送することです。

リダイレクト[Redirect]はすべてのコンテキスト(サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccess)で使用できます。

Redirectの書き方

Redirect [status] URL-path URL
Redirect 301 /redirect-from-url /redirect-to-url

Redirectには、2つのstatusがあります。

  • 301 – 永続的なリダイレクトの設定に使用
  • 302 – 一時的に引っ越したことを表す(デフォルト)

一時的な場合は302を指定します。恒久的にリダイレクトさせたいときは、301をステータスに指定します。
何も指定しないときは、302になります。

URL-pathには、リダイレクトさせたいURLを書き、URLにはリダイレクト先のURLを書きます。
Redirectを使う場合は、ドメインのあとのパスをすべて書く必要があります。
そのため、エイリアスなどを使って記述を短くすることもできます。
エイリアスについては、httpd.confの設定と基本的な使い方を参照してみてください。

リダイレクト先は外部サイトでもOKです。

転送の仕組みの確認方法

Chromeの検証ツールのNetworkタブを開きます。
すると、上から順番に行われたリクエストが表示されます。
レスポンスは、Status Codeで確認できます。302など300番代でサーバーからレスポンスが返ってきた場合は、
Response HeadersのLocationのパスに再度リクエストを送ります。
そしてそのパスでリクエストを送り、サーバーからレスポンスがあって300番代なら同じことを繰り返します。
そうしてレスポンス(Status Code)が200などになって最終的に表示されたり、404などで表示されなかったりといった結果が返されます。

ポイントは、リダイレクトを指定した場合、サーバー内部で処理されるのではなく、
ブラウザにレスポンスを返してロケーションで再度リクエストを要求しているという点です。

301リダイレクトと302リダイレクトの挙動の違い

302リダイレクトの場合は、即座に変更が反映されます。
301リダイレクトの場合は、永続的な変更になるため、ブラウザでリダイレクトの情報をキャッシュとして保持します。そのため、一度301リダイレクトを設定した場合、その後に変更してもキャッシュの影響で即座に反映されません。

301リダイレクトの挙動を確認するためには、Chromeの検証ツールのNewworkタブにある、Sizeという項目の(disk cache)というのがあります。
このdisk cacheのに、ブラウザが保持しているリダイレクトの設定が含まれています。
そのcacheが残っている限り、たとえファイルを変更しても永続的に前のリダイレクト先に飛んでしまいます。

ブラウザ内のキャッシュがクリアされれば、ファイルの変更が反映されますが、
ユーザーの環境に依存してしまうため、301リダイレクトは注意が必要です。

Redirectの注意点(パスが繰り返される)リダイレクトループ

Redirectの処理は、前方一致で処理されます。

Redirect 301 /redirect-from-url /redirect-from-url/redirect-to-url

上の場合、/redirect-from-urlが一致するものに関しては、何度も上のリダイレクト処理が実行されることになります。
つまり、上のようなサブディレクトリに転送したい場合、
ドメイン/redirect-from-url/redirect-from-url/redirect-from-url/redirect-from-url
…といったURLに延々とリダイレクトされてしまうことになります。

これは、RewriteとRewriteCondを使うことで解消できます。

RewriteEngine On
RewriteBase /some-folder/
# ファイルが存在しないかつディレクトリが存在しない場合
RewriteCond %{HTTP_HOST} ^www\.hoge\.com
RewriteCond %{HTTP_HOST} !^/some-folder/subfolder2/
RewriteRule (.*) subfolder2 [R]

!^/some-folder/subfolder2/というので、not条件のため、
上のようにすると、二回目以降は、すでにsubfolder2があるので条件から外れることになります。
このあたりは、【Apache】RewriteCondの使い方を参照してみてください。

Apache

Posted by devsakaso