📃
CloudFrontでSPAをやりつつ背後にAPI Gatewayもある時のエラーレスポンスの扱いをいまさらながら
- 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で書き換えたステータスコード、リクエスト元には影響ないはずですよね?
- オリジンにリクエストしレスポンスされる (
404
) - Lambda@Edgeがレスポンス内のステータスコードを書き換える (
400
) - CloudFrontがオリジンレスポンスに応じてカスタムエラーレスポンスする (
200
) - クライアントに届く (
200
)
だから、極論 501 Not Implemented とかでいいのかもしれないです。
S3が返す5xx系のステータスコードは、以下の記事を元にすると、500と503らしいので…
Discussion
CloudFront Functions を使って対応できないのかな、とは思っている