4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudFront FunctionsでS3静的サイトのディレクトリURL問題をリライトで解決する

Last updated at Posted at 2025-12-01

Japan AWS Top Engineers アドカレ10日目の記事です!

CloudFront+S3でWebサイト公開はキャッシュも使えて料金も安くて本当に重宝しますよね。
Apache、nginx、IISなど使わずに簡単にサイト公開はできるしOSレイヤーの保守やミドルウェアの保守も要らずインフラエンジニアとしてはかなり助かるマネージドな構成だと思います。

ただ、Apache、Nginxで慣れていると思わぬハマりポイントがありますので今日はその一例と解決方法を記載します。

/dashboard/など特定のディレクトリページが見れない

https://example.com/dashboard/

などwebシステムでログイン後にダッシュボードなど表示させたいときにディレクトリ構造を作ることはよくあるかと思います。
今日は上記のように/dashboard/でURLを入力した際にページが表示されない場合の対処方法を記載します。

構成図、S3の構造

構成はよくあるCloudFront+S3のフロント構成です。

image1.png

S3の構成は以下のような感じです。

┌─────────────────────────┐
│ S3 bucket               │
├─────────────────────────┤
│ 📁 404/                 │
│ 📄 404.html             │
│ 📁 dashboard/           │
│    └── 📄 index.html    │
│ 📁 forgot-password/     │
│ 📄 index.html           │
│ 📁 login/               │
│ 📁 signup/              │
└─────────────────────────┘

CloudFront配下のS3はOAI(Origin Access Identity)によりS3バケットへの直接アクセスは禁止にしています。

特定のディレクトリにあるindex.htmlが見えない

本来はhttps://example.com/dashboard/にアクセスするとhttps://example.com/dashboard/index.htmlのページが見えてほしいところです。
ですが標準のCloudFront+S3の構成だとページが表示しません。
ただ、https://example.com/dashboard/index.htmlでアクセスするとページは表示します。

なぜ特定のディレクトリにあるindex.htmlが見えないか

S3はオブジェクトストレージであり、LinuxやWindowsのようなファイルシステムとは異なります。
リクエストされたパスをそのままオブジェクトキーとして探すため、https://example.com/dashboard/ でアクセスすると /dashboard/ というオブジェクトを返そうとします。
しかし /dashboard/ はオブジェクトではなく、キー名に / を含むオブジェクトをコンソールが便宜上グループ化して表示しているだけです。
実際にはフォルダもオブジェクトも存在しないため、403エラーが返されます。
内部的には403をS3が返しますがWebアクセスですとトップページのindex.htmlが表示され、ダッシュボードにアクセスしたけどトップページにアクセスが飛ばされるような動きとなります。

curlで確認するx-cache: Error from cloudfrontと返ってきます。

curl -I https://{cloudfornturl}.net/dashboard/ | grep x-cache
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0  9868    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
x-cache: Error from cloudfront

デモサイトですがhttps://example.com/dashboard/にアクセスしてもトップのindex.html(Home)が表示されます。内部的にはエラーレスポンスを返して/index.htmlにフォールバックされています。
スクリーンショット_2025-11-30_23_57_04.jpg

https://example.com/dashboard/index.htmlにアクセスするとオブジェクトがありますのでブラウザでも正常に表示がされます。
スクリーンショット_2025-11-30_23_57_14.jpg

CloudFront FunctionでURLリライトをする

https://example.com/dashboard/などのアクセスで/dashboard/index.htmlのページを表示させるにはCloudFront Functionを作成し、対象のCloudFrontに関連付けをします。

1.[CloudFront]→[関数]を選択し、Functionsタブで「関数を作成」を選択します。

スクリーンショット_2025-12-01_20_12_30.jpg

2.[名前]は任意の名前を設定、[Runtime]は「cloudfront-js-1.0」を選択し、作成します。

スクリーンショット 2025-12-01 20.13.32.png

3.Functionの画面に遷移しますので[構築]タブ内の関数コードを以下コードに書き換えて「変更を保存」を選択します。

function handler(event) {
  var request = event.request;
  var uri = request.uri;

  // URIが/で終わる場合、index.htmlを追加
  if (uri.endsWith('/')) {
    request.uri = uri + 'index.html';
  }
  // URIに拡張子がない場合(ファイルでない場合)、/index.htmlを追加
  else if (!uri.includes('.')) {
    request.uri = uri + '/index.html';
  }

  return request;
}

スクリーンショット 2025-12-01 20.14.16.png

4.作成したFunctionをCloudFrontに関連付けします。
対象のCloudFrontを選択し、[ビヘイビア]タブ内のビヘイビアを選択して「編集」を選択してください。

スクリーンショット_2025-12-01_20_18_46.jpg

画面下部にある[関数の関連付け]内で[ビューワーリクエスト]の関数タイプを「CloudFront Functions」に設定し、[関数ARN]に作成したFunctionを選択して「Save changes」を選択してください。

スクリーンショット_2025-12-01_20_21_49.jpg

以上で設定完了です。

https://example.com/dashboard/にアクセスするとCloudFront Functionでリライト処理が行われてhttps://example.com/dashboard/index.htmlにアクセスできました。

スクリーンショット_2025-12-01_20_25_26.jpg

Apache、Nginxではなぜアクセスできるのか

ApacheやNginxといった従来のWebサーバには、ディレクトリにアクセスした際に自動的に index.html を探して返す機能が標準で備わっています。
例えば、/dashboard/ にアクセスすると、Webサーバが自動的に /dashboard/index.html を探して表示してくれます。これはWebサーバの基本機能として、特別な設定をしなくても動作します。

一方、S3はオブジェクトストレージであり、Webサーバのような機能はありません。
指定されたキー(パス)のオブジェクトを返すだけしかできません。

そのため、S3には自動的に index.html を補完する機能がないため、/dashboard/ というリクエストに対して dashboard/ というキーを探しますが、そのようなオブジェクトは存在せず、結果として403エラーが返ります。

これが、CloudFront Functionsによるリライトが必要な理由です。 CloudFront Functionsを使うことで、Webサーバと同じように /dashboard//dashboard/index.html に自動変換できます。

まとめ

CloudFront+S3でSPAやWebサイトを公開する際、ディレクトリ形式のURL(/dashboard/)でアクセスできない問題は、S3がオブジェクトストレージであり、Webサーバのような自動的なindex.html解決機能がないことが原因です。

CloudFront Functionsを使ってURLリライトを行うことでApache、nignxと同等の動作が実現できます。

  • CloudFront Functionの変更後、反映には数分かかる場合があります
  • 既存のキャッシュがある場合は、キャッシュの無効化が必要な場合があります
4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?