Laravel/Inertia.jsをCloudFrontを使ったインフラ構成で構築する場合のハマりポイント
こんにちは。
ニシザワです。
本日は、Laravel+InertiaでAWSのCloudFrontを使った時のハマりポイントを説明します。
本ブログではLaravelやInertia.jsのインストール方法は説明しません
inertiajs/inertia-laravel:0.6.9
inertiajs/react:18.0.X
期待する動作としては、ページが表示されるはずですよね。
CloudFrontを経由すると、画面が表示されなかったり、思わないページに遷移したりします。
Inertia.jsは極力HTMLは返さず、対象のComponentと必要な情報の差分を返すようになっているため
HTTPリクエストヘッダーにX-InertiaとX-Inertia-Version,X-Requested-Withが必要になります。
AWSのCloudFrontは余計なHTTPリクエストヘッダーを通さない様になっているため上記追加が必要になってきます。
CloudFrontのビヘイビアからカスタムヘッダーを追記してみましょう。
参考
それは、バリデーションエラーを発生させたときです。
この時、期待する動作は画面にバリデーションエラーが表示されるはずですが、何故かjsonのレスポンスが返ってきてしまいます。
InertiaのuseFormは非同期の処理を内部的に行っており、JSONを返すAPIにアクセスしているような振る舞いをします。
HTTPリクエストヘッダーを見ると、X-Requested-With:XMLHttpRequest,Content-Type:application/jsonになっていることがわかるでしょう。
また、Accept:text/html, application/xhtml+xmlになっています。
ここで見えてくるのが、inertia.fromは非同期でAPI通信をしているが、ResponseはHTMLを要求していることです。
CloudFrontを通すと、jsonが返ってきます。
何故かというと、LaravelがレスポンスをJSONで返すべきかどうかの判定にHTTPリクエストヘッダーのAcceptが関係しているからです。
CloudFrontのカスタムヘッダーにAcceptが無いと、Accept:*/*がリクエスト時にWebサーバーへ送られるため
X-Requested-With:XMLHttpRequestの判定のみとなり、JSONでレスポンスを返すべきリクエストと判定されてしまっています。
ですので、CloudFrontのカスタムヘッダーにAcceptも追加しないといけません。
ビヘイビアのカスタムヘッダーに
Laravel/Inertia.jsの構成はこれから色々と機能が拡充されていくと思うので楽しみにしてます。
ニシザワです。
本日は、Laravel+InertiaでAWSのCloudFrontを使った時のハマりポイントを説明します。
本ブログではLaravelやInertia.jsのインストール方法は説明しません
環境
Laravel:10.xinertiajs/inertia-laravel:0.6.9
inertiajs/react:18.0.X
ハマりポイント
InertiaのuseFormを使ってPOSTやGETのリクエストを送ります。期待する動作としては、ページが表示されるはずですよね。
CloudFrontを経由すると、画面が表示されなかったり、思わないページに遷移したりします。
解決策
結論、CloudFrontの設定でHTTPリクエストのカスタムヘッダーをキャッシュキーに設定し、オリジンリクエストのヘッダーにもカスタムヘッダーが含まれるようにしましょう。Inertia.jsは極力HTMLは返さず、対象のComponentと必要な情報の差分を返すようになっているため
HTTPリクエストヘッダーにX-InertiaとX-Inertia-Version,X-Requested-Withが必要になります。
AWSのCloudFrontは余計なHTTPリクエストヘッダーを通さない様になっているため上記追加が必要になってきます。
CloudFrontのビヘイビアからカスタムヘッダーを追記してみましょう。
もう一つのハマりポイント
ここまでは、探せば出てきますが、もう一つハマりポイントがあります。参考
それは、バリデーションエラーを発生させたときです。
この時、期待する動作は画面にバリデーションエラーが表示されるはずですが、何故かjsonのレスポンスが返ってきてしまいます。
InertiaのuseFormは非同期の処理を内部的に行っており、JSONを返すAPIにアクセスしているような振る舞いをします。
HTTPリクエストヘッダーを見ると、X-Requested-With:XMLHttpRequest,Content-Type:application/jsonになっていることがわかるでしょう。
また、Accept:text/html, application/xhtml+xmlになっています。
ここで見えてくるのが、inertia.fromは非同期でAPI通信をしているが、ResponseはHTMLを要求していることです。
CloudFrontを通すと、jsonが返ってきます。
何故かというと、LaravelがレスポンスをJSONで返すべきかどうかの判定にHTTPリクエストヘッダーのAcceptが関係しているからです。
CloudFrontのカスタムヘッダーにAcceptが無いと、Accept:*/*がリクエスト時にWebサーバーへ送られるため
X-Requested-With:XMLHttpRequestの判定のみとなり、JSONでレスポンスを返すべきリクエストと判定されてしまっています。
ですので、CloudFrontのカスタムヘッダーにAcceptも追加しないといけません。
まとめ
CloudFront+Laravel/Inertia.jsを使った、アプリケーションを構築する時はビヘイビアのカスタムヘッダーに
- X-Inertia
- X-Inertia-Version
- X-Requested-With
- Accept
Laravel/Inertia.jsの構成はこれから色々と機能が拡充されていくと思うので楽しみにしてます。
- Laravel , AWS , Inertia.js