IORI-ST

.htaccessリダイレクトの覚書

先日、.htaccessのリダイレクト作業を初担当しました。トラブル続きで半泣きになりながら総量1000行弱のリダイレクト設定を書くというなかなかインプレッシブな経験をしたので、ここで「.htaccessリダイレクトの覚書」と題し、リダイレクト設定のカンニングペーパーを残しておきます。

現場でコピペして使えるように、なるべく様々な場合での表記例をご紹介しています。

基本のき

今回は「https://sample.com」のルートディレクトリに「.htaccess」があるケースを想定しています。.htaccess には以下のソースをコピペしてください。

RewriteEngine On
RewriteBase /

# =====================
# リダイレクト始まり

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

# リダイレクト終わり
# =====================

「#(ハッシュ)」がついている文章はコメントアウトされるので省いても問題ありませんが、リダイレクトの量が膨大になってきたときにわかりやすいので見出しとしてつけてます。
ちなみにリダイレクト部分以外の文章の役割は以下のような感じです。

RewriteEngine On
Rewriteの機能を有効にします。これ気づかずに離れたところにダブルで表記してたらエラーになったので、わかりやすく最初に書いておくのがおすすめです。(経験談)
RewriteBase
ベースURLの設定です。.htaccessをルートディレクトリに置いているのであれば「/(スラッシュ)」のみになります。
もし設置場所とリダイレクトを有効にしたい場所が違うのであれば、そのディレクトリ名に書き換えましょう。
(例)「https://sample.com/aaa」をベースにしたい時 -> RewriteBase /aaa
RewriteRule
リダイレクトは「RewriteRule」の部分の文章を書き換えて設定していきます。ちなみに文章末の[L,R=301]は、「表記は終わり(**L**ast)だからこれを恒久的に転送してね(**301**に**R**edirect)」という意味だそう。

余談ですが、.htaccess は表記の方法が一箇所でも違うと、サーバーにアクセスした時に突然サーバーエラーになってしまいます。もし不安であれば、「htaccess.txt」など下書き兼バックアップファイルなどを用意しておくと安全・安心です。

ではまずはよく使われる表記から!

ファイル名のみを変更したい時

(例)https://sample.com/aaa.html を https://sample.com/bbb.html へ

RewriteRule ^aaa.html$ bbb.html  [L,R=301]

ディレクトリ名のみを変更したい時

(例)https://sample.com/aaa/ を https://sample.com/bbb/ へ

RewriteRule ^aaa/$ /bbb/ [L,R=301]

下のように置換パターンの冒頭の「/(スラッシュ)」を省いても大丈夫です。htaccessが理解していい感じにパスを繋いでくれます。

RewriteRule ^aaa/$  bbb/ [L,R=301]

階層がずれても特に表記規則の変更はありません。
(例)https://sample.com/aaa/bbb/ を https://sample.com/aaa/ へ

RewriteRule ^aaa/bbb/$ /aaa/ [L,R=301]

(例)https://sample.com/aaa/ を https://sample.com/aaa/bbb/ へ

RewriteRule ^aaa/$ /aaa/bbb/ [L,R=301]

ディレクトリ名の変更をディレクトリ以下のファイルにも適用したい時

(例)https://sample.com/bbb/aaa.html を https://sample.com/ccc/aaa.html へ

RewriteRule ^bbb(.*)$ /ccc$1 [R=301,L]

ディレクトリもファイル名も変更したい時

(例)https://sample.com/aaa/bbb.html を https://sample.com/ccc.html へ

RewriteRule ^aaa/bbb.html$ /ccc.html [R=301,L]

ディレクトリ表記だったページがファイル表記になる時

(例)https://sample.com/aaa/ を https://sample.com/bbb/ccc.html へ

RewriteRule ^aaa/$ /bbb/ccc.html [R=301,L]

トラブルシューティング

1. 複雑なパスで表記が正しいかわからない

上で紹介したように、.htaccessのリダイレクトは「^」や「$」などの記号を使った記法で書く必要があります。これを「正規表現」と言います。

今回紹介しきれなかった複雑なリダイレクトの場合にも表記を予測できることがあるので、余裕があれば正規表現の意味もなんとなく覚えておくと◎


