Skip to content

CloudFront CachePolicyにNext.js RSCヘッダーが含まれておらずキャッシュ汚染が発生する #100

@konokenj

Description

@konokenj

概要

CloudFrontのCachePolicyCacheHeaderBehavior.allowListにNext.js App RouterのRSC(React Server Components)関連ヘッダーが含まれていないため、RSCフライトレスポンス(text/x-component)と通常のHTMLレスポンスが同一キャッシュキーで扱われ、キャッシュ汚染が発生する。

問題の詳細

Next.js App Routerのクライアントサイドナビゲーションでは、ブラウザが同一URLに対して2種類のリクエストを送る:

  1. HTMLリクエスト — 初回アクセス・フルページロード
  2. RSCリクエストRSC: 1ヘッダー付き、クライアントサイドナビゲーション時

レスポンス形式が全く異なる(HTML vs text/x-componentフライトデータ)にもかかわらず、現在のCachePolicyではこれらを区別できない。

顕在化条件

現在のサンプルアプリは全ページがcookies()を呼ぶ動的レンダリングのため、Next.jsがCache-Control: private, no-cache, no-storeを返し、minTTL=0の設定下ではCloudFrontがキャッシュしないため問題が顕在化しにくい。

しかし以下の条件で問題が発生する:

  • 静的にレンダリング可能なページ(cookies()headers()を呼ばないServer Component)を追加した場合
  • ISR(Incremental Static Regeneration)を使用した場合
  • 明示的にキャッシュヘッダーを設定した場合

スターターキットとしてユーザーが静的ページを追加するのは自然な利用パターンであり、その時点で確実に問題が発生する。

該当箇所

cdk/lib/constructs/cf-lambda-furl-service/service.ts L84-91

headerBehavior: CacheHeaderBehavior.allowList(
  'authorization',
  'Origin',
  'X-HTTP-Method-Override',
  'X-HTTP-Method',
  'X-Method-Override',
),

修正案

CacheHeaderBehavior.allowListにRSCヘッダー4つを追加する:

headerBehavior: CacheHeaderBehavior.allowList(
  'authorization',
  'Origin',
  'X-HTTP-Method-Override',
  'X-HTTP-Method',
  'X-Method-Override',
  // Next.js App Router RSC headers
  // Without these, RSC flight responses (text/x-component) are cached and served
  // for normal HTML requests, causing cache poisoning.
  'RSC',
  'Next-Router-Prefetch',
  'Next-Router-State-Tree',
  'Next-URL',
),
ヘッダー 用途
RSC RSCリクエストであることを示す(値: 1
Next-Router-Prefetch プリフェッチリクエストの識別
Next-Router-State-Tree ルーターの状態ツリー
Next-URL Next.js内部のURL情報

検証方法

  • CloudFrontキャッシュ有効時に、ブラウザナビゲーション(HTMLリクエスト)とクライアントサイドナビゲーション(RSCリクエスト)で異なるレスポンスが返ること
  • RSCリクエスト(RSC: 1ヘッダー付き)のレスポンスがHTMLリクエストに返されないこと

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions