What comes with the AWS Lambda event and context - ruby

I've got AWS Lambda written in Ruby 2.7 and the Lambda is setup based on templates.yml. Since I'm not able to use debugger on AWS Lambda which is run locally (AWS SAM gives me an error: Ruby 2.7 is not supported at the moment - docs) I also can't check what's coming inside Event and Context.
My lambda uses the Gateway API, and I'm wondering what I should do to pull the entire payload (I assume it's in the body of the request) from the request that comes in at POST /quizzes, which looks like the following:
{
"quiz":
{
"first_name": "john",
"last_name": "doe",
"ssn": "1234",
"address":
{
"line1": "4444 NW ANYSTREET AVE",
"city": "anytown",
"state": "FL",
"zip_code": "33333"
},
"dob":
{
"day": 25,
"month": 12,
"year": 2000
}
}
}
From the entire Lambda Event I want to fetch and pass only the body that is attached to the request. In other words, what does the event look like with this type of request body?

If you want to know what an event in lambda looks like, you can use AWS SAM to generate the body of a fake event using the sam local generate-event command.

Related

how can I compose a bot to iterate trough a xml json object?

I am using the composer to publish a bot to fetch data from an azure storage table.
In short, the bot composer needs to construct a bot to iterate through an XML deserialized JSON object returned by the azure storage rest API.
In my code generated by the composer, the bot does a "set property" step immediately following the successful return of the REST API (storage table query). Given the deserialized object returned by the storage REST API, how should the "set property" statement be constructed so the bot can print our the individual data field,
Another way to phrase the question: how can I use the composer to construct the bot to iterate through a returned deserialized object (coded in XML JSON format)?
Where can I find a document that can shed some light on this matter?
Is there any place I can find a good example? Can it be done via composer?
Thanks in advance.
Yes, it can be done. If the API returns XML, make sure you configure your api call to ask for content type application/xml.
Then you can use use the xPath built in function. Make note that it will return an array if results in more than value matches the expression, in which you can use the foreach function to iterate over it with. I needed to run the nightly build of Composer (with bot-builder 4.12.0) to get it to work for me. See here for some more info:
https://github.com/microsoft/botbuilder-js/pull/3093
Here's an example that worked for me:
"actions": [
{
"$kind": "Microsoft.SendActivity",
"$designer": {
"id": "rGv7XC"
},
"activity": "${SendActivity_rGv7XC()}"
},
{
"$kind": "Microsoft.HttpRequest",
"$designer": {
"id": "TDA1wO"
},
"method": "GET",
"url": "http://www.geoplugin.net/xml.gp?ip=157.54.54.128",
"resultProperty": "dialog.api_response",
"contentType": "application/xml"
},
{
"$kind": "Microsoft.SetProperty",
"$designer": {
"id": "ipNhfY"
},
"property": "dialog.timezone",
"value": "=xPath(dialog.api_response.content,'/geoPlugin/geoplugin_timezone/text()')"
},
{
"$kind": "Microsoft.SendActivity",
"$designer": {
"id": "DxohEx"
},
"activity": "${SendActivity_DxohEx()}"
}
]
You can (if needed/you wish) use the json and jPath built in functions to convert xml to json and then query with. Something like:
${json(user.testXml)} and then
${jPath(user.testJson , "automobiles")}

CORS error with AWS api gateway and java lambda function

Today I created one api gateway on aws and one java lambda function. Then finally integrated api gateway with lambda function.
So when I hit the api using postman then it returns the result which is basically a list of customer. Till now everything looks fine. Following is the
#Override
public TestResponse handleRequest(Request input, Context context) {
TestService testService = SingletonServiceManager.getInstance().getTestService();
TestListResponse response = (TestListResponse)productListService.executeRequest(input);
return response;
}
After executing it returns following output.
{
"status": 200,
"products": [
{
"name": "test1",
"code": "test1",
"status": true
},
{
"name": "test2",
"code": "test2",
"status": true
}
]
}
but when I started integrating this with api call with Angular from local machine it start throwing CORS issue. Angular client using it CORS setting to connect.
Can someone help me on this. Do I need to enable something special from lambda function.
You need to enable CORS in your API Gateway configuration.

How do I post a test Kinesis event from Postman to a local Lambda function running on serverless?

