#009
posted on 2020.12.29 (Tue) 2021.10.27 (Wed)

.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でリダイレクトさせる記述。

サイトのすべてのページで「Always On SSL」にする。(常時SSL化。)

 

サーバー変数の「%{HTTPS}」が「on」ではない(https通信ではない)場合に、「https://リクエストされたホスト/リクエストされたパス」に301でリダイレクトさせる。

 

RewriteCondの行で、第1引数のサーバー変数「%{HTTPS}」が第2引数の「!on」(「on」ではない)にマッチすれば、次のRewriteRuleを処理。

第2引数に「!on」(「on」ではない場合にマッチ)ではなく「off」(「off」の場合にマッチ)を指定すると、https通信ではない時の「%{HTTPS}」の返り値の設定が空の場合など、サーバー設定で「off」以外を指定しているときに動作しない可能性がある。

RewriteRuleの行で、リクエストされたURLの書き換えとリダイレクトを実行する。

 

※ サブディレクトリに設置した.htaccessの場合は、「%{REQUEST_URI}」でホスト名の後ろの「/」が重複する場合があるので注意。

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

%{HTTPS} : リクエストがhttps通信かどうかを返す。

%{HTTP_HOST} : リクエストされたホスト名を返す。サブドメインがあればサブドメインも含める。(「https://memo.ag2works.tokyo/post-240/」なら「memo.ag2works.tokyo」の部分。)

%{REQUEST_URI} : リクエストされたURI(ドメイン以降のパス)を返す。(「https://memo.ag2works.tokyo/post-240/」なら「/post-240/」の部分。)

 

「<IfModule mod_rewrite.c>」

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

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

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

「RewriteEngine」

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

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

「RewriteBase」

ベースとなるディレクトリを明示的に指定するもの。

※ .htaccessを設置したディレクトリと、処理を行うディレクトリが同じなら不要。

「RewriteCond」

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

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

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

「RewriteRule」

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

※ 渡されるURLは、「https://memo.ag2works.tokyo/post-240/」なら「post-240/」。(最初のスラッシュを含めないので注意。)

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

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

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

 

 

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

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

 

クライアントがリクエストしたホスト名が「www」+「.」+「何らかの文字列01」の構造形式にマッチした場合、「リクエストされたURL文字列02」を調べて「https://何らかの文字列01/マッチしたURL文字列02」へ301でリダイレクト。

※ 正規表現では、「()」で囲った部分にマッチした文字列は後方で参照できる。

  • RewriteCondの「^www\.(.*)$」で「(.*)」にマッチした文字列を「%1」で参照。
  • RewriteRuleの「^(.*)$」で「(.*)」にマッチした文字列を「$1」で参照。
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]

%{HTTP_HOST} : リクエストされたホスト名を返す。(サブドメインがあればサブドメインも含める。)

%{HTTPS} : リクエストがhttps通信かどうかを返す。

%{REQUEST_URI} : リクエストされたURI(ドメイン以降のパス)を返す。

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

 

 

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

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

 

ルートディレクトリ以下の構成が違う場合は、正規表現で調べる文字列のパターンや移動先に指定するホスト名以降のパス部分の記述を調整して指定する。

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

 

 

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

各ディレクトリのトップページを正規化する記述。

 

サーバー変数「THE_REQUEST」の文字列(例 : 「GET /index.php HTTP/2.0」)内で「/index.php」がマッチした場合に、リクエストされたURLの末尾の「index.php」の部分だけを削除して301でリダイレクト。

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

%{THE_REQUEST} : ブラウザからサーバーに送られてきたHTTPリクエストの内容を返す。(「GET /index.html HTTP/2.0」など。)

%{HTTP_HOST} : リクエストされたホスト名を返す。(サブドメインがあればサブドメインも含める。)

 

 

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

2021年01月01日以前のアクセスの場合には、「page1.html」へのアクセスを「page2.html」に一時移転のステータスコード302でリダイレクトさせる記述。

 

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

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

%{TIME} : 年月日時分秒 (例 : 20210101123456)を返す。

< : 比較演算子。上記の場合は指定日時以前にマッチ。後ろにスペースを入れるとエラーになるので注意。(「>」なら指定日時以降にマッチ。)

 

 

この記事のURL

https://memo.ag2works.tokyo/post-240/

Copyコピー
この記事のタイトル

.htaccessでリダイレクトしてURLを正規化。 | memo メモ [AG2WORKS]

Copyコピー
この記事のリンクタグ

<a href="https://memo.ag2works.tokyo/post-240/" target="_blank" rel="noopener">.htaccessでリダイレクトしてURLを正規化。 | memo メモ [AG2WORKS]</a>

Copyコピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)