Home > database >  REST API (Lambda integration) deployment using Terraform - POST is giving 200, but GET is giving 500
REST API (Lambda integration) deployment using Terraform - POST is giving 200, but GET is giving 500

Time:07-24

I am trying to create a REST API with 2 methods GET and POST. Here is the work I have done:

  1. Using Terraform to deploy AWS services.
  2. Created 2 REST API methods - GET and POST.
  3. Integrated API Gateway to AWS lambda. I created two lambdas, one for each method. The objective is to get "Hello World" as a response. The two lambdas (handlers) are identical in code.

The problem: After the deployment, it worked as expected (200) when I tried to hit POST. However, GET is giving a 500 error. This is what I see on the AWS console.

  • [When I am using type='MOCK' for GET]Execution failed due to configuration error: No match for output mapping and no default output mapping configured. Endpoint Response Status Code: 200
  • [When I am using type = 'AWS_PROXY' for GET] Lambda invocation failed with status: 403. Lambda request id: 5b23639d-f6fb-4130-acf0-15db9a2f76b0
  • Method completed with status: 500

Why is it that POST is working and GET is throwing an error? Any leads to rectifying this error or providing some explanation are appreciated.

Below is my Terraform configuration.

Note: I included only the "aws_api_gateway_*" resources. IAM roles, Lambdas, Lambda permissions are all good.

# 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"
}

CodePudding user response:

According to the documentation:

integration_http_method - (Optional) The integration HTTP method (GET, POST, PUT, DELETE, HEAD, OPTIONs, ANY, PATCH) specifying how API Gateway will interact with the back end. Required if type is AWS, AWS_PROXY, HTTP or HTTP_PROXY. Not all methods are compatible with all AWS integrations. e.g., Lambda function can only be invoked via POST.

In a very simple way, the http_method attribute refers to the HTTP Method of your endpoint, the integration_http_method is the HTTP method of the call that API Gateway will do to invoke the Lambda function.

Just change it to 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
      }
    )
  }
}
  • Related