.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フラグで無限ループを防ぐ方法とかありますが、そういったことはスライドを見ていただくなり、ググって情報を探していただければよいと思います。

.htaccessによるリダイレクト徹底解説” に対して1件のコメントがあります。

  1. ten より:

    こんにちは。

    有用な記事の掲載、ありがとうございます。

    .htaccessファイルで苦戦していたので非常~~~~~~~にたすかりました!

    一つお伺いしたいのですが、スライド内の文字をテキストでコピーすることはできないでしょうか?

    サンプルとしてつかいたいのですが、手入力して間違うと、書き方が間違っているのかそもそもの処理の箚せかたが間違っているのかわからなくなってしまう可能性があるなと思いまして・・。

    可能でしたらお願いします!!

    1. 川井 昌彦 より:

      コメントありがとうございます。
      スライド内の文字のコピーですが、スライド右下の「Slideshare」をクリックすると、Slideshareでスライドが開きます。
      スライドの下のほうにスライド内の文字がテキストで出てくるので、それをコピーすることはできます。

      改行が反映されていないので、ちょっと難しいとは思いますが・・・

      1. ten より:

        川井 様

        ご回答ありがとうございます!!
        10分後にコメントしていただいていたのですね・・。今確認しました!

        スライドの動物かわいいですね笑

        無事コピーできました! 改行が無くても必要な部分を検索してコピペできれば
        十分でございます。
        非常に助かりました!

        そしてまたまたご質問良いですか?
        今回の記事で使用されているあのスライドはどうやって実現しているのでしょうか?

        WordPressのプラグイン化なにかでしょうか?
        初めて見たので非常に興味があります!

        差し支えなければお教えいただけるとありがたいです。

        よろしくおねがいします。

        1. 川井 昌彦 より:

          うまく行って良かったです。

          記事中のスライドは「Slideshare」というサービスにアップロードしてあるものですが、そのスライドのURLをWordPressの記事中に貼り付けると、自動で表示してくれるようになります。
          他にもスライドをシェアするサービスがいくつかありますが、たいてい対応しているんじゃないかなと思いますよ。

          1. ten より:

            こんにちは!

            ありがとうございます。
            リンクドインのサービスなのですね!
            これですよね。
            https://ferret-plus.com/8483

            ちょうどアカウントも持っているので使ってみたいと思います。

            いろいろとありがとうございました!

川井 昌彦 にコメントする コメントをキャンセル