参考:https://road-to-road.com/htaccess_redirect/

SSLリダイレクト+wwwあり

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

SSLリダイレクト+wwwなし

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

index.html(php)なしにする場合

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

注意点

[R,L]は302リダイレクト になってしまい、URLの正規化が一時的だと認識されるため、SEOとしてはよくない。
必ず[R=301,L]と記述する。

ただし、リダイレクトが2段階になる可能性がある。

  1. http://example.com → https://example.com(HTTPS化)
  2. https://example.com → https://www.example.com(www追加)

この順序で処理されるか、逆に処理されるかは、サーバー設定や条件次第だが、最終的には https://www.example.com にたどり着き、すべて 301リダイレクトになる。
リダイレクトチェーン(二段階以上のリダイレクト)は表示速度やSEOの観点で避ける方がよいといわれているが、今回のケースでは過剰に意識する必要がないと思われる。
一発で最終URLに遷移するようにする場合は、たとえば以下のようになる。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
Options +FollowSymLinks

# HTTP または www なし を https://www に統一(1回でリダイレクト)
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</IfModule>

検証方法

Chrome DevToolsは、過去のリダイレクトをキャッシュし「実際にはリクエストを送っていない状態」で擬似的に表示していることがある。
とくにステータスコードが「200 Temporary Redirect」の場合は、キャッシュである可能性が高い。
その場合は、以下の対応を行う。

  1. DevToolsの「Network」タブを開く
  2. 上部で「Disable cache」にチェックを入れる
  3. Shift + リロード(または Cmd/Ctrl + Shift + R)でハードリロード

コマンドラインの場合は、以下で対応する。

$ curl -I http://example.com