📃

CloudFrontでSPAをやりつつ背後にAPI Gatewayもある時のエラーレスポンスの扱いをいまさらながら

に公開1
  • CloudFront
    • /api/* -> API Gateway -> Lambda
    • /index.html -> S3 SPA resource
    • default (*) -> 同上

この時、SPAのルーティングに合わせるため、CloudFrontディストリビューションのカスタムエラーレスポンスを設定し、404, 403の時にindex.htmlを200で返す設定をやります。

が、そうすると、APIが空の結果・取得対象無しで 404 Not Found を返すとき、index.htmlがレスポンスされてしまう…
(空の結果を正常系のステータスコードにすべきかどうかの話はしません)

ということで、デフォルトのビヘイビアの、オリジンレスポンスに以下のようなLambda@Edgeを設定して事なきを得ました。

exports.handler = (event, _, callback) => {
	const response = event.Records[0].cf.response;

	// 元のステータスコードを保存
	const originalStatus = response.status;

	// 404/403エラーを400に変換
	if (originalStatus === "404" || originalStatus === "403") {
		response.status = "400";
		response.statusDescription = "SPA Routing";

		// デバッグ用のヘッダー追加
		response.headers["x-origin-status"] = [
			{
				key: "X-Origin-Status",
				value: originalStatus, // 元のステータスコードを使用
			},
		];
	}

	callback(null, response);
};

400に対するカスタムエラーレスポンスが必要にはなります。
/api/* ビヘイビアへのリクエスト・レスポンスに影響がなくなったため、APIの404も正しくレスポンスできるようになりました。

当然、APIが400を返すことがあったらその時はうまく動かないですね。
その時は…カスタムエラーレスポンスで使える他のステータスコードを使うしかないでしょうか。

独自のステータスコード(499とか)使えたら安心なんですけどね。

このLambda@Edgeで書き換えたステータスコード、リクエスト元には影響ないはずですよね?

  1. オリジンにリクエストしレスポンスされる (404)
  2. Lambda@Edgeがレスポンス内のステータスコードを書き換える (400)
  3. CloudFrontがオリジンレスポンスに応じてカスタムエラーレスポンスする (200)
  4. クライアントに届く (200)

だから、極論 501 Not Implemented とかでいいのかもしれないです。
S3が返す5xx系のステータスコードは、以下の記事を元にすると、500と503らしいので…

https://repost.aws/ja/knowledge-center/http-5xx-errors-s3

Discussion

chatiichatii

CloudFront Functions を使って対応できないのかな、とは思っている