Serverless 3: API Integration Responses and Lambda Proxy
In the last tutorials (part 1 and part 2) we created DynamoDB tables, Lambda functions, resources and methods inside API Gateway and even some simple logic to run database queries directly from the API templates, without the need to code anything.
In this third article about serverless architecture (and development), we will finish the API calls with the two still remaining: UPDATE e DELETE. For the first, the API Gateway will be just as a proxy integration for a Lambda function. For the latter, we will use a DynamoDB query action called DeleteItem, straight from the API.
Let’s go!
Editing Permissions (I)
For our Lambda function to be able to edit a DynamoDB table, we will need to create a new role or edit an existing one. In this case, we will create an additional role.
Go to IAM dashboard and choose Roles -> Create Role.
Then, click on AWS Service as type, Lambdaa as use case e click Next: Permissions.
Now, you will need to attach a policy to this role, allowing only the change/update action (UpdateItem) for DynamoDB. As this is not created by default, click on Create Policy.
In this new screen, fill up as below:
· Service: DynamoDB
· Actions: UpdateItem
· Resources: Specific, then Add ARN, then use region: your-region-X, Account: your-account-id, Table Name: Users)
Click Add and then Review Policy.
Name it DynamoDBUpdateItem and click Create Policy.
Once finished, head back to the previous role screen, refresh the Policy list, select DynamoDBUpdateItem and click in Next: Tags and Next:Review.
Name it LambdaDynamoDBUpdate and click in Create role. That’s all!
Lambda Function (UPDATE)
Go to the Lambda dashboard and click in Create Function.
Then select Author from Scratch and fill in using the information below, clicking in Create Function after that.
· Function Name: UpdateUser
· Runtime: Python 3.8
· Permissions: Use existing role -> LambdaDynamoDBUpdateItem
The API that will trigger this function will be a simple proxy integration, and for this reason, the request body is passed in a different way with much more information about the API call, so it must be handled with care in your code.
In the function IDE screen, in the section Function Code, paste this code.
At last, click in Deploy.
API Gateway (UPDATE)
Head back to the API Gateway dashboard, inside the resource created before to GET a simple user, let’s insert a new method PATCH.
To do that, select the highlighted resource above and in the dropdown Actions, select Create Method. Then in the menu, select PATCH and click the little check mark.
In the configuration page, use the information below to fill in the gaps:
· Integration Type: Lambda Function
· Use Lambda Proxy integration: Yes (checked)
· Lambda Region: your-region-xx
· Lambda Function: UpdateUser
Hit Save.
You will be prompted to allow API Gateway to call Lambda function on your behalf. Please accept it in OK.
Testing Time!
In the Method Execution screen, click Test.
Here, in resource path {usuario} put the user previously created on parts 1 and 2 and paste the following in the Request Body :
{
"user_pass":"myNewHashedMD5EncryptedPassword",
"user_fullname":"Novo Nome Que eu Quiser"
}
Finally, click Test down below and, if everything is fine, you will get the response returned by the Lambda function.
And just checking our DynamoDB table for updated item:
And that ends the API for updating. If you need to update other fields, just change the SET attribute on the Lambda function, and map the input JSON to the desired variables.
API Gateway (DELETE)
For this last part, to remove user, go again to the API Gateway dashboard and select the resource {usuario}, and then Actions -> Create Method.
Follow the same M.O. of the PATCH method and use the information below to fill in:
· Integration Type: AWS Service
· AWS Region: your-region
· AWS Service: DynamoDB
· HTTP Method: POST
· Action: DeleteItem
· Execution Role: (APIDynamoDBCustom role ARN)
We will reuse the role (APIDynamoDBCustom) because already attached to it there is a policy (DynamoDBCustomPermissions) that also allows us to use DeleteItem.
Click Save.
Last stage, use the DeleteItem query syntax to delete an item directly from the API call (no functions!). For that, click in Integration Request.
Further down below, expand the section Mapping Templates, choose the second (recommended option) and click in the little (+) sign and then Add mapping template.
Type application/json and click the little check mark to open a small coding section. Paste the following lines:
{
"TableName": "Users",
"Key": {
"username": {
"S": "$input.params(‘usuario’)"
}
},
"ReturnValues": "ALL_OLD"
}
This bold line will give us back the deleted item attributes before the deletion as a response, instead of a blank body.
Testing (DELETE)
Ready to test, click Test. In Path {usuario} type any user present in the table and hit Test.
See the body? API response, by default, returns a JSON formatted from DynamoDB, but as a bonus, let’s clean it up removing some fields and additional data.
This is not necessary to finish this part of the tutorial, just as a new stuff to use.
It is possible to format a JSON response from a Lambda function, but as we are using Integration Request, let’s edit Integration Response as well.
Bonus: Editing Responses (DELETE)
Head back to the Method Execution from the DELETE method and click in Integration Response.
Expand the Response 200 section ein Mapping Templates, click in application/json and in the little screen that appeared, type:
#set($inputBody = $input.path('$'))
{
"deleted":TRUE,
"username": "$inputBody.Attributes.username.S",
"usuario_id": $inputBody.Attributes.user_info.M.user_id.S
}
What happened here is that the API response body was mapped to the inputBody variable and between the curly brackets is the custom JSON that we want to appear as final response, mapping the key/values of the dynamoDB structure and types (S for String, M for Map, etc).
Head back to Test and try to delete another user.
Conclusion
End of Part 3! We now have a complete API with GET, POST, PATCH e DELETE and two Lambda functions with different integrations.
As explained in the first article, it is essential to have some kind of security for API authorization and in the next post I will explore a litlle more Lambda authorizers and tokens to allow or deny access to these resources.
Thanks for following and see you in the next post!