AWS ELB配下でApacheのRewriteRuleが上手く動かなかった話

■環境

AWS ELB
AWS EC2
Apache 2.2.32


AWSのEC2上で動いているApacheサーバーでの話。

SEO対策で/index.html/にリダイレクトしたかったので
.htaccess に以下を設定しました。

RewriteRule ^(.*)index.html$ $1 [R=301,L]

検証インスタンスでは上手く動いたので、本番インスタンスにも反映させたところ
https://〜/index.html(443ポート) が http://〜/(80ポート)にリダイレクトされるようになってしまいました。

なんでだろう?と思いながら以下のような分岐を作ってみましたが、結果は変わらずでした。

# 一旦プロトコルはhttpとしておく
RewriteRule .* - [E=X_PRTCL:http]
# リクエストプロトコルがhttpsの場合、リダイレクト先もhttpsにする
RewriteCond %{HTTPS} on
RewriteRule .* - [E=X_PRTCL:https]
RewriteRule ^(.*)index.html$ %{ENV:X_PRTCL}://%{HTTP_HOST}/$1 [R=301,L]

なぜ443ポート(https)の通信が80ポート(http)扱いになってしまったかというと
本番環境のEC2はELBを通しているのが原因でした。

つまり、検証環境では

PC
↓443ポート
EC2

だったのに対して、本番環境では

PC
↓443ポート
ELB
↓80ポート
EC2

となっていたのでした。

ELBを経由した場合、HTTPプロトコルを判定するにはX-Forwarded-Protoというパラメータを見る必要があるようです。
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/x-forwarded-headers.html

以下のようにhtaccessへ記載すればELB経由でも上手く動きました

# 一旦プロトコルはhttpとしておく
RewriteRule .* - [E=X_PRTCL:http]
# リクエストプロトコルがhttpsの場合、リダイレクト先もhttpsにする
RewriteCond %{HTTPS} on [OR] # ELBを経由しない時用
RewriteCond %{HTTP:X-Forwarded-Proto} https # ELBを経由する時用
RewriteRule .* - [E=X_PRTCL:https]
RewriteRule ^(.*)index.html$ %{ENV:X_PRTCL}://%{HTTP_HOST}/$1 [R=301,L]