【问题标题】:How set Proxy on AWS API Gateway using Cloudformation如何使用 Cloudformation 在 AWS API Gateway 上设置代理
【发布时间】:2019-02-03 16:06:14
【问题描述】:

我有一个 lambda 函数,它将使用 Amazon API Gateway {proxy+} 处理 PUT 和 GET 请求。 当所有设置都由 Amazon 控制台手动设置时,它可以正常工作。但我想使用 AWS Cloudformation 将其自动化。

为了通知大家,我会写设置{proxy+}的步骤:

1) 创建一个简单的Lambda function 并将这行代码粘贴到其中:

import boto3

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "headers": {
            "Content-Type": 'text/html',
            "Access-Control-Allow-Origin": "*"
        },
        "body": "Hello Reza Amya, Your Lambda is working..!"
    }

2) 转到Amazon API Gateway 并点击Create API

3) 选择New API,填写API name,从Endpoint Type列表中选择Edge optimized,然后点击Create API

4) 然后你的 API 就创建好了,你应该在它的 Resources 页面上,如果你不是,转到 Resources 页面来查看创建的 API。

5) 从Actions 选择Create Resource

6) 选择Configure as proxy resource(然后它应该自动更改其他字段,如果没有,输入proxyResource Name{proxy+}Resource Path)然后点击Create Resource

7) 为Integration type 选择Lambda Function Proxy 并从Lambda Function 中选择您的lambda 函数并点击Save

8) 在Add Permission to Lambda Function 弹出窗口中,点击Ok

9) 从Actions 点击Deploy API

10) 从Deployment stage 的列表中选择New Stage,然后输入Stage name 的名称(对我来说,我输入了'api')并点击Deploy

11) 在您部署的 API 的根页面上的 stage 上,您可以看到 Invoke URL。点击它,它会打开链接到这样的地方的新标签:https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/api/

12) 在 URL 的末尾添加一个简单的段,如下所示: https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/api/测试

现在您应该在浏览器页面中看到以下消息:

Hello Reza Amya, Your Lambda is working..!

现在的问题是我已经在一个 Yaml 文件中编写了所有这些步骤:

AWSTemplateFormatVersion: 2010-09-09
Description: My Lambda Function
Parameters:
  S3Bucket:
    Description: S3 Bucket where the Lambda code is
    Type: String
  S3Key:
    Description: S3 Key where the Lambda code is
    Type: String
  S3ObjectVersion:
    Description: Version of the S3 Key to use
    Type: String

Resources:
  apiGateway:
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: "my-api"
      Description: "My API"
      EndpointConfiguration:
        Types:
          - EDGE

  Resource: 
    Type: AWS::ApiGateway::Resource
    Properties: 
      RestApiId: 
        Ref: "apiGateway"
      ParentId: 
        Fn::GetAtt: 
          - "apiGateway"
          - "RootResourceId"
      PathPart: "{proxy+}"

  ProxyMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !Ref Resource
      RestApiId: !Ref apiGateway
      AuthorizationType: NONE
      RequestParameters:
        method.request.path.proxy: true
      Integration:
        CacheKeyParameters:
          - 'method.request.path.proxy'
        RequestParameters:
          integration.request.path.proxy: 'method.request.path.proxy'
        Type: AWS_PROXY
        IntegrationHttpMethod: ANY
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Arn}/invocations
          - Arn:
              Fn::GetAtt:
               - LambdaFunction
               - Arn
        PassthroughBehavior: WHEN_NO_MATCH
        IntegrationResponses:
          - StatusCode: 200 

  apiGatewayDeployment:
    Type: "AWS::ApiGateway::Deployment"
    DependsOn:
      - "ProxyMethod"
    Properties:
      RestApiId: !Ref "apiGateway"
      StageName: "dev"

  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'

      Policies:
        - PolicyName: Logging
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'
        - PolicyName: AccessToDynamoDB
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:CreateTable'
                  - 'dynamodb:DeleteItem'
                  - 'dynamodb:DeleteTable'
                  - 'dynamodb:GetItem'
                  - 'dynamodb:GetRecords'
                  - 'dynamodb:UpdateItem'
                  - 'dynamodb:UpdateTable'
                  - 'dynamodb:PutItem'
                  - 'dynamodb:UpdateTable'
                Resource: 'arn:aws:dynamodb:*:*:*'

  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: {Ref: S3Bucket}
        S3Key: {Ref: S3Key}
        S3ObjectVersion: {Ref: S3ObjectVersion}
      Handler: main.lambda_handler
      MemorySize: 128
      Role: {'Fn::GetAtt': [IAMRole, Arn]}
      Runtime: python3.6
      Timeout: 300

  LambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !GetAtt 
        - LambdaFunction
        - Arn
      Action: 'lambda:InvokeFunction'
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*/*

Outputs:
  apiGatewayInvokeURL:
    Value: !Sub "https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGateway}"

  lambdaArn:
    Value: !GetAtt "LambdaFunction.Arn"

上面的 Yaml 文件将创建 Lambda 函数并部署 API,但是当我尝试测试 API 时它会显示以下错误:

{"message": "Internal server error"}

您能否指导我出了什么问题以及如何解决问题?

【问题讨论】:

    标签: amazon-web-services aws-lambda yaml aws-api-gateway amazon-cloudformation


    【解决方案1】:

    该问题与您的IntegrationHttpMethod 设置有关。尽管您的 APIGateway 方法是 ANY,但对于 AWS Lambda,IntegrationHttpMethod 必须始终为 POST

    这将导致以下方法声明。

      ProxyMethod:
        Type: 'AWS::ApiGateway::Method'
        Properties:
          HttpMethod: ANY
          ResourceId: !Ref Resource
          RestApiId: !Ref apiGateway
          AuthorizationType: NONE
          RequestParameters:
            method.request.path.proxy: true
          Integration:
            CacheKeyParameters:
              - 'method.request.path.proxy'
            RequestParameters:
              integration.request.path.proxy: 'method.request.path.proxy'
            Type: AWS_PROXY
            IntegrationHttpMethod: POST
            Uri: !Sub
              - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Arn}/invocations
              - Arn:
                  Fn::GetAtt:
                   - LambdaFunction
                   - Arn
            PassthroughBehavior: WHEN_NO_MATCH
            IntegrationResponses:
              - StatusCode: 200 
    

    【讨论】:

    • 非常感谢,它正在工作。我花了大约 2 天的时间来处理它!
    猜你喜欢
    • 2018-01-27
    • 2018-05-25
    • 1970-01-01
    • 2021-08-14
    • 2020-01-06
    • 2019-12-30
    • 1970-01-01
    • 2018-07-22
    • 2021-09-13
    相关资源
    最近更新 更多