【AWS CloudFront】302がキャッシュされてがぞう見れない問題とその対処法(Lambda@Edge + Nginx)
CloudFront を使っていて、302リダイレクトがキャッシュされてしまい、ユーザーが正しくページを見れないという問題に直面したことはありませんか?
この記事では、CloudFrontが302レスポンスをキャッシュしてしまう問題の対処法と、それに伴うExpress.jsの副作用やNginxを使った回避策について紹介します。
🧨 発生した問題:CloudFrontが302をキャッシュしてしまう
CloudFront はデフォルトで 200以外のレスポンス(302など)もキャッシュする ことがあります。
これにより、一時的なリダイレクトがずっとキャッシュされてしまい、本来表示されるべきページが見られなくなるという事象が発生しました。
💡 解決策:302レスポンスにはキャッシュさせない
✅ 方法① Lambda@Edgeで Cache-Control: no-store
を付与
CloudFrontのオリジンレスポンスに対してLambda@Edgeを使い、ステータスコードが200以外のときだけキャッシュさせないようにします。
exports.handler = async (event) => {
const response = event.Records[0].cf.response;
const statusCode = parseInt(response.status);
if (statusCode !== 200) {
response.headers['cache-control'] = [{
key: 'Cache-Control',
value: 'no-store'
}];
}
return response;
};
ポイント:302などの一時的リダイレクトをCloudFrontでキャッシュさせないようにする。
✅ 方法② CloudFrontのカスタムエラーページのTTLを制御
CloudFrontのエラーページ設定でも、キャッシュ期間を短く制御できます。
設定項目 | 値 |
---|---|
最小 TTL |
0 秒 |
最大 TTL |
600 秒 |
デフォルト TTL |
300 秒 |
これにより、万が一キャッシュされても 短時間で再評価される ようになります。
⚠️ 問題再燃:Express.jsが自動で Cache-Control
を付与してしまう
ここで新たな問題が発生。
Express.js はデフォルトで Cache-Control: public, max-age=xxx
を自動的に付与します。
この挙動により、302以外のレスポンスも含めて一律にキャッシュ設定され、静的ファイルも含めてキャッシュされなくなる という副作用が発生しました。
✅ 回避策:Nginxで強制的に Cache-Control
ヘッダーを上書き
Express.js 側で細かく制御するのが難しかったため、Nginxをリバースプロキシとして挟み、特定のレスポンスだけキャッシュヘッダーを外す構成にしました。
location / {
proxy_pass http://localhost:3000;
# 302 の場合は Cache-Control を外す
proxy_intercept_errors on;
add_header Cache-Control 'no-store' always;
}
※ 状況に応じて
add_header
にif
条件を付けたり、ルールを細かく書き分けることも可能です。
🧪 最終的な構成まとめ
CloudFront
└── Lambda@Edge(200以外のレスポンスに no-store)
└── Nginx(Cache-Controlの強制制御)
└── Express.js(静的ファイル配信)
- ✅ CloudFrontのキャッシュは必要最小限に
- ✅ Lambda@Edgeでステータスベースに振り分け
- ✅ Express.jsの意図しないキャッシュはNginxで上書き
🎯 まとめ
課題 | 解決策 |
---|---|
CloudFrontが302をキャッシュしてしまう | Lambda@Edgeで Cache-Control: no-store を付与 |
エラーページが長くキャッシュされる | TTLを最小0、最大600、デフォ300に設定 |
Expressが自動でキャッシュを付与する | Nginxで強制的に上書きする |
👀 おわりに
CloudFrontでのキャッシュ制御は非常に強力ですが、一歩間違えるとユーザー体験を壊してしまう危険もあります。
本記事のような「200以外のレスポンスに対する適切なキャッシュ制御」は、特に認証リダイレクトや一時的なページ移動が発生するサービスでは重要です。
同じようなことでハマってる人の参考になれば幸いです!
📚 参考文献
-
[1] コンテンツをキャッシュに保持する期間 (有効期限) を管理する
CloudFront がオブジェクトをキャッシュする期間の制御方法について。 -
[1] CloudFront がエラーをキャッシュする時間を制御する
CloudFront は 4xx・5xx レスポンスごとにキャッシュ期間(TTL)を設定可能。 -
[2] エラーレスポンスの動作を設定する - カスタムエラーレスポンス
エラーレスポンスをカスタマイズする方法。 -
[3] HTTP ステータスコード別のカスタムエラーページを作成する
CloudFrontがサポートするエラーページのステータスコード一覧。 -
[4] Lambda@Edge を使用してエッジでカスタマイズする
CloudFront で Lambda@Edge を使う基礎。 -
[5] Lambda@Edge 関数をトリガーできる CloudFront イベント
Lambda@Edge のトリガータイミングに関する解説。 -
[6] オリジンレスポンストリガーでの HTTP レスポンスを更新する
origin-response
を使って HTTP レスポンスを書き換える方法。 -
[7] Cache-Control - HTTP | MDN
Cache-Control: no-store
の意味と動作(AWS公式ではない参考資料)。 -
[8] オリジンが Cache-Control を設定した場合の CloudFront キャッシュ挙動
no-store
などが付与されていても CloudFront 側の最小TTL設定に影響される点。 -
[9] Lambda@Edge 関数の例: エラーステータスコードを 200 に変更
実践的な Lambda@Edge スニペット例。