【Laravel】初めてのAWSデプロイ - 3~5分ごとにヘルパー関数が生成するリンクがHTTPとHTTPSで切り替わってしまう問題編 -

Laravel + vue.jsで作成したポートフォリオをデプロイするために初めてAWSを利用したところ様々な問題にぶつかり、解決に時間を要しました。

- **発生した問題**
 - [JSファイルやCSSファイルが正しく読み込まれない問題](https://qiita.com/namo_berry/items/f56126a3ed866723a705)
 - ブラウザを問わず、**数分毎にHTTPとHTTPSが切り替わってしまう**問題(★ 本記事)

前回、JSファイルやCSSファイルが正しく読み込まれない問題を無事に解決しましたが、次なる問題が発生しました。


# 3~5分ごとにasset()関数が生成するリンクのHTTPとHTTPSが切り替わってしまう問題
タイトルだけだと何のことやらと思います。

前回、無事に信用するプロキシを記述し、ヘルパー関数が生成するリンクをhttpsにすることに成功。無事にJSやCSSが読み込まれた...と思いきや

**「別のブラウザでもちゃんと表示されるのか確認しよう！」**

そしてfirefox、Edge、Safariで開いてみた結果...
![UdemyloadQiita01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/0b1a5045-723d-94e9-2d76-9bf1348b5ea1.jpeg)

### フ ァ イ ル が 読 み 込 ま れ て い な い


JSファイルもCSSファイルも読み込まれず、テキストだけの寂しい画面が現れました。Chromeではちゃんと読み込んでくれていたというのに一体どういうことなのでしょう。
今まで無事に読み込まれていたGoogleChromeも更新してみると

![UdemyloadQiita01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/0b1a5045-723d-94e9-2d76-9bf1348b5ea1.jpeg)

なんとChromeもダメになってしまいました。ほんの5分前には正しく読み込まれていたというのに...
今までhttpsでリンクを作ってくれていたヘルパー関数が、元のhttpによるリンクを生成してしまっていたのです。
キャッシュの問題でしょうか...?しかしながら最初に開いたブラウザにキャッシュも何もないはず...

理由が解明されないままF5でページのリロードを繰り返した結果

**3~5分程度経過すると再度asset()がhttpsで読み込むようになった**のです。


## 症状のまとめ
- 3~5分のスパンで`asset()`が生成するリンクが`http`と`https`で切り替わる。
- この症状は、ブラウザを問わず発生する。
- 生成するリンクのスパンはブラウザごとに独立している(例えば、Chromeでhttpsリンクが生成されている時でも、safariではhttpリンクになっていることがある、など。)

時間差でリンク生成が切り替わるということなんて聞いたことがなく、検索をかけてもそれらしき記事やまとめが見つかりませんでした。
そのため出来ることを1つ1つ試して解決に繋げようと模索しました。

## 試したこと1 リンクの強制HTTPS化
前回信用するプロキシとして`app/Http/Middleware/TrustProxies.php`への記述を行いましたが、もしかしたら不十分だったかもしれないと考えました。

- [[Laravel]常時SSLなアプリケーションでのURL生成のベストプラクティスを考える](https://qiita.com/hisash/items/4b3bb1ea47c38b0d8c86#%E3%82%B1%E3%83%BC%E3%82%B91-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%81%A8%E3%82%A2%E3%83%97%E3%83%AA%E9%96%93%E3%81%A7ssl%E9%80%9A%E4%BF%A1%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88)
- [laravelでリンクがhttpsにならない](https://qiita.com/horikeso/items/fa15aaec0c0762d687ed)

そこで上記記事を参考にし、forceSchemeにより本番環境の場合にリンク生成をhttpsとするように設定しました。

```app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\UrlGenerator; // 追記

class AppServiceProvider extends ServiceProvider
{
    // 中略

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(UrlGenerator $url)
    {   
        // ★ 以下を追記！！！
        // 本番環境の時、URLをhttpsにする
        if (config('app.env') === 'production') {
          $url->forceScheme('https');
        }
    }
}

```

結果: **ダメでした**
状況は変わらず、3~5分のスパンで`aseet()`はhttpになったりhttpsになったり...
原因はどうもここではないようです。



## 試したこと2 APP_URLの修正
.envファイルのAPP_URLを修正すればもしかしたら正しく動作するかもしれません。
早速本番環境の.envファイルを修正していきます。

```.env
// 修正前
APP_URL=http://xxx.xx.x.xx

// 修正後
APP_URL=https://xxx.xx.x.xx
```

.envファイルを修正した後は以下コマンドでキャッシュをリフレッシュして、その後ブラウザをリロードします。

```
$ php artisan config:cache
```

結果: **ダメでした**
httpsのリンクすら生成されなくなってしまいました。どうやら原因はここではなかったようです。
**.envファイルは元に戻します。**


## 試したこと3 そもそも本番環境になっているかのチェック
「試したこと1」で記述した`app/Providers/AppServiceProvider.php`を眺める中でふと思いました。

```php
// 本番環境の時、URLをhttpsにする
if (config('app.env') === 'production')
```

**「そもそも本番環境になっているのか...?」**

いや、まさか、そんなはずはない。
そう思いつつも、再び.envファイルを確認してみると...

```php:.env
APP_ENV=local
```

やってしまっていました...。デプロイしておきながら、ローカル環境のまま動いていました。
とんでもないことです。

早速修正します。

```php:.env
APP_ENV=production
```

```
$ php artisan config:cache
```

ブラウザをロードしてみると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/2d1c4f3a-3770-3b3a-f396-b7e75dc08cdd.png)

無事に表示されました！
この後別のブラウザで時間をかけて何度もリロードしましたが、`asser()`がhttpリンクを生成することはなくなりました！

### 原因に気付けたもう1つの要因
原因に気付くことができた理由は実はもう1つあります。

私はローカル環境の時、SQLが発行された際にそのSQL文をログファイルに乗るように設定していました。

```app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\UrlGenerator;

class AppServiceProvider extends ServiceProvider
{
    // 中略

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(UrlGenerator $url)
    {   
        // 開発環境の時、SQLをログに表示する
        if (config('app.env') !== 'production') {
          \DB::listen(function ($query) {
            \Log::info("Query Time:{$query->time}s] $query->sql");
          });
        }

        // 本番環境の時、URLをhttpsにする
        if (config('app.env') === 'production') {
          $url->forceScheme('https');
        }
    }
}
```
そして、原因が一向に掴めない私は、Laravelプロジェクトのlogファイル(`storage/logs/laravel.log`)を確認していました。
その中で、

**(ローカルでしか表示されないはずのSQLログが表示されている...?)**

と気付けたところから解決に結びつけることができました。

## 調査しきれていないところ
結局のところ、裏でどういうロジックが働いて、時間経過によって`asset()`が生成するリンクがhttpになったりhttpsになったりするのかというのはわかりませんでした。

引き続き調査を行いますが、こういったところが怪しいといったものがあればご指摘いただけると幸いです。


# まとめ
しっかり.envファイルは確認すること、どんな小さなことからも原因を探すことが出来るということを学ぶことができたと思います。
次にデプロイする機会があればこういった部分もしっかりチェックしていきます。