こんにちは、遠藤です。
今回はAPI GatewayとLambdaを使用してAPIを作成してみたところ、CORSの設定でつまずいたのでその内容と解決方法を共有します。
- つまずいた内容
- 解決方法
1. つまずいた内容
簡潔に述べると、
S3の静的ウェブサイトホスティングを使用して公開されているサイトからAPIを呼び出したところ、GETメソッドやPOSTメソッドのリクエストはLambdaのレスポンスヘッダーにCORS設定を記載したら問題なく動いたが、DELETEメソッドにするとLambdaのレスポンスヘッダーにCORS設定を記載を記載しても動かなかった
というのが今回のつまずきの内容です。
詳細を以下に記載します。
GETの場合のLambdaは以下のように実装しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
exports.handler = async function(event, context) { let sample = []; // DBからの取得処理など const response = { statusCode: 200, headers: { "Access-Control-Allow-Headers" : "*", "Access-Control-Allow-Origin": "http://{S3バケット名}.s3-website-ap-southeast-1.amazonaws.com", "Access-Control-Allow-Methods": "OPTIONS,POST,GET" }, body: JSON.stringify(sample), }; return response; }; |
DELETEの場合のLambdaは以下のように実装しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
exports.handler = async function(event, context) { let sample = []; // DBからの削除処理など const response = { statusCode: 200, headers: { "Access-Control-Allow-Headers" : "*", "Access-Control-Allow-Origin": "http://{S3バケット名}.s3-website-ap-southeast-1.amazonaws.com", "Access-Control-Allow-Methods": "OPTIONS,DELETE" }, body: JSON.stringify(sample), }; return response; }; |
GET及びDELETEどちらの場合も同様にレスポンスのheadersに指定しておりますが、S3から呼び出そうとするとGETの場合は問題なく通ったもののDELETEの場合はCORSエラーでブロックされてしまいました。
API Gatewayで何かブロックされているのではと思って調査したところ、以下のようなCORSの設定画面がありました。
しかし、この画面についてはGETの場合にも設定されておらず、DELETE側だけ特殊な設定がされているようには見受けられませんでした。そのため、どこに原因があるのか分からず詰まってしまったというのが今回のつまずきの内容です。
2. 解決方法
Lambdaに記載したソースコードは正常なはずなのにCORSでブロックされるということは、API Gatewayに問題があるのではないかと思い、API GatewayのCORS設定を以下のように設定しました。
すると、問題なくS3からDELETEメソッドのAPIを実行することができました。
しかし、次はGETメソッドのアクセスができなくなってしまいました。よく見ると「If you configure CORS for an API, API Gateway ignores CORS headers returned from your backend integration.」という注記がありました。翻訳すると「API に CORS を設定すると、API Gateway はバックエンド統合から返された CORS ヘッダーを無視します。」とのことでした。つまり、Lambdaで設定していたCORS関連のヘッダー情報はAPI Gatewayによって上書きされてしまっているようでした。そこで、上記にGETメソッドやPOSTメソッドを追加したところ問題なくS3から全てのメソッドのAPIを呼び出すことができるようになりました。
なぜ、API Gatewayで明示的にCORSの設定をしていない状態でGETやPOSTは表示され、DELETEは表示されないのかについての決定的なドキュメントを探すことはできませんでしたが、API GatewayのCORS設定を使用して許可設定を実施することで解決できることは分かりました。
ただし、1つのAPI Gatewayに対して、Lambda関数を複数統合している場合は、全て同じCORS設定となってしまいます。API GatewayのCORS設定にはそれぞれの統合ごとにCORSを設定する方法はなく、全体に適用されます。大半のケースで問題なく使用できますが、Lambda関数ごとにCORSの設定を切り替えたいという場合はAPI Gatewayごと変更することが必要です。