ReactからAxiosでLambdaで作ったAPIへリクエストした時に、CORSの設定でハマったのでメモしておきます。
症状
curl
ではレスポンスがAPIから帰ってくるが、Axios
でReact側からリクエストをすると、下記のエラーメッセージが返ってくる。
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
原因
API GatewayでCORSが有効化されていない。
Lambda関数が必要なヘッダー情報を返していない。
CORS(Cross-origin resource sharing) とは?
- ブラウザのセキュリティ機能。
- ブラウザからのHTTPリクエストを制限する。
ざっくりいうとこのセキュリティ機能のせいで、ReactからLambdaのAPIを叩けない。
具体的に言うと、プレフライトリクエストがアクセスコントロールチェックをパスしていない。
プレフライトリクエストについて
簡単言うと、OPTIONSメソッドでAPIへの疎通確認するリクエスト。
詳しくは、https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#preflighted_requests
解決法
1. APIGatewayでCORSを有効化
⑴ AWSにログイン。APIGatewayのコンソール画面からAPIを選ぶ。
⑵ 「アクション」 > 「CORSの有効化」を選択。
⑶ ヘッダーの設定
- メソッド:OPTIONSにチェックが入ってることを確認。(preflightアクセスで使う。OPTIONSメソッドでAPIへの疎通確認。)
-
Access-Control-Allow-Headers
が、デフォルトは'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
だけど、オープンな場合認証情報は必要ないので'Content-Type,X-Amz-Date'
に設定。
設定が終わったら「CORS を有効にして既存の CORS ヘッダーを置換」ボタンをクリック。
⑷ APIのデプロイをクリック
「APIのデプロイ」をクリック。デプロイしないと設定が反映されない。
###2. Lambdaで必要なヘッダー情報を返す。
下ようにヘッダー情報を返すように関数を修正。デプロイする。
import json
def lambda_handler(event, context):
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*', // アクセス元を限定するときは 'https://www.example.com'と指定。
'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
},
'body': json.dumps('Hello from Lambda!')
}
3. Reactからリクエストを投げる
import axios from 'axios';
axios({
method: 'post',
url:'https://xxx.execute-api.ap-northeast-1.amazonaws.com/default/your-api',
data: {
line_count: lineCount,
text: finalText,
},
})
.then(results => {
console.log(results);
)
.catch(results => {
console.log(results);
});
最後に
これでレスポンスが返ってくるようになりました。
もし、これでもまだ返ってこない場合は、LambdaのCloudWatchのログを見てみるか、Testing CORS - Amazon API Gateway を参考にCORSテストをしてみてください。
参考
APIGatewayでCORSを有効化
https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html
LambdaでCORSを有効化
https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html