【问题标题】:REST API (Lambda integration) deployment using Terraform - POST is giving 200, but GET is giving 500使用 Terraform 的 REST API(Lambda 集成)部署 - POST 给出 200,但 GET 给出 500
【发布时间】:2022-07-22 18:32:47
【问题描述】:

我正在尝试使用 2 种方法 GET 和 POST 创建一个 REST API。这是我所做的工作:

  1. 使用 Terraform 部署 AWS 服务。
  2. 创建了 2 个 REST API 方法 - GET 和 POST。
  3. 将 API 网关集成到 AWS lambda。我创建了两个 lambda,每个方法一个。目标是获得“Hello World”作为响应。这两个 lambda(处理程序)在代码中是相同的。

    问题:部署后,当我尝试点击 POST 时,它按预期工作(200)。但是,GET 给出了 500 错误。这是我在 AWS 控制台上看到的。

    • [当我使用 type=\'MOCK\' 获取 GET 时]由于配置错误,执行失败:输出映射不匹配,也没有配置默认输出映射。端点响应状态码:200
    • [当我对 GET 使用 type = \'AWS_PROXY\' 时] Lambda 调用失败,状态为:403。Lambda 请求 ID:5b23639d-f6fb-4130-acf0-15db9a2f76b0
    • 方法完成,状态:500

    为什么 POST 正常工作而 GET 抛出错误?任何导致纠正此错误或提供一些解释的线索表示赞赏。

    下面是我的 Terraform 配置。

    注意:我只包括了“aws_api_gateway_*”资源。 IAM 角色、Lambda、Lambda 权限都很好。

    # Lambda handler - This is the same for both GET and POST. I used the same in both lambdas integrated to GET and POST.
    
    import json
    
    def lambda_handler(event, context):
        return {
            \"statusCode\": 200,
            \"headers\": {
                \"Content-Type\": \"application/json\"
            },
            \"body\": json.dumps(\"Hello World\")
        }
    
    ################################################################################
    # REST API and Resource
    ################################################################################
    resource \"aws_api_gateway_rest_api\" \"hello_world_v1\" {
      name = \"hello_world_v1\"
    }
    
    resource \"aws_api_gateway_resource\" \"hello_world_v1\" {
      parent_id   = aws_api_gateway_rest_api.hello_world_v1.root_resource_id
      rest_api_id = aws_api_gateway_rest_api.hello_world_v1.id
      path_part = \"test\"
    }
    
    ################################################################################
    # GET - method and integration
    ################################################################################
    resource \"aws_api_gateway_method\" \"hello_world_v1_get\" {
      rest_api_id   = aws_api_gateway_rest_api.hello_world_v1.id
      resource_id   = aws_api_gateway_resource.hello_world_v1.id
      http_method   = \"GET\"
      authorization = \"NONE\"
    
    }
    resource \"aws_api_gateway_integration\" \"hello_world_v1_get\" {
      rest_api_id = aws_api_gateway_rest_api.hello_world_v1.id
      resource_id = aws_api_gateway_method.hello_world_v1_get.resource_id
      http_method = aws_api_gateway_method.hello_world_v1_get.http_method
      integration_http_method = \"GET\"
      type = \"AWS_PROXY\"
      uri = aws_lambda_function.lambda_hello_world_v1_get.invoke_arn
    # I initially didn\'t use this request template.
    # I tried this after reading it somewhere while I was attempting to search for a solution. 
    # However,using or not using, didn\'t work out.
      request_templates = {
        \"application/json\" = jsonencode(
          {
            statusCode = 200
          }
        )
      }
    }
    
    ################################################################################
    # POST - method and integration
    ################################################################################
    resource \"aws_api_gateway_method\" \"hello_world_v1_post\" {
      rest_api_id   = aws_api_gateway_rest_api.hello_world_v1.id
      resource_id   = aws_api_gateway_resource.hello_world_v1.id
      http_method   = \"POST\"
      authorization = \"NONE\"
    }
    resource \"aws_api_gateway_integration\" \"hello_world_v1_post\" {
      rest_api_id = aws_api_gateway_rest_api.hello_world_v1.id
      resource_id = aws_api_gateway_method.hello_world_v1_post.resource_id
      http_method = aws_api_gateway_method.hello_world_v1_post.http_method
      integration_http_method = \"POST\"
      type = \"AWS_PROXY\"
      uri = aws_lambda_function.lambda_hello_world_v1_post.invoke_arn
    }
    
    ################################################################################
    # Stage and Deployment
    ################################################################################
    resource \"aws_api_gateway_deployment\" \"hello_world_v1\" {
      rest_api_id = aws_api_gateway_rest_api.hello_world_v1.id
      depends_on = [
        aws_api_gateway_method.hello_world_v1_get,
        aws_api_gateway_method.hello_world_v1_post
      ]
    }
    
    resource \"aws_api_gateway_stage\" \"hello_world_v1\" {
      deployment_id = aws_api_gateway_deployment.hello_world_v1.id
      rest_api_id   = aws_api_gateway_rest_api.hello_world_v1.id
      stage_name    = \"development\"
    }
    
  • 为什么 GET type = \"MOCK\"request_template
  • 你好,我编辑了。它是“AWS_PROXY”。我正在尝试如果它的“MOCK”忘记改变它会发生什么。行为是相同的。至于请求模板,我在另一篇 StackOverflow 帖子上读到,对于 GET,它是必需的(不确定原因)。然而,这也没有奏效。

标签: api rest aws-lambda aws-api-gateway terraform-provider-aws


【解决方案1】:

根据documentation

integration_http_method -(可选)集成 HTTP 方法(GET, POST、PUT、DELETE、HEAD、OPTIONs、ANY、PATCH) 指定 API 如何 网关将与后端交互。如果类型是 AWS,则为必需, AWS_PROXY、HTTP 或 HTTP_PROXY。并非所有方法都兼容 AWS 集成。例如,Lambda 函数只能通过 POST 调用。

以一种非常简单的方式,http_method 属性是指您的端点的 HTTP 方法,integration_http_method 是 API 网关将调用 Lambda 函数的调用的 HTTP 方法。

只需将其更改为 POST:

resource "aws_api_gateway_integration" "hello_world_v1_get" {
  rest_api_id = aws_api_gateway_rest_api.hello_world_v1.id
  resource_id = aws_api_gateway_method.hello_world_v1_get.resource_id
  http_method = aws_api_gateway_method.hello_world_v1_get.http_method
  integration_http_method = "POST"
  type = "AWS_PROXY"
  uri = aws_lambda_function.lambda_hello_world_v1_get.invoke_arn
# I initially didn't use this request template.
# I tried this after reading it somewhere while I was attempting to search for a solution. 
# However,using or not using, didn't work out.
  request_templates = {
    "application/json" = jsonencode(
      {
        statusCode = 200
      }
    )
  }
}

【讨论】:

  • 工作。谢谢你的解释!接受了答案。
猜你喜欢
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2022-12-25
  • 1970-01-01
相关资源
最近更新 更多