いわさです。
上記を参考に、Lightsail で Laravel を実行していました。
はじめは問題なく動作していたのですが、ディストリビューションを有効化するとページのスタイルが崩れるようになってしまいました。
Laravel のアセット特有の設定が必要ということがわかったのでご紹介します。
何が起きたのか
前述の記事を参考に Lightsail 上へ Laravel を設定し適当な View と CSS を作成しました。
/opt/bitnami/apache2/htdocs/laravel/public/css/hoge.css
p {
color: blue;
font-weight: bold;
}
/opt/bitnami/apache2/htdocs/laravel/resources/views/hoge.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="{{ asset('/css/hoge.css') }}" >
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>hogehoge</p>
</body>
</html>
/opt/bitnami/apache2/htdocs/laravel/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('hoge');
});
ディストリビューションを有効化したらスタイルが適用されなくなった
Lightsail では以下のようにディストリビューションという機能を有効化することで Lightsail に統合された CloudFront を使うことが出来ます。
こちらを有効化したところ、先程まで設定できていたスタイルが適用されなくなってしまいました。
"Mixed Content: The page at 'xxx' was loaded over HTTPS, but requested an insecure stylesheet 'xxx'. This request has been blocked; the content must be served over HTTPS." が発生
ブラウザの開発者コンソールを確認してみるとエラーが発生していることが確認出来ます。
d2pzoi98pm8mbl.cloudfront.net/:4 Mixed Content: The page at 'Document' was loaded over HTTPS, but requested an insecure stylesheet 'http://ec2-54-238-33-9.ap-northeast-1.compute.amazonaws.com/css/hoge.css'. This request has been blocked; the content must be served over HTTPS.
以下のようにスタイルシートのパスがhttp
になっていますね。
ただし、それ以前にホスト名がオリジンのものになっています。
対処方法
どうやら Laravel ではリバースプロキシ経由の環境でasset
やsecure_asset
を使っても暗黙的に CDN 経由とならないそうです。
こちらの対処方法は Laravel 公式ドキュメントに記述がありました。
You can configure the asset URL host by setting the ASSET_URL variable in your .env file. This can be useful if you host your assets on an external service like Amazon S3 or another CDN:
アセットのパスを別のストレージや CDN などでホストする際には、.env
ファイルのASSET_URL
を使うことが出来るとのこと。
やってみる
.env
ファイルはアプリケーションのルートディレクトに存在していますのでそちらに CloudFront のドメイン名を指定します。
/opt/bitnami/apache2/htdocs/laravel/.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:13/asdsadasdsadasdasdasda/vb8U8=
APP_DEBUG=true
APP_URL=http://localhost
ASSET_URL=https://d2pzoi98pm8mbl.cloudfront.net
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
:
おお、うまくいきました。
アセットの絶対パスが CDN ドメインとなっており、警告も解消されています。
さいごに
本日は、Lightsail で Laravel を実行してディストリビューションを有効化するとアセットパスがオリジンパスになる問題に対処してみました。
ドメイン関係なしに HTTP を HTTPS にしたいだけであればTrustProxies
など他の対処方法もあるそうなのですが、今回はプロトコルを解決してもクロスオリジンになる可能性があったのでASSET_URL
にてまとめて対処しました。
Web で調査したところ、asset
のパスが変更出来ないのでコード側で対応する旨の記事を見つけましたが、本日時点の最新バージョンではASSET_URL
を使うことが可能です。
Laravel であれば CloudFront や Lightsail に関わらずリバースプロキシ環境全般で起きそうな気もするのでasset
メソッドを使う際にはこういった設定がある点も覚えておくと良さそうです。