使用SAM将lambda集成添加到HttpApi路由

问题描述

我目前正在尝试将AWS::Serverless::HttpApi与一组AWS::Serverless::Function集成在一起。目标是在SAM模板中定义这些资源,并使用swagger文件定义实际的API。

我的SAM模板定义如下:


Resources:
  apiPing:
    Type: AWS::Serverless::Function
    Properties:
      Description: 'Ping'
      CodeUri: ../bin/cmd-api-ping.zip
      Handler: cmd-api-ping
      Runtime: go1.x
      Role:
        Fn::GetAtt: apiLambdaRole.Arn
      Events:
        PingEvent:
          Type: HttpApi
          Properties:
            ApiId: !Ref api
            Path: /ping
            Method: post
  api:
    Type: AWS::Serverless::HttpApi
    Properties:
      StageName: prod
      DeFinitionBody:
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: swagger.yaml
      AccessLogSettings:
        DestinationArn: !GetAtt accessLogs.Arn
        Format: $context.requestId

还有我的招摇文件

openapi: 3.0.1
info:
  title: 'API'
  version: 2019-10-13

paths:
  /ping:
    post:
      summary: 'invoke ping'
      operationId: 'apiPing'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PingRequest'
        required: true
      responses:
        '200':
          description: 'Successful'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PongResponse'
      x-amazon-apigateway-integration:
        httpMethod: "POST"
        type: aws_proxy
        uri:
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${apiPing.Arn}/invocations
        responses:
          default:
            statusCode: "200"
        contentHandling: "CONVERT_TO_TEXT"
        passthroughBehavior: "when_no_match"
components:
  schemas:
    PingRequest:
      description: 'a ping request'
      type: object
      properties:
        ping:
          description: 'some text'
          type: string
    PongResponse:
      description: 'a pong response'
      type: object
      properties:
        pong:
          description: 'some text'
          type: string

此模板的部署没有任何错误,但是/ping POST路由没有任何集成。

CloudFormation中转换后的模板确实显示了已加载的swagger文件

    "api": {
      "Type": "AWS::ApiGatewayV2::Api","Properties": {
        "Body": {
          "info": {
            "version": 1570924800000,"title": "API"
          },"paths": {
            "/ping": {
              "post": {
                "requestBody": {
                  "content": {
                    "application/json": {
                      "schema": {
                        "$ref": "#/components/schemas/PingRequest"
                      }
                    }
                  },"required": true
                },"x-amazon-apigateway-integration": {
                  "contentHandling": "CONVERT_TO_TEXT","responses": {
                    "default": {
                      "statusCode": "200"
                    }
                  },"uri": {
                    "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${apiPing.Arn}/invocations"
                  },"httpMethod": "POST","passthroughBehavior": "when_no_match","type": "aws_proxy"
                },"summary": "invoke ping","responses": {
                  "200": {
                    "content": {
                      "application/json": {
                        "schema": {
                          "$ref": "#/components/schemas/PongResponse"
                        }
                      }
                    },"description": "Successful"
                  }
                },"operationId": "apiPing"
              }
            }
          },"openapi": "3.0.1","components": {
            "schemas": {
              "PingRequest": {
                "type": "object","description": "a ping request","properties": {
                  "ping": {
                    "type": "string","description": "some text"
                  }
                }
              },"PongResponse": {
                "type": "object","description": "a pong response","properties": {
                  "pong": {
                    "type": "string","description": "some text"
                  }
                }
              }
            }
          },"tags": [
            {
              "name": "httpapi:createdBy","x-amazon-apigateway-tag-value": "SAM"
            }
          ]
        }
      }
    }

我试图了解我可能需要更改或添加什么以将集成添加到http api。在aws文档中找不到任何明确的解释。

解决方法

我设法解决了这个问题。 aws::serverless::httpapi创建一个AWS::ApiGatewayV2::Api资源。这需要与先前版本的ApiGateway不同的集成。

x-amazon-apigateway-integration有一个定义的密钥,payloadFormatVersion。尽管documentation建议同时支持1.0和2.0,但似乎必须使用2.0。因此,我的x-amazon-apigateway-integration已成为以下成员(我做了一些清理工作):

x-amazon-apigateway-integration:
  payloadFormatVersion: "2.0"
  httpMethod: "POST"
  type: "aws_proxy"
  uri:
    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${apiPing.Arn}/invocations
  responses:
    default:
      statusCode: "200"
  connectionType: "INTERNET"

因此,集成将在部署时应用。