正規表現 意味 リダイレクトでの例
^ 直後の文字が行の最初の時 ^aaa/ ベースURL以下がaaa/のもの
$ 直前の文字が行の最後の時 aaa.html$ URLがaaa.htmlで終わっているもの
. 任意の一文字 aaa(.*) aaa以下に任意の文字列が続くもの全て
* 直前の文字が0回以上繰り返す時
( ) 文字を1つのグループにまとめる

2. 表記は正しいはずなのにうまくパスが繋がらない

確認するのが2回目以降であればキャッシュの可能性も高いです。私が経験した9割はキャッシュでした…。キャッシュをクリアして再確認しましょう。

また置換前の正規表現パターンに aaa.html?id=bbb などのクエリがついている時は RewriteRule の表記に加えて RewriteCond という表記も必要になります。

(例)https://sample.com/aaa/bbb.html?id=123 を https://sample.com/ccc/ddd.html へ

RewriteCond %{QUERY_STRING} (^|&)id=123(&|$)
RewriteRule ^aaa/bbb.html?$ /ccc/ddd.html? [L,R=301]

クエリが2つ以上でになっても基本的には同じです。

(例)https://sample.com/aaa/bbb.html?bid=123&eid=456 を https://sample.com/ccc/ddd.html へ

RewriteCond %{QUERY_STRING} (^|&)bid=123&eid=456(&|$)
RewriteRule ^aaa/bbb.html?$ /ccc/ddd.html? [L,R=301]
RewriteCond
「RewriteCond %変数名 条件」という形で使います。上記の例だと『「%{QUERY_STRING}=クエリ文字列」が「(^|&)bid=123&eid=456(&|$)」の時に RewriteRule を実行してね』という感じです。%変数名には Apache httpd が用意している多くの変数が利用できます。

新しい正規表現も出てきましたね。


正規表現 意味 リダイレクトでの例
| もしくは (^|&)id=123 idの直前はクエリの先頭もしくは&
id=123(&|$) id=123の直後はクエリの最後もしくは&
? 直前の文字が0個か1個の場合 bbb.html? bbb.htmlかbbb.htmllの時
つまりパスの部分が bbb.html の時のみ

(^|&)id=123とid=123(&|$) は、これら2つ一気に表記することで id=123 で検索した時に bid=123 などのパラメータを除外する役割を果たすのだそう。

初見では「&(アンド)」は正規表現の一部なのかと思っていましたが、ここでは単純に文字列の一部でした…。笑

またRewriteRuleの第二引数の最後に「?(クエスチョンマーク)」をつけているのはクエリ文字列を空で上書きするためです。もしこれをつけないと 置換後のパスが旧表記を引き継いで /aaa/ddd.htmll?id=123 になってしまいます。

3. リダイレクトループしてしまう

もし aaa.html -> bbb.html という表記と同時に、 bbb.html -> aaa.html という表記を書くと aaa.html ⇄ bbb.html 間で無限にリダイレクトしてしまいます。これを「リダイレクトループ」と呼びます。

リダイレクトループが起こった時は、ブラウザの警告文で「リダイレクトが繰り返し行われました」などと知らせてくれるのでその点ではとても対応がしやすいです。

私がよくやってしまったのは、以下のように同じディレクトリで2通りの表記をした時などでした。

RewriteRule ^aaa(.*)$ /bbb$1 [R=301,L]
RewriteRule ^aaa/ccc.html$ /aaa/ddd.html$1 [R=301,L]

ある意味保険のような感覚で書いてしまったのですが、上記の例では上の表記で必然的に下のリダイレクトも実行されます。したがってこの場合は上の表記のみだけでよかったんですね。

もしどの場所がループの原因になっているかわからない場合は、一度ループが発覚した表記のファイル名やディレクトリ名をファイル全体で検索すると見当がつくこともあります。テストサーバーであれば「.htaccess」として実行して、部分ごとに削りつつ反映&だんだん原因の箇所を絞り込む…なんて手も。(結構根気はいりますが)

まとめ

ひょんなことから.htaccessのリダイレクト作業に入門し、Xserverなどが提供しているリダイレクトサービスのありがたみをひしひしと感じました…。と言いつつも、表記量が多くなってきたら単純にスピード感のある.thaccessの方が便利なのかなとも思います。

慣れないところを調べながら作業したので、もし「ここの認識間違ってるよ!」という部分があればSNSのDMなどでご指摘いただけると大変助かります。


Related Posts

この記事に関連するエントリーは見つかりませんでした。

Tags