hanju
hanju

Reputation: 139

Getting 500 response while invoking API with post request

I have deployed serverless function with an API integreated. Below is the code

Serverless.yml

service: serverless-rest-api-with-dynamodb

provider:
  name: aws
  runtime: python3.8
  region: eu-west-1
  environment:
    DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
  logs:  true
functions:
  myFunc:
    handler: handler.customer
    events:
      - http:
          path: customer_details
          method: post

resources:
  Resources:
    TodosDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        TableName: CustomerTablev1
        AttributeDefinitions:

          - AttributeName: id
            AttributeType: S
          - AttributeName: CustomerName
            AttributeType: S
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
          - AttributeName: CustomerName
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

handler.py

import json


def customer(event, context):
    postData= event['body']
    return {

        'statusCode': 200,
        'body': "Hello Post accepted",
        "content-type": "application/json"
    }

Below is the permission i have added for the api to invoke the lambda function

{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":
    [{\"Sid\":\"serverless-rest-api-with-dynamodb-dev-MyFuncLambdaPermissionApiGateway-dfdd22\",
    \"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},
    \"Action\":\"lambda:InvokeFunction\",
    \"Resource\":\"arn:aws:lambda:eu-west-1:##3d64543:function:serverless-rest-api-with-dynamodb-dev-myFunc\",
    \"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:eu-west-1:##343d64543:tmx8paevk3/*/*\"}}},
    {\"Sid\":\"###23232dfecfb\",
    \"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},
    \"Action\":\"lambda:InvokeFunction\",
    \"Resource\":\"arn:aws:lambda:eu-west-1:##3d64543:function:serverless-rest-api-with-dynamodb-dev-myFunc\",
    \"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:eu-west-1:##3d64543:tmx8paevk3/*/POST/customer_details\"}}},
    {\"Sid\":\"apigateway\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},
    \"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:eu-west-1:##3d64543:function:serverless-rest-api-with-dynamodb-dev-myFunc\"}]}",
    "RevisionId": "##3d64543ddf-4ecdfe"
}

I called api with the body request, for eg: { "Name":"123" }

Below is the log

 Verifying Usage Plan for request: 33434-df-sdf##. API Key:  API Stage: tmx8paevk3/dev
API Key  authorized because method 'POST /customer_details' does not require API Key. Request will not contribute to throttle or quota limits
 Usage Plan check succeeded for API Key  and API Stage tmx8paevk3/dev
 Starting execution for request: 343-f-er-###
 HTTP Method: POST, Resource Path: /customer_details
 Method request path: 
{}
(c3434-ffg34--sd2qw) Method request query string: 
{}
 Method request headers: {Accept=application/json, CloudFront-Viewer-Country=IN, CloudFront-Forwarded-Proto=https, CloudFront-Is-Tablet-Viewer=false, CloudFront-Is-Mobile-Viewer=false, User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36, X-Forwarded-Proto=https, CloudFront-Is-SmartTV-Viewer=false, Host=tmx8paevk3.execute-api.eu-west-1.amazonaws.com, Accept-Encoding=gzip, deflate, X-Forwarded-Port=443, X-Amzn-Trace-Id=Root=1-5e08179b-231fd1c4058eaaa020eff0d0, Via=1.1 da86ace2d9b441802dcc77e25582499b.cloudfront.net (CloudFront), X-Amz-Cf-Id=oXgrxNvE97x-3FvOB7_85BawEcIIGe5Puzy6S9XIiKSDj8yLZQv-Ig==, X-Forwarded-For=117.204.125.144, 52.46.37.72, content-type=application/json, Accept-Language=en-US,en;q=0.8, CloudFront-Is-Desktop-Viewer=true}
 Method request body before transformations: 
{
    "name": "test"
}
Endpoint request URI: https://lambda.eu-west-1.amazonaws.com/2013-233-32/functions/arn:aws:lambda:eu-west-1:3d##:function:serverless-rest-api-with-dynamodb-dev-myFunc/invocations
Endpoint request headers: {x-amzn-lambda-integration-tag=##sdsd-sd23, Authorization=************************************************************************************************************************************************************************************************************************************************************************************************************************d9c3f1, X-Amz-Date=20191229T030355Z, x-amzn-apigateway-api-id=tmx8paevk3, X-Amz-Source-Arn=arn:aws:execute-api:eu-west-1:7###343434:tmx8paevk3/dev/POST/customer_details, Accept=application/json, User-Agent=AmazonAPIGateway_tm##we, X-Amz-Security-Token=I###12323/D######/xfP2323######//////////8B#######/334####/dsd## [TRUNCATED]
Endpoint request body after transformations: 
{
    "name": "test"
}
Sending request to https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-west-1:####:function:serverless-rest-api-with-dynamodb-dev-myFunc/invocations
Received response. Status: 200, Integration latency: 263 ms
Endpoint response headers: {Date=Sun, 29 Dec 2019 03:03:56 GMT, Content-Type=application/json, Content-Length=86, Connection=keep-alive, x-amzn-RequestId=3443D-23#, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=23d=-dere###;sampled=0}
Endpoint response body before transformations: 
{
    "statusCode": 200,
    "body": "Hello Post accepted",
    "content-type": "application/json"
}
Execution failed due to configuration error: Output mapping refers to an invalid method response: 200
Method completed with status: 500
AWS Integration Endpoint RequestId : 323d-fer-vsd###

But still it returns 500 internal error. I searched different ways to get the solution, and everybody says its only due to the lack of permission that API must have to invoke the lambda. As i already provided the permission to the API, i want to know what exactly, what would be the solution for this? Appreciate if anyone can help on this?

Upvotes: 2

Views: 2519

Answers (2)

aksyuma
aksyuma

Reputation: 3180

I have reviewed and tested your Serverless Framework code and after slight modification I was able to get the setup working by making the following changes :

handler.py

    import json

    def hello(event, context):

        postData = event['body']

    # Prepare a response dictionary as required by API Gateway
        response = {
            "statusCode": 200,
            "isBase64Encoded": False,
            "headers": {},
            "content-type": "application/json",
            "body": json.dumps(postData)
        }

        return response 

Serverless.yml

service: HelloWorld
provider:
    name: aws
    runtime: python2.7
    region: eu-west-1

    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:Query
          - dynamodb:Scan
          - dynamodb:GetItem
          - dynamodb:PutItem
          - dynamodb:UpdateItem
          - dynamodb:DeleteItem
        Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
    logs:  true

    environment:
        DYNAMODB_TABLE: '${self:service}-${opt:stage, self:provider.stage}'

functions:
    hello:
        handler: handler.hello
        events:
          - http:       
              path: customers-details
              method: POST
              integration: LAMBDA # Add this line

resources:
  Resources:
    TodosDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        TableName: CustomerTablev1
        AttributeDefinitions:

          - AttributeName: id
            AttributeType: S
          - AttributeName: CustomerName
            AttributeType: S
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
          - AttributeName: CustomerName
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

Curl Test

Request:

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"name":"syumaK"}' --url https://z0uu17yp6f.execute-api.eu-west-1.amazonaws.com/dev/customers-details

Response:

{"body": "{\"name\": \"syumaK\"}", "headers": {}, "content-type": "application/json", "isBase64Encoded": false, "statusCode": 200}%     

The takeaway point is that when working with Serverless Framework and AWS Lambda(Lambda proxy) you have to add to the following line in your serverless.yml under events:

          integration: LAMBDA

Hope this helps!

Upvotes: 1

Dhaval Chaudhary
Dhaval Chaudhary

Reputation: 5815

You response body is the problem here:

{
    'statusCode': 200,
    'body': "Hello Post accepted",
    "content-type": "application/json"
}

It should be something be(as you are setting header as json and passing normal text):

{
    'statusCode': 200,
    'body': json.dumps({"reply":"Hello Post accepted"}),
    "content-type": "application/json"
}

Upvotes: 0

Related Questions