AWS プリフライトリクエストに対応したAPIGatewayの定義をSwaggerで記述する

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

SwaggerでAPIGateway + Lambdaの構成定義を書いたのでメモしておきます。


出来上がりのtemplate.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
  getData:
    Type: 'AWS::Serverless::Function'
    Properties:
      CodeUri: getData/
      Handler: get-data.lambda_handler
      Runtime: python3.6
      Role: arn:aws:iam::****:role/your-lambda-execute-role
  Api:
    Type: 'AWS::Serverless::Api'
    Properties:
      StageName: Prod
      DefinitionBody:
        swagger: "2.0"
        info:
          version: "1.0"
          title: "lambda-web-interface"
        schemes:
        - "https"
        paths:
          /data:
            get:
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Sub arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/${getData.Arn}/invocations
                passthroughBehavior: "when_no_match"
                httpMethod: "POST"
                type: "aws_proxy"
            options:
              consumes:
                - application/json
              produces:
                - application/json
              x-amazon-apigateway-integration:
                type: mock
                requestTemplates:
                  application/json: |
                    {
                      "statusCode" : 200
                    }
                responses:
                  "default":
                    statusCode: "200"
                    responseParameters:
                      method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                      method.response.header.Access-Control-Allow-Methods : "'GET, POST, PUT, DELETE'"
                      method.response.header.Access-Control-Allow-Origin : "'*'"
                    responseTemplates:
                      application/json: |
                        {}
              responses:
                "200":
                  headers:
                    Access-Control-Allow-Headers:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Origin:
                      type: "string"
  getDataPermission:
    Type: "AWS::Lambda::Permission"
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref getData
      Principal: apigateway.amazonaws.com


Lambda関数

getDataというLambda関数を定義します。関数の実装は、getData/get-data.pyという名前で作成してあります。

  getData:
    Type: 'AWS::Serverless::Function'
    Properties:
      CodeUri: getData/
      Handler: get-data.lambda_handler
      Runtime: python3.6
      Role: arn:aws:iam::****:role/your-lambda-execute-role


API Gatewayの定義

Lambda呼び出しのインターフェース

REST APIでpath:data/にGET時のAPI Gatewayの定義。同ファイル内に定義したLambda関数を呼び出すよう、uri: !Sub arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/${getData.Arn}/invocationsと記述して参照してます。

  Api:
    Type: 'AWS::Serverless::Api'
    Properties:
      StageName: Prod
      DefinitionBody:
        swagger: "2.0"
        info:
          version: "1.0"
          title: "lambda-web-interface"
        schemes:
        - "https"
        paths:
          /data:
            get:
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Sub arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/${getData.Arn}/invocations
                passthroughBehavior: "when_no_match"
                httpMethod: "POST"
                type: "aws_proxy"

x-amazon-apigateway-integrationはベンダー拡張の属性でAWS側のLambda関数のイベントソースとなる為の項目らしいです。httpMethodはPOSTなるので注意。

参考: x-amazon-apigateway-integration オブジェクト - Amazon API Gateway


OPTIONメソッド プリフライトの定義

optionメソッドの定義にプリフライト時に許可するHeader、Origin、Methodを記述する。optionのtypeはラムダのイベントとはならないのでmockと定義するみたいです。

            options:
              consumes:
                - application/json
              produces:
                - application/json
              x-amazon-apigateway-integration:
                type: mock
                requestTemplates:
                  application/json: |
                    {
                      "statusCode" : 200
                    }
                responses:
                  "default":
                    statusCode: "200"
                    responseParameters:
                      method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                      method.response.header.Access-Control-Allow-Methods : "'GET, POST, PUT, DELETE'"
                      method.response.header.Access-Control-Allow-Origin : "'*'"
                    responseTemplates:
                      application/json: |
                        {}
              responses:
                "200":
                  headers:
                    Access-Control-Allow-Headers:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Origin:
                      type: "string"

ブラウザはOPTIONメソッドから返されたレスポンスを見て実際に送信可能であるか判断します。


Lambdaの実行権限

忘れずにLambdaの実行ロールを記述しよう。

  getDataPermission:
    Type: "AWS::Lambda::Permission"
    Properties: 
      Action: lambda:InvokeFunction
      FunctionName: !Ref getData
      Principal: apigateway.amazonaws.com