【.htaccess】リダイレクトが上手く行かないときの対処法|RewriteRule 新しいページに転送する方法

wordpress-prograshi(プロぐらし)-kv WordPress
記事内に広告が含まれていることがあります。

WordPressなどApacheサーバーを使ったWEBサイトで転送設定を行う場合は.htaccessに転送設定を使った記述を行います。

正しく記述したはずなのに上手く作動しない、、、といった状況に遭遇する場合があります。そんなときの対処法をまとめています。


基本的な転送設定

基本的な転送設定の記述は以下になります。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^旧ページのディレクトリパス$ 転送先ページのURL [R=302,L]
</IfModule>
############################

上記は一時的に転送をする場合です。恒久的に転送する場合は「R=302」を「R=301」にします。

RewriteRuleの基本構文は以下のようになっています。

RewriteRule ①入力URL ②置換後のURL [③フラグ]

①の入力URL(アクセスしてきたURL)は正規表現で記述します。このとき、サイトを展開しているディレクトリのパスが対象となります。

②置換後のURLは絶対パス(https://~)で指定します。

③フラグは転送方法の指定です。[302, L]とは、302転送をし、ここでIfModule mod_rewrite.cの転送設定を終了することを表しています。


参考

「mod_write.c」「Rewrite Engine」「RewriteRule」は一体何なのか?やフラグについては下記をご参考ください。

【WordPress】.htaccessとは何か?IfModule mod_write.c, Rewrite Engine, RewriteRuleの意味や書き方、フラグの一覧



転送時の注意点:301と302

主な転送方法には301と302があります。数値が1つズレているだけですがとても重要です。間違えるとえらいことになります。

301と302リダイレクトの違い
  • 301: 恒久的な転送
  • 302: 一時的な転送

301転送は過去のページを終了して、新しいページに完全に移管するときに使用します。

302転送は一時的にページを転送して、今後元に戻す場合に使用します。例えば、オープン開始前は「Comming Soon」といったページに飛ばして、オープン後に本物のTOPページに飛ばすといった処理です。

注意しなければいけないのは安易に301転送をしないということです。301転送をした状態でGoogleなどのブラウザがその転送を認識すると、旧ページのURLが入力されたら新ページにリダイレクトするという処理を記録してしまいます。

これはキャッシュなどでクリアできない場合があり、「あっ間違えた」というときに時すでに遅しということもありえます。

ちなみに転送のフラグを指定しない場合や[R]とのみ記載した場合など301を明示しない場合は302転送になります。



リダイレクトの実例

例えば、「https://example.com/reservation」というページを「https://example.com/reservation-pending」にリダイレクトしたい場合は以下のように記述します。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################



リダイレクトの実例(サブディレクトリにサイトを展開している場合)

WEBサイトによってはルートディレクトリの下に、別のディレクトリを作成してサブディレクトリでWEBサイトを公開していることもあります。

そういったときに、例えば、「https://example.com/sys/reservation」というページを「https://example.com/sys/reservation-pending」にリダイレクトしたい場合は以下のように記述します。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /sys/
 RewriteRule ^reservation$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################


「RewriteBase」でサブディレクトリ「/sys/」を指定しています。ディレクトリを指定する場所なので両端に「/」をつけます。

ルートディレクトリに展開しているサイトの場合は「RewriteBase /」またはRewriteBase自体記載なにします。


リダイレクトが上手くいかないときの対処法

コードの書き方自体が間違っている場合(例えば全角スペースが含まれているなど)は500番のサーバーエラーが発生します。

その場合はコード自体を見直しが必要です。

ここでは、旧ページから新ページへのリダイレクトを設定したのに、旧ページがそのまま表示されてしまうという状態の対処法について解説します。


発生原因:正規表現が間違っている

リダイレクトしているのに旧ページがそのまま表示されてしまう場合は、「RewriteRule」の①入力URLの正規表現の記述が間違っていることがほとんどです。

RewriteRule ①入力URL ②置換後のURL [③フラグ]


ここの記述が間違っていると、入力したURLがこの転送設定に該当せず何も行われないという状態になります。


デバッグ方法|IfModule mod_rewrite.cが機能しているか確認する

まずはそもそも記述した場所の「IfModule mod_rewrite.c」が正しく動いているか確認します。

例えば、「https://example.com/reservation」というページを「https://example.com/reservation-pending」にリダイレクトしたい場合に以下の記述があるとします。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################

これで旧ページ「https://example.com/reservation」がそのまま表示されてしまう場合は、以下のように入力URLを^(.*)$に書き換えます。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^(.*)$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################


これによりすべての入力URLが新しいページ「https://example.com/reservation-pending」にリダイレクトされます。

ブラウザで実際に転送を試してみて、転送される場合は①入力URLの正規表現の書き方が間違っているということになります。

※すべてのページが転送されるので、本番公開しているクライアントのサイトなどで行うときは注意してください。


記述を確認する

入力URLの正規表現が正しくないということがわかったら、少し改良します。

まずは入力URLの指定方法を確認します。例えば、スペルミスがないかや、末尾にスラッシュ「/」や「\.html」を付けるなどを試してみます。

※「.」は正規表現のメタ文字のため文字列として使うためにはバックスラッシュでエスケープする必要があります。


正規表現を使う

それでもダメなら正規表現で力業で修正を行います。

例えば、「https://example.com/reservation」というページを「https://example.com/reservation-pending」にリダイレクトしたい場合に以下の記述があるとします。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################


これを以下のように書き換えます。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation(?!.*(pending)).*$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################

こうすることで、「https://example.com/reservation~」のようにドメイン以下のURLがreservationで始まるページが全て新しいページに転送されるようになります。


コード解説

このとき、転送先のページが同じく「reservation」で始まる「reservation-pending」のため、転送の無限ループが発生しないように正規表現で除外するキーワードを指定しています。

^reservation(?!.*(pending)).*$

この(?!.*(pending)).*は「pending」を含まないという意味です。


もう少し詳しく見ると各メタ文字は以下のを意味しています。

正規表現のメタ文字意味
?直前のパターンの0~1回繰り返し(最長一致)
!否定
.任意の1文字
*直前のパターンの0回以上繰り返し(最長一致)
^先頭一致
$末尾一致


!.*(pending)

これは、0文字以上の繰り返しで「pending」という文字列を含まないという意味になります。


否定条件に該当する複数のページがある場合

下記の記述だと、reservation以下に「pending」を含むページはリダイレクト対象になりません。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation(?!.*(pending)).*$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################


しかし、サイトによっては他にも「https://example.com/reservation-test」や「https://example.com/reservation/sample」など複数のディレクトリがあるかもしれません。

そういった場合は以下のように記述します。

##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /
 RewriteRule ^reservation(?!.*(pending|test|sample)).*$ https://example.com/reservation-pending [R=302,L]
</IfModule>
############################

「|(パイプ)」を使うことで「!」の否定に該当する文字列をor条件でつなげることができます。


複数の否定条件とサブディレクトリの転送設定

最後に参考として複数の否定条件とサブディレクトリの転送設定をする場合の実例を記載しておきます。

例えば、

  1. ルートディレクトリ直下にsysというディレクトリを切り出し、その中にサイトを構築している場合で
  2. 「https://example.com/reservation」というページを「https://example.com/reservation-pending」にリダイレクトしたい場合
  3. かつ、pending, backend, testという文字列を含むページは転送から除外したい場合は以下のように記述します。
##########転送設定##########
<IfModule mod_rewrite.c>
 RewriteEngine on
 RewriteBase /sys/
 RewriteRule ^reservation(?!.*(pending|backend|test)).*$ https://example.com/sys/reservation-pending [R=302,L]
</IfModule>
############################


タイトルとURLをコピーしました