中国版AWSであるAlibaba CloudでLaravelを動かした際に手間取った点をまとめました。タイトルの通りです。
作ったのはSLB(Server Load Balancer)とECS(Elastic Compute Service)を用いたシンプルなアーキテクチャ。AWSにおけるELBとEC2みたいなものです。
HTTPS化するために、ELBと同様にSSL証明書をSLBにインストールしました。インストールの手順はSLBのほうが簡単かもしれません。
Alibaba CloudもAWSと同様に、
client <- 443 -> SLB <- 80 -> ECS
という通信の流れです。
これで何も考えずにLaravelでroute('auth.login')
と書いたら、
http://hoge.foo.bar/login
と、HTTPのURLが出力されてしまいました。
出力したいのは
https://hoge.foo.bar/login
です。
まあ、これはAWSでありふれた問題なので解決方法もインターネットに溢れています。
というかLaravelの公式ドキュメントに記載されています。
https://laravel.com/docs/5.7/requests#configuring-trusted-proxies
https://readouble.com/laravel/5.7/ja/requests.html#configuring-trusted-proxies
公式ドキュメントにもあるように、
app/Http/Middleware/TrustProxies.php
を以下のように設定します。
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = '*';
これでうまくいくかと思いきやまだHTTPのまま
どうしてだろう。。。
ここで何をしているかというと、
ロードバランサーからのリクエストを信頼できる通信であると、
しかもprotected $proxies = '*';
と、すべてを許可するようにしています。
そして信頼できる通信だと、route()
での出力がhttps://
になります。
さらに詳しく調べると、vendor/symfony/http-foundation/Request.php
のisSecure()
が信頼できるかどうかを判断しています。
/**
* Checks whether the request is secure or not.
*
* This method can read the client protocol from the "X-Forwarded-Proto" header
* when trusted proxies were set via "setTrustedProxies()".
*
* The "X-Forwarded-Proto" header must contain the protocol: "https" or "http".
*
* @return bool
*/
public function isSecure()
{
if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
}
$https = $this->server->get('HTTPS');
return !empty($https) && 'off' !== strtolower($https);
}
X-Forwarded-Proto
を調べてますね。
そういえば、SLBのリスナー設定でX-Forwarded-Proto
のチェック項目があったような。。。
ありました!!
ということで「ヘッダーにX-Forwarded-Proto(SLBへの接続プロトコル)を追加します」にチェックを入れて更新したら、
晴れてroute()
で出力されるURLがhttps://
となりました。
めでたしめでたし