Sorry, wasn't sure how to make the question itself brief enough...
I can post data from Postman to my local Lambda function. The issue is that when running locally, I have use this line of code...
event = JSON.parse(event.body);
...so that I can do this...
event.Records.forEach(function(record)
{
// do some stuff
}
But when I deploy the function to AWS, parsing event.body is unnecessary. In fact it throws an error.
I was assuming that there is something different about the JSON (or other aspects of the request) that I'm posting from Postman to my local app when compared to what Kinesis actually sends. But the JSON blob I'm posting locally was logged directly from Lambda on AWS to Cloudwatch.
I'm missing something.
TBH, this only matters because having to comment out that line as a step in the deployment process is annoying and error-prone.
Here's the JSON (names have been changed to protect the innocent):
{
"Records": [
{
"kinesis": {
"kinesisSchemaVersion": "1.0",
"partitionKey": "Thursday, 11 April 2019",
"sequenceNumber": "49594660145138471912435706107712688932829223550684495922",
"data": "some base 64 stuff",
"approximateArrivalTimestamp": 1555045874.83
},
"eventSource": "aws:kinesis",
"eventVersion": "1.0",
"eventID": "shardId-000000000003:1234123412341234123412341234123412341234123412341234",
"eventName": "aws:kinesis:record",
"invokeIdentityArn": "arn:aws:iam::1234123412341234:role/lambda-kinesis-role",
"awsRegion": "us-west-2",
"eventSourceARN": "arn:aws:kinesis:us-west-2:1234123412341234:stream/front-end-requests"
}
]
}

Bot framework direct line using POST with JSON data

I now use bot framework with Azure functions.
it now works when the user sends his message its writes it to queue storage then picked up by Azure function and sends it back to the bot with direct line build in Azure function connector.
I want to change the functionality to LogicAppp and return the answer to the user with direct-line with http rest.
I have a key and have a json input that the function got like this:
{
"relatesTo": {
"user": {
"id": "default-user",
"name": "User"
},
"bot": {
"id": "b5023440-b1ce-11e8-9ad8-f5b615a4c6c3",
"name": "Bot"
},
"conversation": {
"id": "33cd0410-bf46-11e8-a228-a5c7cd21a798|livechat"
},
"channelId": "emulator",
"serviceUrl": "https://0a87dff1.ngrok.io"
},
"text": "example",
"isTrustedServiceUrl": true
}
I try to answer the chat using
https://directline.botframework.com/v3/directline/conversations/{conversationId}/activitie
I can't make it work, the conversation id looks different, it's like a guid instead of an id.
how can help me with the right POST syntax from the json provided?

Can I get information about AWS Lambda request IDs, e.g. the trigger?

In my logs I find
START RequestId: 123a1a12-1234-1234-1234-123456789012 Version: $LATEST
for every invocation of AWS lambda. Is it possible to get more information about a request, e.g. what triggered it?
You can get the request id and other information from the context object.
When Lambda runs your function, it passes a context object to the handler. This object provides methods and properties that provide information about the invocation, function, and execution environment.
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html
You can get further information from the process.env variable.
I wrote a short lambda function (node.js) which logs these information to the console and ends up in aws cloud watch
exports.handler = async (event, context) => {
console.log('context:', JSON.stringify(context));
console.log('process.env:', JSON.stringify(process.env));
return {statusCode: 200, body: 'Hello World'};
};
Log output:
START RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e Version: $LATEST
context:
{
"callbackWaitsForEmptyEventLoop": true,
"functionVersion": "$LATEST",
"functionName": "my_lambda_function_name",
"memoryLimitInMB": "128",
"logGroupName": "/aws/lambda/my_lambda_function_name",
"logStreamName": "2020/10/01/[$LATEST]8adb13668eed4ac8b3e7f8d796fe4d49",
"invokedFunctionArn": "arn:aws:lambda:us-east-1:636121343751:function:my_lambda_function_name",
"awsRequestId": "6f3c103e-f0a5-4982-934c-dabedda0065e"
}
process.env:
{
"AWS_LAMBDA_FUNCTION_VERSION": "$LATEST",
"AWS_SESSION_TOKEN": "IZZ3eS6vFF...",
"LD_LIBRARY_PATH": "/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib",
"LAMBDA_TASK_ROOT": "/var/task",
"AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/my_lambda_function_name",
"AWS_LAMBDA_RUNTIME_API": "127.0.0.1:9001",
"AWS_LAMBDA_LOG_STREAM_NAME": "2020/10/01/[$LATEST]8adb13668eed4ac8b3e7f8d796fe4d49",
"AWS_EXECUTION_ENV": "AWS_Lambda_nodejs12.x",
"AWS_LAMBDA_FUNCTION_NAME": "my_lambda_function_name",
"AWS_XRAY_DAEMON_ADDRESS": "169.254.79.2:2000",
"PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin",
"AWS_DEFAULT_REGION": "us-east-1",
"PWD": "/var/task",
"AWS_SECRET_ACCESS_KEY": "5nQrpKhBwF...",
"LAMBDA_RUNTIME_DIR": "/var/runtime",
"LANG": "en_US.UTF-8",
"NODE_PATH": "/opt/nodejs/node12/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task",
"AWS_REGION": "us-east-1",
"TZ": ":UTC",
"AWS_ACCESS_KEY_ID": "ASIAZNANWY3473BTADSB",
"SHLVL": "0",
"_AWS_XRAY_DAEMON_ADDRESS": "169.254.79.2",
"_AWS_XRAY_DAEMON_PORT": "2000",
"AWS_XRAY_CONTEXT_MISSING": "LOG_ERROR",
"_HANDLER": "index.handler",
"AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128",
"_X_AMZN_TRACE_ID": "Root=1-6f75f4e5-5801599f17fd63e74ecd0833;Parent=73fb93812cdbf83f;Sampled=0"
}
END RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e
REPORT RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e
Duration: 21.71 ms Billed Duration: 100 ms
Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 132.35 ms
Not sure I understand what you mean by what triggered it? If it's connected to the API Gateway, then requests are proxied through the Gateway to your Lambda. In that case the Gateway triggered it, even though it was a proxied request.
Additionally and you can augment your Gateway to pass additional request info to your Lambda. See how
And also, to attach the request details to the RequestID you're seeing, you can check the context.awsRequestId.
I'd assume you want to do some form of log monitoring, in which case I think you can bundle up these request information(headers, query, params, body) and send to your log aggregator along with the awsRequestId.
Let me know if that helps
Further reference
A lambda function has two parameters: Event and context.
A normal invocation looks like this:
{
"event": {
"version": "0",
"id": "abcdefgh-1234-5678-1234-abcdefghijkl",
"detail-type": "Scheduled Event",
"source": "aws.events",
"account": "123456789012",
"time": "2018-01-01T12:00:00Z",
"region": "us-east-1",
"resources": [
"arn:aws:events:us-east-1:123456788901:rule/foo"
],
"detail": {}
},
"context": "<__main__.LambdaContext object at 0x123456ax1234>"
}
The test invocation has the elements you get.
You need to get this information from your lambda function context .
RequestId=context.aws_request_id
You will get following result
RequestId- "00cfaafe-5018-4be0-9668-b98daf5a7312" Version: $LATEST

Resources