Need your help! I have the below Lambda function that will take inputs from the API Gateway (using RestAPI Post method) and pass the same as Payload to a second Lambda function.
def lambda_handler(event, context):
customerName = event['Name']
customerEmail = event['EmailAddress']
input = {"Name": customerName, "EmailAddress": customerEmail}
response = lambda_client.invoke(
FunctionName='arn_of_the_lambda_to_be_invoked',
InvocationType='Event',
Payload=json.dumps(input))
Below will be my input to the API Gateway in JSON format -
{
"Name": "TestUser",
"EmailAddress": "test#abc.com"
}
Have tried Lambda proxy integration and Generic Body Mapping templates (from here). In both occasions, API Gateway returns the below error -
Response Body:
{
"errorMessage": "'Name'",
"errorType": "KeyError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n customerName = event['Name']\n"
]
}
With the same JSON input when I directly invoke the Lambda from the Lambda console, it works. I know that API Gateway, along with the JSON body, pushes many other things. However, I'm unable to figure out.
How do I get this working?
In the lambda proxy integration, the event will be in the following format.
{
"resource": "Resource path",
"path": "Path parameter",
"httpMethod": "Incoming request's method name"
"headers": {String containing incoming request headers}
"multiValueHeaders": {List of strings containing incoming request headers}
"queryStringParameters": {query string parameters }
"multiValueQueryStringParameters": {List of query string parameters}
"pathParameters": {path parameters}
"stageVariables": {Applicable stage variables}
"requestContext": {Request context, including authorizer-returned key-value pairs}
"body": "A JSON string of the request payload."
"isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}
the values you posted will be inside body as a json string. you need to parse the json.
import json
def lambda_handler(event, context):
fullBody = json.loads(event['body'])
print('fullBody: ', fullBody)
body = fullBody['body']
customerName = body['Name']
customerEmail = body['EmailAddress']
input = {"Name": customerName, "EmailAddress": customerEmail}
response = lambda_client.invoke(
FunctionName='arn_of_the_lambda_to_be_invoked',
InvocationType='Event',
Payload=json.dumps(input))
Input format of a Lambda function for proxy integration
Please remember that the lambda is expected to return the output in the following format for Lambda Proxy integration.
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}
Related
I am trying to create a connect instance with a lambda function. This lambda function needs to go into DynamDB and return the value associated with the primary key as a key value pair. The function is using python to program in.
What happens is that testing the function is passing, I am able to get a successful result through the test option with the function. However when I add the lambda function to my contact flow it is failing to even run the function successfully, and it is throwing the error "error". I think this is due to the result of it needing a key value repair.
Below is the code for the Lambda funcion:
import json
import boto3
client = boto3.client('dynamodb')
def lambda_handler(event, context):
data = client.get_item(
TableName='MessageFlat',
Key={'Message': {'S': "1"}
}
)
response = {
'statusCode': 200,
'body': json.dumps(data),
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
}
return response
This is the response given by the lambda function.
Response
{
"statusCode": 200,
"body": "{\"Item\": {\"Message\": {\"S\": \"1\"}, \"Hello\": {\"S\": \"Good Day. Welcome to Shelby's contact centre. \"}}, \"ResponseMetadata\": {\"RequestId\": \"S1CRNMSO7KM15TE5I70HJ2AL0FVV4KQNSO5AEMVJF66Q9ASUAAJG\", \"HTTPStatusCode\": 200, \"HTTPHeaders\": {\"server\": \"Server\", \"date\": \"Thu, 25 Aug 2022 22:54:10 GMT\", \"content-type\": \"application/x-amz-json-1.0\", \"content-length\": \"93\", \"connection\": \"keep-alive\", \"x-amzn-requestid\": \"S1CRNMSO7KM15TE5I70HJ2AL0FVV4KQNSO5AEMVJF66Q9ASUAAJG\", \"x-amz-crc32\": \"996959635\"}, \"RetryAttempts\": 0}}",
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
}
This is the needed output from the lambda function
{
"Message": "1",
"Hello": "Good Day. Welcome to Shelby's contact centre."
}
This is what my table is made up of.
If you simply want a subset of attributes of the DynamoDB item, then try this:
response = {
"Message": data["Item"]["Message"]["S"],
"Hello": data["Item"]["Hello"]["S"]
}
return response
'''
Trying to get response back as name of the intent from lambda for Amazon Lex v2. It can be string or any response back in simple program.
I have referred the V2 Lex documentation but I can come-up with below code which shows error after several attempts. https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html
error : "Invalid Lambda Response: Received error response from Lambda: Unhandled"
'''
def lambda_handler(event, context):
entity = event["currentIntent"]["slots"]["Nm"].title()
intent = event["currentIntent"]["name"]
response = {
'sessionState': {
'dialogAction': {
'type': 'Close'
},
'state': 'Fulfilled'
},
'messages': [
'contentType': 'PlainText',
'content': "The intent you are in now is "+intent+"!"
],
}
return response
The 'messages' field is an array of objects, not an array of strings. It should be declared as follows:
'messages': [
{
'contentType': 'PlainText',
'content': "The intent you are in now is "+intent+"!"
}
]
Reference:
Amazon Lex - Lambda Response format
I faced the same issue. The solution that worked for me is like below
var response = {};
response.messages = [
message
];
response.sessionState = {
sessionAttributes:sessionAttributes,
intent : {
name : intentRequest.interpretations[0].intent.name,
state : 'Fulfilled'
},
dialogAction: {
type: "Close",
fulfillmentState: "Fulfilled"
}
};
Refer to lex v2 developer guide page 69 Response format
https://docs.aws.amazon.com/lexv2/latest/dg/lex2.0.pdf
I have created an API with AWS Lambda in Python. Unfortunately, the response contains the headers, and I would like it to only contain the body. The Lambda API looks like this:
import json
import boto3
def lambda_handler(event, context):
#Step1: Scan table
client = boto3.resource('dynamodb') #Access DynamoDB
table = client.Table("register-to-event") #Access table
response = table.scan()
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json",
},
"body": response["Items"]
}
The problem is that the API response contains headers and body when I call it. This is the response:
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"your-email": "hannes.hannesen#googlemail.com",
"your-number": "004785454548",
"your-last-name": "Hannesen",
"your-first-name": "Hannes",
"ID": 3
},
{
"your-email": "stig.stigesen#googlemail.com",
"your-number": "+4754875456",
"your-last-name": "Stigesen",
"your-first-name": "Stig",
"ID": 0
}
]
}
The goal is to call the API and return only the body which is json like this:
[
{
"your-email": "hannes.hannesen#googlemail.com",
"your-number": "004785454548",
"your-last-name": "Hannesen",
"your-first-name": "Hannes",
"ID": 3
},
{
"your-email": "stig.stigesen#googlemail.com",
"your-number": "+4754875456",
"your-last-name": "Stigesen",
"your-first-name": "Stig",
"ID": 0
}
]
The Solution was to configure the API in AWS correctly by ticking the box next to "Use Lambda Proxy integration":
Use Lambda Proxy integration
My next problem ended up being "serializing decimals" as a result of DynamoDB making the keys of the table a type (Decimal) which does not exist in Python.
The solution to this can be found here: https://learn-to-code.workshop.aws/persisting_data/dynamodb/step-3.html
I am using Amazon API Gateway to invoke a lambda function. I am testing a get request with the following as my query string earlyDate="12-01-21"&laterDate="12-03-21".
I currently have my lambda function returning the event that gets passed:
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps(event)
}
This works as expected. When I test my API gateway I get a response which includes
"queryStringParameters": {
"earlyDate": "12-01-21",
"laterDate": "12-03-21"
},
"multiValueQueryStringParameters": {
"earlyDate": [
"12-01-21"
],
"laterDate": [
"12-03-21"
]
},
This indicates I should be able to access these query parameters at event.queryStringParameters. However when I change my lambda function to return those:
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps(event.queryStringParameters)
}
The result is a 502 error.
How do I access the query string parameters passed in from my API Gateway?
I think, event is a dict and we can access its query params as event['queryStringParameters']
We can confirm that by
for key, value in event.items():
print(key, value)
Lambda could return this:
return {
'statusCode': 200,
'body': json.dumps(event['queryStringParameters'])
}
I'm building an mapping app using cordova and making a post request sending the following JSON (feature)
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-6.6865857,
53.2906136
]
},
"properties": {
"amenity": "pub",
"name": "The Parade Ring"
}
}
This is the JQuery code sending the request
function savePub(feature){
$.ajax({
type: "POST",
headers: {"csrfmiddlewaretoken": csrftoken},
url: HOST + URLS["savePub"],
data: {
pub_feature: JSON.stringify(feature)
},
contentType:"application/json; charset=utf-8"
}).done(function (data, status, xhr) {
console.log(data + " " + status);
pubDialogAlert("Pub saved",feature);
}).fail(function (xhr, status, error) {
showOkAlert(error);
console.log(status + " " + error);
console.log(xhr);
}).always(function () {
$.mobile.navigate("#map-page");
});
}
When the request is received in the Django backend I am not sure why when I print the request body it looks like this,
b'pub_feature=%22%7B%5C%22type%5C%22%3A%5C%22Feature%5C%22%2C%5C%22geometry%5C%22%3A%7B%5C%22type%5C%22%3A%5C%22Point%5C%22%2C%5C%22coordinates%5C%22%3A%5B-6.6865857%2C53.2906136%5D%7D%2C%5C%22properties%5C%22%3A%7B%5C%22amenity%5C%22%3A%5C%22pub%5C%22%2C%5C%22name%5C%22%3A%5C%22The+Parade+Ring%5C%22%7D%7D%22'
and when I try to decode it and then use json.loads() it throws this error
#api_view(['POST'])
def save_pub(request):
if request.method == "POST":
data = request.body.decode('utf-8')
received_json_data = json.loads(data)
return Response(str(received_json_data) + " written to db", status=status.HTTP_200_OK)
JSONDecodeError at /savepub/
Expecting value: line 1 column 1 (char 0)
I am assuming because once it decodes the binary string it can't be converted to valid JSON because of those characters %22 etc, but I don't know what the solution is.
Any help would be appreciated.
Thanks
You're mixing up two things here, form-encoded and JSON format. What you have is a form-encoded post with one key, pub_feature, whose value is a JSON object.
Instead you should post the JSON directly:
data: JSON.stringify(feature),
and then you should be able to load it as you do already - although note that really you should let DRF deal with that for you