Amazon-API-Gateway

API Gateway Lambdaプロキシ統合のCORSで必要な設定を調べてみた

はじめに

こんにちは、omkです。
WEBコンテンツが全くわからないので、同じく全くわからない方向けにLambdaプロキシ統合利用時のAPIGatewayのCORS設定で何が必要かざっくりまとめてみます。
知ってみれば普通のCORSの話ですが、CORSのエラーでコケたときに何したらええんや……となったのでLambda統合プロキシにおけるポイントを伝えられればと思います。

CORSについて

MDN Web Docsのリンクを置いておきます。
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

通常、オリジンを跨いでの通信はセキュリティ的に心配なところです。
で、「オリジンAを跨いでのリクエストをオリジンBで許可する」というヘッダを「オリジンB」のレスポンスに含めることでこれを許可します。
この設定がオリジンBに入っていない場合はオリジンBからのレスポンスは返ってきますがブラウザが止めてしまいます。
このあたりは以下のサイトが参考になりました。
https://coliss.com/articles/build-websites/operation/work/cs-visualized-cors.html

API GatewayのCORS設定(統合プロキシでないケース)

API Gatewayには「CORSの有効化」というボタンがあり、これを押せばCORSが有効になる設定が行われます。

普通の(?)Rest APIで本設定を行った場合、
「OPTIONS」メソッドが作成され、各メソッドにCORSのレスポンスヘッダーが設定されます。


→OPTIONS統合レスポンスで有効化時の既存のメソッド・その他ヘッダーでのCORSを許可、


→OPTIONSで統合レスポンスのヘッダーの値をレスポンス



→GETでCORS許可のレスポンス

このように対象のメソッド(今回はGET)とOPTIONSメソッドでCORSの許可設定を入れれば良いことがわかります。
しかし、Lambdaプロキシ統合ではLambdaに対応したメソッドで統合レスポンスが使用できないのでどのように設定するべきでしょうか。

結論

必要なヘッダーをLambdaのレスポンスに含める必要があります

まずは単純リクエストかどうかの確認が必要です。
単純リクエストはOPTIONSにリクエストしないリクエストです。

単純リクエストの条件についてはこちらの記事がわかりやすいです。
CORS: OPTIONSリクエスト(preflight request)を避ける

単純リクエストに該当するものであれば特に対応は不要です。該当しなければ対応が必要となります。

どのように対応すべきか

通常のやるべきことは以下に載ってます。
REST API リソースの CORS を有効にする
これと同じことをLambdaで行うようにします。

例えば、GETをLambdaに統合しているとしてレスポンスでContent-Typeに「application/json」を指定するとします。
これは単純リクエストに該当しないので対応が必要です。

この場合、GETのレスポンスとしては「Access-Control-Allow-Origin」を含めて返す必要がありますので、
Lambdaのレスポンスとしては以下のように返しておけば良いです(例はPython)。

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        "headers": {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": '*'
        },
        'body': json.dumps('Hello from Lambda!')
    }

あとはLambdaプロキシ統合以外と同じです。
API Gateway側でOPTIONSに「Access-Control-Allow-Origin」、「Access-Control-Allow-Methods」、「Access-Control-Allow-Headers」の設定を含めます。
まぁ、「CORS設定の有効化」を実行しておけばOKです。

まとめ

プロキシ統合のLambdaで動作するメソッドで必要なヘッダーは全部Lambdaのレスポンスに含めましょう。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA