access root event in EB input transformer - amazon-web-services

i have an input event, for example:
{"key1": "val1", "key2": "val2"}
i would like to add an input transformer to output the following:
{"task_id": "some_const_id", "payload": {"key1": "val1", "key2": "val2"}}
so basically id like to put the entire event as a key in the output event.
i tried to access the "root" event by using things like:
input path:
{"payload": "$"}
template:
{"task_id": "some_const_id", "payload":"<payload>"}
but $ is not the correct way to access it. couldn't find anything online.

ok i found it,
the var name is called:
<aws.events.event.json>
template now looks like this:
{"task_id": "some_const_id", "payload":<aws.events.event.json>}

Related

Don't show discovered fields in CloudWatch log insights?

Is it possible to configure CloudWatch log insights so it just shows the JSON log message, not the discovered fields? For example, currently my logs show up like this:
#timestamp xxx
#message { "field1": "value1", "field2": "value2" }
field1 value1
field2 value2
Because CloudWatch discovered the two fields in the JSON message. But is it possible to just see the JSON, like so:
{
"field1": "value1",
"field2": "value2"
}
This would make it much easier for me to copy logs to different sources, as the #message field can get very long and unreadable if it's not formatted as JSON, which each field on a separate line and with indentations. Also, when I copy a log entry in the first format from Log Insights, the formatting puts the field name and value on different lines which is difficult to read.

AWS API Gateway - Configuring Integration Request Mapping Templates to accept String body rather JSON

I have a spring boot application with GET method like below. This method has input parameter as String that is mapped with path variable {userId}.
#GetMapping("/users/{userId}")
public String get(#PathVariable ("userId") String userId) {
return userId;
}
I created AWS lambda function and uploaded my spring boot JAR. I am able to test lambda fuction with test event after passing string example "userId1". Lambda function worked fine.
Using API gateway, created API, defined resource and GET method. URL looks like below:
/users/{userId} - GET - Integration Request
Also, followed below steps to define Mapping Templates.
Opened the Integration Request settings and then Body Mapping Templates.
Selected the option: When there are no templates defined (recommended)
Added a mapping template for: application/json
Added the following template to map the userId to the Lambda input
{
"userId": "$input.params('userId')"
}
When I test my API, it gives me below exception. I am not sure, how I should define Mapping Templates so that it accepts only String rather JSON. Because my Lambda function and corresponding implemented method accepts only String. Thanks in advance for help.
{
"errorMessage": "An error occurred during JSON parsing",
"errorType": "java.lang.RuntimeException",
"stackTrace": [],
"cause": {
"errorMessage": "com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream#69b2283a; line: 1, column: 1]",
"errorType": "java.io.UncheckedIOException",
"stackTrace": [],
"cause": {
"errorMessage": "Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream#69b2283a; line: 1, column: 1]",
"errorType": "com.fasterxml.jackson.databind.JsonMappingException",
"stackTrace": [
"com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)",
"com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:857)",
"com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:62)",
"com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)",
"com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1511)",
"com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1102)"
]
}
}
}
I think that your problem occurred because you are mapping a JSON like:
{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": {
"sub_key1": "value4"
}
}
This containt a key key4 with and JSON object as value. When your are trying to deserialize this element, it won't work directly because it sees a JSON_OBJECT, not a String.
You need to create a class like the following one:
public class Name { // the name doesn't matter
#JsonProperty("sub_key1")
private String sub_key1;
// getter and setter
}
to solve your problem.
My problem is resolved with simple change. As, I mentioned in my above question, I followed below steps.
Opened the Integration Request settings and then Body Mapping Templates.
Selected the option: When there are no templates defined (recommended)
Added a mapping template for: application/json
Added the following template to map the userId to the Lambda input
{ "userId": "$input.params('userId')" }
In last step #4, I replaced below JSON format with String format.
{ "userId": "$input.params('userId')" }
With below, it worked. My API could pass String parameter properly to my lambda function which has handler method with one single input of type String.
$input.params('userId')

Appsync response mapping template json key name change

What would be the right way to change json response key value in aws appsync response mapping template?
JSON that I get looks like this:
{
"tenant_id": 1,
"id": "bd8ce6a8-8532-47ec-8b7f-dcd1f1603320",
"header": "Header name",
"visible": true
}
and what I would like to pass forward is
{
"tenantId": 1,
"id": "bd8ce6a8-8532-47ec-8b7f-dcd1f1603320",
"header": "Header name",
"visible": true
}
Schema wants tenant id in form of tenantID and lambda returns it in form of tenant_id. I could change it in lambda but I would like to know how to do it in response mapping template.
You could do this via the response mapping template for the field you are resolving to in the following manner:
Consider the JSON response from your lambda to be stored in the response variable, then you can return something like this.
$#set($result = {
"tenantId": ${response.tenant_id},
"id": "${response.id}",
"header": "${response.header}",
"visible": $response.visible
})
$util.toJson($result)
Alternatively, you could also mutate your response from the lambda by setting a tenantId field, something like #set( $response.tenantId = $response.tenant_id ). Let me know if you still face an issue.
Thanks,
Shankar

Show user rights and status for a REST resource

An user can have different rights to a REST resource. Like delete or edit the resource. Also child resources can have different user rights.
Example:
GET /cats -> return all cats
GET /cats/{id} -> return cat {id}
UPDATE /cats/{id} -> update cat {id}
POST /cats/{id}/like -> create a like to the cat {id}
DELETE /cats/{id}/like -> delete your like to the cat {id}
When an user requests a cat resource I want to show him the rights (allowed actions) and the status of the object.
In this example:
Is the user allowed to update the cat?
Is the user allowed to like the cat?
Does the user already like the cat?
Our UI should use this information to show allowed actions for an objects:
Update button
Like button
Dislike button
How can I add this information to my resource response. It should be possible to add the information to one resource, but also to a list of objects.
I thought about Links in the http header for all allowed actions. But this would only be possible for one object. Is their a better solution?
I'm unclear on why you can't include collection-specific links in the header of the response containing the collection. I'll take you at your word that that's not possible, but it seems like it should be an option.
Another option is to use an envelope around your response data. That will let you include metadata, including links, at the collection level.
GET /cats?owner=12
{
"totalRecords": 2,
"links": [ ... ],
"records": [ ... ]
}
EDIT (based on comment)
You should add a links property to the cat representation, either as an envelope or as a direct property. So your cat would look like:
GET /cats/354
{
"name": "Poke",
...,
"links": [
{ "rel": "like", "href": "/cats/12/like" },
....
]
}
Then, each cat in your collection will have the relevant links associated with it. This is a generally accepted alternative to using link headers.
Variations:
Some people like including the verb in the link resource, such as { "rel": "like", "verb": "POST", "href": "/cats/12/like" }
Some people like making the ref the name of the link property, such as "links": { "like": "/cats/12/like", "delete": "/cats/12" }

I need to find and configure AWS Lambda to accept a parameter. Is it possible?

I need to find and configure AWS Lambda to accept a parameter and based on the input it has to process the request and insert data into service now portal.
When invoking a lambda, you can add a payload, for example:
{
"key3": "value3",
"key2": "value2",
"key1": "value1"
}
Which you can then call in your code:
def my_handler(event, context):
print("First value is event['key1']")
// do other stuff and return
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
http://docs.aws.amazon.com/lambda/latest/dg/get-started-create-function.html
So you could use this input to add a parameter for processing.
You pass data ['abc', 'xyz'] in JSON format when invoke lambda function
than in the lambda function get data like,
Example:
event[0], event[1]
In event[0] value is abc