.htaccessによるリダイレクト徹底解説

久しぶりに「WordBench京都」でスピーカーをやらせていただきました。
今回は「.htaccess特集」ということで、その中でも、この仕事を何年やってても未だに良くわからない(笑)リダイレクトについて、お話しさせていただきました。

 

詳しい内容はスライドを見ていただくとして、.htaccess を使ってリダイレクトを行う際に、つまづきやすいポイントをいくつか取り上げて、ブログ記事として整理しておきたいと思います。

Redirect permanent と、RewriteRule はどう使い分けるのか

実は、私がずっと疑問に思っていたのはこれなんですね(笑)
たとえば、サーバー移転の時のリダイレクトの書き方は

Redirect permanent / http://example.com/

と、

RewriteEngine On
RewriteRule ^(.*)$ http://example.com/$1

の2通りの書き方があるわけですが、ググってもたいてい1つ目の書き方が書かれているだけで、リダイレクトの内容が難しくなるといきなり RewriteEngine On とか出てきて、なぜ2通りの書き方があるのかという疑問に答えてくれる記事は少ないんです。

で、何が違うのかというと、mod_rewrite の機能を使うか使わないかの違いです。
mod_rewrite は、Webサーバーの拡張機能で、Webサーバー内でURLの書き換え(リダイレクト)を行うものです。
拡張機能なので、入っていないサーバーもあります。
入っていなければ、1つ目の書き方を使うしかありません。
入っていれば、2つ目の書き方も使えます。
使えるかどうかは、レンタルサーバーであれば「よくある質問」を見ればたいてい載っています。

上記のようなパターンでは必要性を感じませんが、mod_rewrite があると、無い時にできなかった次のようなことが出来るようになります。

  • ブラウザの種類、リファラ、アクセス日時など、リダイレクトするときの条件を指定できる
    (キャンペーン時期だけいつもと違うトップページを見せる、ieだけ違うページを見せる、など)
  • 上記の応用で、柔軟なアクセス制限ができる
    (特定IPからのアクセス禁止、他サイトからの直リンク禁止、自社IPのみ管理画面へのアクセスを許可、など)
  • リダイレクト先の指定にも正規表現が使えるので、テスト用サーバーから本番用サーバーに移行のときなど、リダイレクト先のドメイン名が変わるときにいちいち書き換えなくていい

.htaccess があちこちにあるときのトラブル

.htaccess は、リクエストされたURLの示す、最も下位のディレクトリのものが適用されます。
上位ディレクトリの設定に対して、下位ディレクトリの設定が「項目ごと」上書きされます。
項目の内容が丸ごと上書きされるので、上位ディレクトリの同じ項目の設定は無視されることになります。

このへんがちょっと難しいんですね。
例として、下記のようなディレクトリ構成を考えます。

20131015.png

ここで、oldディレクトリにBasic認証をかけるために .htaccess を置くとします。
このとき、ルートディレクトリにある .htaccess のリダイレクト指定とかは、oldディレクトリにも有効です。
これは、認証とリダイレクトは設定項目(ディレクティブ)が違うからです。

では、ルートディレクトリとoldディレクトリ、それぞれに .htaccess を置いて、両方でリダイレクト指定をするとどうなるでしょうか?

ルートディレクトリの指定が無視される場合

  • ルートディレクトリ
    RewriteEngine On
    RewriteRule ^old/test1\.html$ test2.html
  • oldディレクトリ
    RewriteEngine On
    RewriteRule ^test2\.html test3.html

ここで、次のようなURLにアクセスするとどうなるでしょうか?

old/test1.html

結果は、リダイレクトは行われず、old/test1.html にアクセスします。
流れとしては、リクエストされたURLの最も下位のディレクトリがoldディレクトリなので、まず、その指定が適用されます。
oldディレクトリの .htaccess には、test1.html に関する指定がないので、ここで終了です。
ルートディレクトリにある
 .htaccess のリダイレクト指定は無視されます。

同じディレクティブの指定がある場合、そのディレクティブごと上書きしてしまうからです。
(oldディレクトリにある .htaccess にリダイレクト指定がなければ、その上位にさかのぼってルートディレクトリの設定が適用されます)

上位ディレクトリにさかのぼって適用される場合

これだけでも勘違いしやすいのですが、もう一つ、勘違いしやすいことがあります。

.htaccess でリダイレクトされると、書き換えられたURLで、改めて最も下位のディレクトリにある .htaccess が適用されます。
さきほどとはちょっと変えたリダイレクト指定にしてみます。

  • ルートディレクトリ
    RewriteEngine On
    RewriteRule ^test1\.html$ test2.html
  • oldディレクトリ
    RewriteEngine On
    RewriteRule ^test1\.html$ /test1.html

ここで、次のようなURLにアクセスするとどうなるでしょうか?

old/test1.html

まず、oldディレクトリの設定でURLが書き換えられて、ルートディレクトリへのアクセスになります。

old/test1.html → /test1.html

すると今度は、改めて、ルートディレクトリのリダイレクト設定が適用されるのです。

/test1.html → /test2.html

こういうのは、頭で考えてもよくわからないことが多いです。
紙に書きだして、1ステップずつURLを書き直してみるのがいいと思います。
できれば、テスト環境で試してみたほうがいいですね。

RewriteBaseは、リダイレクト後のパスのベース

もう一つ、勘違いしやすいものがあります。
RewriteBase です。

RewriteBase というからには、RewriteRule のベースになるのかと思いきや、実は、リダイレクト後のパスにのみ適用されます。
リダイレクト元のパスには適用されないので、もし、自身のディレクトリ以外のパスをリダイレクト元にしたいときは、きちんとしたディレクトリ指定が必要です。

もう一つ、RewriteBase は、リダイレクト先の指定が相対パスの時にしか適用されません
ですので、リダイレクト先のパスの先頭に「/」をつけると、絶対パスと解釈され、RewriteBase は無視されます。


つまづきやすいのは、この2点ではないでしょうか。
他にも、Lフラグで無限ループを防ぐ方法とかありますが、そういったことはスライドを見ていただくなり、ググって情報を探していただければよいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です