はじめに
PHPの$_SERVERでドメインまでのURLを取得しようとしたときに、本番環境と検証環境、開発環境で挙動がことなることではまったので共有。
AWSを使用した環境で陥りがちなミスかと思います。
具体的な内容
ミスっていたときのコード
開発環境はオンプレのサーバー上にあり、検証・本番環境はAWSサーバー上にあります。開発環境でのプロトコルはhttpですが、検証・本番環境はhttpsです。
画像を取得する際ためにドメインまでのURLを取得するために以下のように書きました。
$domain = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http' . $_SERVER['HOST'];
この書き方ではAWS上の検証環境・本番環境に上げた際にhttpsだと判断されず思うような挙動になりませんでした。
想定した動作をしなかった原因
AWS上でアプリケーションサーバの前にロードバランサーを置いていて、サイト自体はHTTPSだが、
実際のSSL暗号化処理はロードバランサーのSSLアクセラレータ機能が行っており、ウェブサーバはHTTP平文通信をしているため。
修正するにあたって参考にした記事
$_SERVER は、ヘッダ、パス、スクリプトの位置のような 情報を有する配列です。この配列のエントリは、Web サーバーにより 生成されます。全ての Web サーバーがこれら全てを提供する保証はありません。
- PHP の $_SERVER['HTTPS'] が on になる流れ 〜Apache mod_php 編〜
https://qiita.com/xtetsuji/items/36d85bb49a518ed7b1da - ALB+EC2な環境でhttpをhttpsにリダイレクトする
https://re-engines.com/2017/10/13/aws-2/
$http_x_forwarded_protoを使うとクライアントがロードバランサーへの接続に使用したプロトコルを識別できます。
$http_x_forwarded_protoがhttpsではなかった時にhttpsでリダイレクトします。
想定された挙動になった際のコード
$domain = (isset($_SERVER['http_x_forwarded_proto']) && $_SERVER['http_x_forwarded_proto'] === 'https') ? 'https' : 'http' . $_SERVER['HOST'];
まとめ
今回は開発環境と検証・本番環境の環境の差異で起こしてしまったミスです。公式ドキュメントの一番上にヒントがありましたが他の記事を読むまで読み飛ばしていました、、、
開発環境での確認では気づきにくい部分かと思いますので知っておくことが大事な落とし穴かと思います。他の方法や解釈が間違っている箇所がありましたらぜひコメントで指摘をお願いいたします。