はじめに

AWS App Runner で Cantaloupe(IIIF画像サーバー)をホストし、その前段に CloudFront を配置しようとしたところ、CloudFront 経由でアクセスすると全てのリクエストが 404 エラーになる問題に遭遇しました。

本記事では、問題の原因調査から試した解決策、そして結論までを記録します。

環境

  • アプリケーション : Cantaloupe 5.0.5(IIIF画像サーバー)
  • ホスティング : AWS App Runner
  • CDN : Amazon CloudFront
  • リージョン : ap-northeast-1(東京)

問題の概要

症状

アクセス方法結果
App Runner に直接アクセス200 OK
CloudFront 経由でアクセス404 Not Found

確認したこと

CloudFront 経由で 404 が返る際、レスポンスヘッダーに server: envoy が含まれていました。これは App Runner の内部プロキシ(Envoy)に到達していることを示しています。

$HsxTe-cTrcuPar/ecl2rh:e-4:I0e4nEhvrtortyoprs:f/r/oxmxxcxlxo.ucdlforuodnftront.net/

つまり、CloudFront → App Runner の通信は成功しているが、App Runner 内部でリクエストがアプリケーション(Cantaloupe)に転送されていないことがわかりました。

原因

Host ヘッダーの問題

App Runner の内部では、Envoy がリバースプロキシとして動作しています。Envoy は Host ヘッダー を見てリクエストをルーティングします。

ClHoHouosEdsEtnFtn:vr:voooxynxy:xtxxxxxxHxH.o.oascspt:lt-onuodrftrhoenats.tn-e1t.aw4s0a4pp2r0u0nnOeKr.com

なぜ Host ヘッダーが CloudFront のドメインになるのか

CloudFront がオリジン(App Runner)にリクエストを転送する際、デフォルトではビューワーの Host ヘッダーがそのまま転送されます。

試した解決策

1. オリジンリクエストポリシー「AllViewerExceptHostHeader」

AWS が App Runner 向けに推奨しているポリシーです。このポリシーは Host ヘッダーを除外し、CloudFront がオリジンのドメイン名を Host ヘッダーとして自動設定するはずです。

結果 : ❌ 失敗(404 のまま)

2. オリジンリクエストポリシー「なし」

ビューワーのヘッダーを一切転送しない設定です。

結果 : ❌ 失敗(404 のまま)

3. カスタムオリジンリクエストポリシー

明示的に「ヘッダー: なし」を設定したカスタムポリシーを作成しました。

Cook:ie::

結果 : ❌ 失敗(404 のまま)

4. CloudFront Functions で Host ヘッダーを書き換え

ビューワーリクエスト時に Host ヘッダーを App Runner のドメインに書き換えようとしました。

f}unctvrriaeeorqtnuurerhesnaqtnu.rdehelseqetaurde(=esertves;ev[ne'tnh)to.s{rte'q]ue=st{;value:'xxxxx.ap-northeast-1.awsapprunner.com'};

結果 : ❌ 失敗

502ERROR:TheCloudFrontfunctiontriedtoadd,delete,orchangearead-onlyheader.

CloudFront Functions では、ビューワーリクエストイベントで Host ヘッダーは読み取り専用であり、変更できません。

5. Lambda@Edge で Host ヘッダーを書き換え

Lambda@Edge はオリジンリクエストイベントで実行でき、より多くのヘッダーを変更できます。

e}x;porcrrtoeesnqt.suuhterasnnrtde.rlqheeueqreausde=tesrta=s;s[ye'nvhceons(tte.'vR]eenc=to)r[d{=s>[k0e{]y.:cf'.Hroesqtu'e,stv;alue:'xxxxx.ap-northeast-1.awsapprunner.com'}];

結果 : ❌ 失敗

502ERROR:TheLambdafunctionresultfailedvalidation:Thefunctiontriedtoadd,delete,orchangearead-onlyheader.

Lambda@Edge のオリジンリクエストイベントでも Host ヘッダーは読み取り専用でした。

6. 新しい App Runner サービスと CloudFront ディストリビューションを作成

既存の設定に問題がある可能性を考え、完全に新しいリソースを作成しました。

  • 新しい App Runner サービス(カスタムドメインなし)
  • 新しい CloudFront ディストリビューション
  • オリジンリクエストポリシー「AllViewerExceptHostHeader」

結果 : ❌ 失敗(404 のまま)

調査で判明したこと

App Runner のログ確認

App Runner に直接アクセスした場合のログ:

Hos2t0:0xOxKxxx.ap-northeast-1.awsapprunner.com

CloudFront 経由でアクセスした場合:

  • Cantaloupe のログにリクエストが記録されない
  • つまり、Envoy がリクエストをアプリケーションに転送する前に 404 を返している

curlで Host ヘッダーを変更してテスト

App Runner に直接アクセスする際、Host ヘッダーを CloudFront のドメインに変更:

$HsTecTruPr/el1r.:-1Ie4n-0vH4oy"NHootstF:ouxnxdxxx.cloudfront.net"https://xxxxx.ap-northeast-1.awsapprunner.com/

404 が再現しました。 これで、問題は Host ヘッダーにあることが確定しました。

結論

問題の本質

CloudFront + App Runner の組み合わせで 404 エラーが発生する問題は、App Runner の Envoy が Host ヘッダーでルーティングを行っている ことが原因です。

「AllViewerExceptHostHeader」ポリシーを使用しても解決しない場合、これは App Runner 側の問題 と考えられます。

推奨される対応

  1. AWS サポートに問い合わせる

    • App Runner + CloudFront で 404 が発生する問題として報告
  2. 代替アーキテクチャを検討する

    • ECS Fargate + ALB : CloudFront との連携実績が豊富
    • EC2 + Nginx : 最も柔軟な構成
    • Cloudflare : Host ヘッダーの書き換えが容易

参考情報

同様の問題を報告している記事

これらの記事では「AllViewerExceptHostHeader」で解決したと報告されていますが、今回のケースでは解決しませんでした。

AWS ドキュメント

まとめ

試した方法結果
AllViewerExceptHostHeader
オリジンリクエストポリシー「なし」
カスタムポリシー(ヘッダーなし)
CloudFront Functions❌ (Host は読み取り専用)
Lambda@Edge❌ (Host は読み取り専用)
新規リソース作成

設定はすべて正しいにもかかわらず動作しないため、App Runner の内部動作に起因する問題と考えられます。CloudFront + App Runner の組み合わせを検討している方は、この問題に遭遇する可能性があることを念頭に置いてください。