#009
posted on 2020.12.29

.htaccessでリダイレクトしてURLを正規化。

Apacheのモジュールである「mod_rewrite」を.htaccessに記述して、リクエストされたURLを書き換えてHTTPステータスコード301でリダイレクトさせる。(301は恒久移転、302は一時移転。)

※ .htaccessのパーミッションは604にする。 (644を推奨しているレンタルサーバーもある。)

 

「mod_rewrite」は、サーバー変数、環境変数、HTTPヘッダー、タイムスタンプ、データベースなどを使って、正規表現でURLの書き換えができる。 (使える変数や返り値はサーバーの設定に依る。)

 

Apacheの設定ファイル (httpd.conf) に記述する方法もあるが、サーバー自体のroot権限が必要なので、普通のレンタルサーバーでは不可。

 

オンラインのHTTPステータスコードチェッカーで現在のリダイレクトのステータスを確認できる。

 

「http」を「https」にリダイレクト

全ての「http」でのリクエストを「https」へ301でリダイレクト。

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
<IfModule>

サーバー変数の「HTTPS」が「on」では無かった場合に、「https:// + リクエストされたホスト + リクエストされたターゲット」に301でリダイレクト。サブディレクトリに設置した.htaccessの場合は、「%{REQUEST_URI}」でホスト名の後ろの「/」が重複する場合があるので注意。

 

<IfModule mod_rewrite.c>

モジュールのmod_rewriteが有効かどうかを確認するif文。

そもそもmod_rewriteが有効でなければ中身の実行ができないので、結局これは無くても同じ。

レンタルサーバーのロリポップで、このif文を付けると動作せず、if文を付けないと問題無く動作。(2020年12月30日時点で確認。)

 

RewriteEngine

RewriteEngineは、mod_rewrite (URL書き換えエンジン) を使う宣言文。

  • RewriteEngine on : mod_rewriteの機能を有効にする。
  • RewriteEngine off : mod_rewriteの機能を無効にする。

 

RewriteBase

RewriteBaseは、ベースとなるディレクトリを明示的に指定するもの。.htaccessを設置したディレクトリと処理を行うディレクトリが同じなら不要。

 

RewriteCond

RewriteCondは、URL書き換えを行う場合の条件を定義する条件分岐の構文。RewriteRuleの前に記述。

「RewriteCond 対象文字列 条件パターン [フラグ]」 : 第1引数の対象文字列が第2引数の条件パターンにマッチした場合だけ、直後のRewriteRuleが処理される。

  • %{変数名} : サーバー変数
  • %{ENV:環境変数名} : 環境変数
  • %{HTTP:ヘッダ名} : HTTPヘッダー

この場合、第1引数の「%{HTTPS}」が第2引数の「!on」 (onではない)の場合にマッチするという条件分岐。第2引数に「!on」ではなく「off」を記述すると、サーバーの設定でhttpsではない時の「%{HTTPS}」の返り値が空など「off」以外だったときに動作しない。

 

RewriteRule

RewriteRuleは、URL書き換えを実行する構文。複数ある場合は上から順番に処理。

「RewriteRule パターン 置換するURL [フラグ]」 : 渡されたURLが第1引数のパターンとマッチした場合に、第2引数の置換するURLに書き換えられる。

  • [] : フラグ。第3引数で指定できる。複数指定する場合は、「,」で区切る。
  • [R] : Redirect。302(デフォルト)でリダイレクトする。 (「R=301」で301でリダイレクト。)
  • [L] : Last。RewriteRuleが複数あり処理がループする場合に、ルールが一致したら以降の処理を[L]フラグで中止する。ルールの最終行という意味。

もし[R]フラグが無ければ、アドレスバーは書き換わらずにリクエストするファイルのみ変更される。

 

 

「wwwあり」を「wwwなし」へリダイレクト

サブドメインに「www」のあるリクエストをサブドメインなしへ301でリダイレクト。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
# 常時SSL化にも対応する場合は下の2行を併記
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

クライアントがリクエストしたホストが「www. + 任意の文字列01」とマッチした場合、渡された「URL + 任意の文字列02」を「https:// + 任意の文字列01/ + 任意の文字列02」へ301でリダイレクト。

[NC] : No Case。大文字と小文字を無視するフラグ。

 

 

サイト移転でURLをリダイレクト

旧URLへのアクセスを全て新URLの「https://example.com」に301でリダイレクト。

RewriteEngine on
RewriteRule ^/(.*)$ https://example.com/$1 [R=301,L]

ルートディレクトリ以下の構成が違う場合は、「^/」以降を調整して指定する。

 

 

URLの「index.php」をなしにする

各ディレクトリのトップページの正規化。

RewriteEngine on
RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ https://%{HTTP_HOST}/$1 [R=301,L]

サーバー変数「THE_REQUEST」の文字列(例 : 「GET /index.php HTTP/2.0」)に「/index.php」がマッチした場合にURLを書き換える。

 

 

日時を指定してURLをリダイレクト

2021年01月01日以前の「page1.html」へのアクセスを「page2.html」に302でリダイレクト。

RewriteEngine on
RewriteCond %{TIME} <20200101000000
RewriteRule ^/page1.html$ /page2.html [R=302,L]

RewriteCondの第1引数のサーバ変数で取得した日付が、第2引数で指定した日時とマッチした場合にRewriteRuleで302リダイレクト。

< : 比較演算子。「>」なら指定日時以降にマッチ。後ろにスペースを入れるとエラーになる。

%{TIME} : サーバー変数。年月日時分秒 (例 : 20210101123456)。

 

 

この記事をシェア