Tech note

備忘録

CloudFront + S3の構成で、Nuxtで静的化したコンテンツのページをリロードすると404エラーが発生する

事象

Amazon S3 + Amazon CloudFrontの構成で、Nuxtで静的化したコンテンツをS3に配置した際に、 ルート(/index.html)以外のページで、更新すると404エラー「NoSuchKey」が発生する。

構成

f:id:sbu8:20200829193721p:plain

前提

Nuxtで静的化を行うと、以下のようなフォルダ構成となる。

  • /pages/index.vue

    /index.html
  • /pages/test.vue

    /test/index.html

CloudFrontの設定で、Origin Domain NameにS3のバケット名を指定している。 f:id:sbu8:20200823013732p:plain

原因

CloudFrontの設定で、Default Root Objectを「index.html」とすると以下のような動作となる。 f:id:sbu8:20200829172057p:plain

そのため、ルート以外では「index.html」を返さないので、ファイルが存在せずにエラーとなってしまう。

解決方法

解決方法としては、以下の2つの方法がある。

1つ目

Lambda@Edgeを使用して、CloudFront がリクエストをS3オリジンに転送する前にURLを書き換えてサブディレクトリにも「index.html」を付与した状態で、S3オリジンにリクエストするようにする。

2つ目

CloudFrontの設定で、Origin Domain NameにS3のバケット名を指定するのではなく、S3バケットのStatic website hostingのエンドポイントを指定する。

それぞれの解決策での特徴

1つ目
  • S3をパブリック公開としなくても良いため、直接アクセスされてしまうことを防げる。

  • CloudFrontにキャッシュが存在しない場合のみ、Lambda@Edge が実行される。

2つ目
  • S3をパブリック公開の設定をしなければいけないため、S3のバケット名が分かると直接アクセスされてしまう。

  • S3でStatic website hostingの設定をしなければいけない。
    ※インデックスドキュメントの設定を「index.html」とする。

  • CloudFrontに対して AWS WAFでIPアドレス制御をしてもS3まで制御することが出来ないため、 S3でも同様の制御を行わないといけない。

  • サブディレクトリでも「index.html」を返す。

【追記:2021年6月13日】

CloudFront Functionsがリリースされたため、パス書き換えにはLambda@EdgeよりもCloudFront Functionsが適している。