概要
SPAやSSG、ISRをS3やGCSなどのクラウドオブジェクトストレージでホスティングする場合、
静的コンテンツが存在するパス以外にアクセスするとクラウドオブジェクトストレージでステータスコードの403エラーを返します。
今回はこれを防ぐためにどのように対策するのがいいのかをアプリケーションコードによるHTTPの挙動を交えて説明しようと思います。
気をつけるポイント
- 例外処理の場合どこの層でルーティングされるのか
- S3の層でルーティングされるのか、フロントエンドの層でルーティングされるのか
前提条件
- 今回はSPAを例にとって話をします
- 使う言語はVue.jsにします
- AWS環境です
例外処理でのフロントエンドでのルーティング
まずはVue.jsでのルーティングの挙動を確認していきます。
Vue.js と vue-routerで制定コンテンツが存在しない場合のルーティングの書き方は以下の通りになります。
const router = new VueRouter({
routes: [
// コロンで始まる動的セグメント
{ path: '/user/:id', component: User }
{ path: '/*', component: NotFound }
]
})
参考資料: https://router.vuejs.org/ja/guide/essentials/dynamic-matching.html#すべてキャッチするルート-404-not-found-ルート
これでVue.js上に存在しないパスにアクセスすると404エラーを返すようになるとお思いになるでしょう。
ただし、これだとS3の403エラーが返ってきます。
よくはまるミス
これの原因は至ってシンプルです。vue-routerにアクセスする前にS3バケットにアクセスするため、S3のエラーが出てしまいます。
対策
これを解消するためにはS3の前にL7ロードバランサー or CDN(ここだとCloudFront)を置き、S3が403を返してきたときに/404.htmlにアクセスするように設定してVue.jsへアクセスできるようにしましょう。
まとめ
今回はS3でフロントエンドのコードをホスティングしましたが、オブジェクトストレージでフロントエンドのコードをホスティングする場合は、コードの前段にホスティンサービスにリクエストが届くので、HTTPのリクエスト/レスポンスをねじ曲げる層が必要になってきます。そこを意識してインフラ構成を考えるとハマることが少ないと思います。
こちらはSPA(AngularJS)でCloudFront+S3環境でホスティングする場合の具体的な対応が書いていますので、実装の時の参考にしていただければ幸いです。