Reputation: 139
I have deployed serverless function with an API integreated. Below is the code
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
import json
def customer(event, context):
postData= event['body']
return {
'statusCode': 200,
'body': "Hello Post accepted",
"content-type": "application/json"
}
{
"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" }
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
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
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