Rachelle Rathbone

Building Your First Serverless App - Part 3

Updating saveCustomer and Accessing Logs

January 30, 2021

This post continues on from part 2 in this series so make sure you check out parts 1 and 2 before continuing on.

In part 2 of my serverless series, we set Postman up so that we could easily test our API. Today, we're going to update our saveCustomer function and take a look at our logs in AWS CloudWatch.

Updating Our Lambda Function

Right now, saveCustomer doesn't do a whole lot. It returns a successful save message, regardless of the outcome, and the entire event. If you run your request in Postman you'll see there's a lot of data that comes back in the event object when all we really want is the body property. Additionally, because we aren't including the statusCode inside of the body object, we don't actually see that in the response in Postman.

Since we are going to start completely refactoring this function in this post, go ahead and delete everything in the body of saveCustomer.

If we were to create a real customer, my guess is we'd probably want to collect a number of data points on them but, for simplicity's sake, let's just pretend all we need is for a customer to enter an email and a password in order to sign up.

The first thing we'll want to do is to pull the properties from the event object, the first argument passed to our lambda function. This object, as you would've seen from the response if you followed the previous post, contains information from the invoker, formatted as a JSON string.

In the screenshot above you'll see I'm using destructuring to pull out the properties I need and then wrapping the event body in JSON.parse to parse the JSON string that is returned.

If this were a real application we would now want to do a couple of things for security purposes:
  1. Add validation: Even if this is done on the frontend, validations should always be performed on the backend. This not only serves as a double check that all data being sent in the payload is valid, but gives you the opportunity to block cross site scripting attacks. Ideally, code would be validated and sanitised before a request is made to any of your lambda functions but you should always approach potential vulnerabilities like it is up to you to baton down the hatches. Trust no one. Not even yourself if you were the one who built the frontend that's sending the request. If everyone had this mentality, applications would generally be far more secure.
  2. Hash the password: We never want to save passwords as plain text, nor do we want to make it possible for them to be converted to plain text. In this post and the next we'll be working with plain text passwords but, in a later post in this series, I'll show you how to hash your users passwords and generate a token that can then be used for authentication.

For now, let's just check if an email and password has been provided. If not, we'll create an error object and pass it to our lambda's third argument: the callback function. This callback function will have arguments (Error and response) and, when called, will wait for the event loop to be empty. It will then return either the error or response.

Above you can see that we're checking to see if the email or password is not provided. If it is, we create a custom error object, and then pass it as a first and only argument to the callback function. You can add whatever you want to this object that you think would be of benefit to the person who's going to receive the response payload. Here we're setting the errorType to BadRequest, sending a statusCode of 400, and clarifying the error cause further with an error message. We're also passing in the requestId which is available on the context object - the second argument passed to lambda functions (for other properties on the context object, check out these AWS docs).

That's a potential error scenario accounted for. Let's take care of a successful customer save.

Outside of our email and password check, I've added a callback to handle our successful cases. This time, the first argument is null as we don't want to pass in an error object, and the second argument is the success response we want to send.

Testing it Out in Postman

In your save customer POST from part 2, click on body and update the payload to include an email and password. Also, make sure to change the format type from Text to JSON. Otherwise, your request will fail even with the correct values passed in.

Go ahead and hit send and you should see the following response.

Now, remove either the password or email from your payload and try making another request.

Definitely not very useful. We'll work on handling our error response in a later post, for now, let's go to the AWS console and check out some logs.

CloudWatch Logs

In the AWS console search for CloudWatch - a tool used for logging and metrics. Come here whenever things start going awry and you need to debug.

Once you're in CloudWatch, located 'Log groups' in the left-hand panel.

Then click on the link for your lambda function.

If you've been making numerous requests from Postman, you'll probably see a long list of logs. By default, the most recent should be at the top. Feel free to poke around and have a look at what you've been sending through. If you open the most recent one, however, and click on the arrow, you'll see logs for the error handling we added.

Now we've got a slightly more useful lambda function and know where to find logs to help with debugging but there is still much more that needs to be done. Up next, in part 4, we'll set up dynamo so we can actually start saving our customers in a database.
© 2023, Rachelle Rathbone