CPIのレンタルサーバーで.htaccessを使ったリダイレクト設定方法

データセンター内の様子(サーバールーム)

CPIのレンタルサーバーで.htaccessにリダイレクトを書いたのに、まったく効かない。私も最初は「書き方が間違っているのか」と何度も見直しましたが、原因はコードではなくmod_rewriteが有効になっていないことでした。

CPIは初期状態だと.htaccessでのURL書き換えがオフになっていて、ひと手間加えないと動きません。この記事では、その有効化のやり方と、www有無の統一・ページ単位の転送・http→httpsリダイレクトを、CPI環境で実際に動く形で紹介します。

関連記事:GMOのiCLUSTAで.htaccessにhttpsリダイレクトを設定しても動かない時の解決方法

まず.htaccessの先頭でmod_rewriteを有効にする

CPIで.htaccessによるリダイレクトを使うには、ファイルの先頭に次の2行を書いておく必要があります。ここが抜けていると、以降のリダイレクトはすべて素通りしてしまいます。

Options +SymLinksIfOwnerMatch
RewriteEngine On

Options +SymLinksIfOwnerMatch はシンボリックリンクの追跡を許可する指定で、CPIではこれがないとmod_rewriteが正しく動きません。頭の「+」を落とさないよう注意してください。RewriteEngine On で書き換えエンジンそのものを有効化します。この2行はCPI公式マニュアルでも必須として案内されています。

用途で分ける2つの書き方(mod_rewrite と mod_alias)

リダイレクトには大きく2系統あります。条件を付けて柔軟に書き換えたいなら RewriteCond / RewriteRule(mod_rewrite)、単純に「このパスをあのURLへ」で足りるなら Redirect / RedirectMatch(mod_alias)です。両方を同じ.htaccessに混在させると挙動が読みにくくなるので、どちらかに寄せるのがおすすめです。

www有無を統一する(RewriteRule)

wwwなしでアクセスされたらwwwありに揃える、という正規化はmod_rewriteが向いています。

Options +SymLinksIfOwnerMatch
RewriteEngine On

RewriteCond %{HTTP_HOST} ^example\.jp$
RewriteRule (.*) https://www.example.jp/$1 [R=301,L]

RewriteCond でホスト名が example.jp(wwwなし)のときだけ、RewriteRule で www.example.jp へ転送します。[R=301,L]R=301 は「恒久的な移動」を意味し、検索エンジンに旧URLの評価を引き継がせたいときに使います。一時的な転送なら R=302 です。L はここで処理を打ち切る指定です。

ページ単位で転送する(Redirect / RedirectMatch)

1ページだけ別URLへ飛ばしたいだけなら、条件式のいらないmod_aliasが簡潔です。

Redirect permanent /old/hoge.html https://www.example.jp/new/hoge/

Redirect permanent は301と同じ扱いです。パスの一部を正規表現で受けて置き換えたいときは RedirectMatch を使います。

RedirectMatch permanent ^/old/(.*)\.html$ https://www.example.jp/new/$1/

なお Redirect の第2引数は「サーバー上のパス」、第3引数は「転送先の完全なURL」です。ここを取り違えるとループや404の原因になります。

http→httpsへのリダイレクト(CPI特有の注意)

常時SSL化でつまずきやすいのがこの部分です。独自SSLでサーバー自身がSSLを終端している場合は、次の基本形が使えます。

Options +SymLinksIfOwnerMatch
RewriteEngine On

RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.example.jp/$1 [R=301,L]

%{HTTPS} off は「暗号化されていない通信のときだけ」という条件で、httpでのアクセスをhttpsへ振り向けます。CPIの公式ナレッジでもこの形が示されています。

ただし注意したいのは、%{HTTPS} はサーバー自身がSSLを処理しているときにしか on になりません。共有SSLやCDN・ロードバランサーを前段に挟む構成では、サーバーには常にhttpで届くため %{HTTPS} がずっと off のままになり、リダイレクトが無限ループします。その場合は、前段が付与する X-Forwarded-Proto ヘッダーで判定します。

RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^(.*)$ https://www.example.jp/$1 [R=301,L]

あるいは接続ポートで判定する方法もあり、CPIのマニュアルでは %{SERVER_PORT} !^443$ を使う例も案内されています。環境によってどれが効くかが変わるので、ループや500エラーが出たら判定条件を切り替えて試すのが早いです。

動かないときに見直すポイント

  • 先頭の Options +SymLinksIfOwnerMatchRewriteEngine On が入っているか(CPIで最も多い抜け)。
  • https化のループは %{HTTPS} ではなく X-Forwarded-Proto やポート番号で判定すべき環境ではないか。
  • Redirect(mod_alias)と RewriteRule(mod_rewrite)を混在させて競合していないか。
  • ブラウザが301をキャッシュしている可能性があるため、確認はシークレットウィンドウで行う。

判断に迷う設定はCPIのサポートマニュアルにも記述例があるので、あわせて確認すると確実です。

リンク:.htaccess の設定方法(CPIサポート)

まとめ:コピペで動く最小構成

CPIでリダイレクトが効かないほとんどの原因は、先頭2行の書き忘れです。最後に、mod_rewriteの有効化からwww統一・https化までをまとめた最小構成を置いておきます。ドメイン部分を自分のものに置き換えれば、そのまま動きます。

Options +SymLinksIfOwnerMatch
RewriteEngine On

# http でのアクセスを https へ(独自SSLの場合)
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.example.jp/$1 [R=301,L]

# www なしを www ありへ統一
RewriteCond %{HTTP_HOST} ^example\.jp$
RewriteRule (.*) https://www.example.jp/$1 [R=301,L]

これで直らない場合は、SSLの終端位置(独自SSLか共有SSLか)を疑い、判定条件を X-Forwarded-Proto に切り替えてみてください。私はこの切り替えでループが止まりました。