概要
AWS LambdaでS3の静的サイトを表示するAPIを構築していたら、Console画面で以下のCORSエラーに遭遇。
Access to fetch at 'https://xxxx' from origin 'https://xxxxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error xxxxx
Failed to load resource: net::ERR_FAILEDUnderstand this error
xxxxxx
Uncaught (in promise) TypeError: Failed to fetch
at xxxxxx
原因
エラーにある通り、CORS(Cross-Origin Resource Sharing)に問題がありました。
異なるオリジン間の通信(Lambda側のオリジン、S3側のオリジン)が発生するため、「クロスオリジンリクエスト」となります。
ブラウザは、セキュリティのため異なるオリジンへのリクエストを制限しますので、
サーバ側が明示的に「このオリジンからのアクセスを許可する」と宣言する必要があります。
今回は、
「とあるS3の静的ファイルの中のJSが(ApiGateway経由で)Lambdaのエンドポイントをコールする」
という流れの中で上記のエラーが発生していました。
S3の静的ウェブサイトホスティングのドメインとLambda関数のドメインが異なっていたので、このようなCORSエラーになっていたと考えられます。
解決方法
S3にレスポンスを返すLambda(Djangoフレームワーク)のコードで以下のようにしていたので、
return JsonResponse(json_data)
以下にすればOKです。
return JsonResponse(json_data, headers={"Access-Control-Allow-Origin": "*"})
ただし、このヘッダー追加は、「全てのオリジンからのアクセスを許可する」という意味になります。
本番環境では、セキュリティ上「全てのオリジンを許可」というのは推奨されません。
実際に運用する際は、特定のオリジンのみを許可する、などの考慮が必要です。