DEV Community

Cover image for Building a Serverless Hogwarts Sorting Service with Node and AWS Lambda
Eva Greiner-Anzenbacher
Eva Greiner-Anzenbacher

Posted on

Building a Serverless Hogwarts Sorting Service with Node and AWS Lambda

Being on the job hunt for my first web developer role I realized that knowledge and experience with serverless architecture are required and critical for most positions.

During my Full-Stack Web Development training program, I already built an authorization server with the Serverless Toolkit and AWS Lambda. But, only practice makes perfect, and I wanted to have another project to cement what I've learned.

As I'm currently re-reading the Harry Potter book series, I had the idea to build a Sorting Service that assigns a user to a random Hogwarts house. Besides, it should show other students already living in this house. To fetch data about characters, I used this Harry Potter API.

With Node, Serverless Toolkit, AWS Lambda, and API Gateway we'll build a simple API that returns a random Hogwarts house as well as some housemates.

Prerequisites

Before we can start with the actual project, we need to have Node and npm installed, as well as create and activate our own AWS account.

Installing the Serverless Toolkit and Creating a Serverless Service

One reason we'll use the Serverless Toolkit here is, that we'll have to install axios, later on, to fetch data from the Potter API and Serverless lets us easily do this. I also like Serverless when working with AWS because it's easier to implement code or deploy functions locally without having to work with the inline code editor in AWS.

To install Serverless globally and create a Node template, we run the following commands:

npm install -g serverless
serverless create --template aws-nodejs --path random-sorting-service
cd random-sorting-service
npm init // creates a package.json
Enter fullscreen mode Exit fullscreen mode

Our directory structure should look like this now:

📦random-sorting-service
┣ 📜.gitignore
┣ 📜handler.js   // here we'll write our sorting function
┣ 📜package.json
┗ 📜serverless.yml // here we'll configure our function
Enter fullscreen mode Exit fullscreen mode

Configuring AWS Credentials

To make sure the Serverless Toolkit can interact with AWS we need to configure and add our AWS credentials. We'll create an access key that allows us to configure the Serverless Toolkit and enable it to deploy functions directly to AWS.

To achieve this, we have to follow these steps:

  1. Log in to our newly created AWS account by clicking on "Sign in to the Console".
  2. Click on our username in the upper right-hand corner and select "My Security Credentials".
  3. Select "Access keys" and click the "Create New Access Key" button.
  4. Download the new access key (it contains an access key ID and a secret access key) and store it in a safe place.

Back in our terminal, we run the following command (using our own credentials):

serverless config credentials --provider aws --key ACCESS_KEY_ID --secret SECRET_ACCESS_KEY
Enter fullscreen mode Exit fullscreen mode

Configuring and Setting Up serverless.yml

We now open the serverless.yml file in our code editor and declare our sections as follows:

Screenshot of serverless.yml set up

Writing the Lambda Function

The Random House Generator

We open the handler.js file, delete the dummy code, and replace it with the following:

Screenshot of code to get a random house

Let's take a closer look at the code example above:

The function is named getRandomHouseAndHousemates because in Step 2 we'll also fetch data of associated house members.

First, we put all four Hogwarts houses inside an array. Then, we create a random index that is used to display a random house. We use the Math.random() function that returns a floating-point, pseudo-random number between 0 (inclusive) and 1 (exclusive). We also need the Math.floor() function to get a whole number and not a floating type. Because Math.floor() returns a number representing the largest integer less than or equal to the specified number, if passing Math.random() as a parameter to Math.floor(), we get a whole number.

But there is one problem left we have to handle: Math.floor() is always rounding down to the nearest decimal, so every decimal between 0 and less than 1 (and that is what Math.random() is returning) will always be 0. To get a random number between 0 and 4 (the length of our houses array) we have to multiply the Math.random() by randomHouse.length. This index now can be applied to get a random house.

Because we'll have cross-origin requests if we'd want to use our service within another app, we also have to add the Access-Control-Allow-Origin header to the return statement in handler.js

Testing the Random House Generator

Before deploying, we can test our function locally. For now, it should only return a random Hogwarts house. From inside our project directory, we run:

serverless invoke local --function getRandomHouseAndHousemates
Enter fullscreen mode Exit fullscreen mode

If everything works as expected, we should see something like this in our terminal:

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*"
    },
    "body": "{\"randomHouse\":\"Hufflepuff\"}"
}
Enter fullscreen mode Exit fullscreen mode

If that works, we can go on and implement the additional logic to fetch and return data about our new housemates.

Getting data from 3rd party API

In order to be able to make requests to the Harry Potter API, inside our random-sorting-service folder, we run:

npm install axios
Enter fullscreen mode Exit fullscreen mode

In our handler.js, we add the code we need to get and return our housemates' data:

Screenshot of completed code

Let's take a closer look at this code example, too:

In our handler.js, we have to require axios. Then, we use the randomHouse variable declared in the first step to generate the URL to reach the API endpoint we need. Subsequently, we make the API request. As getRandomHouseAndHousemates already is an async function, we'll use a try...catch block to handle possible request errors with axios.

Because we plan to return only students from the same house, but the given endpoint returns teachers as well as students, we have to apply the filter() method to the API response as well.

Testing the API Request

Now it is time to test our function locally again before we finally can deploy:

serverless invoke local --function getRandomHouseAndHousemates 
Enter fullscreen mode Exit fullscreen mode

We should see something similar to that in our terminal:

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*"
    },
    "body": "{\"randomHouse\":\"Ravenclaw\",\"housemates\":[{\"name\":\"Cho Chang\",\"species\":\"human\",\"gender\":\"female\",\"house\":\"Ravenclaw\",\"dateOfBirth\":\"\",\"yearOfBirth\":\"\",\"ancestry\":\"\",\"eyeColour\":\"brown\",\"hairColour\":\"black\",\"wand\":{\"wood\":\"\",\"core\":\"\",\"length\":\"\"},\"patronus\":\"swan\",\"hogwartsStudent\":true,\"hogwartsStaff\":false,\"actor\":\"Katie Leung\",\"alive\":true,\"image\":\"http://hp-api.herokuapp.com/images/cho.jpg\"},{\"name\":\"Luna Lovegood\",\"species\":\"human\",\"gender\":\"female\",\"house\":\"Ravenclaw\",\"dateOfBirth\":\"13-02-1981\",\"yearOfBirth\":1981,\"ancestry\":\"\",\"eyeColour\":\"grey\",\"hairColour\":\"blonde\",\"wand\":{\"wood\":\"\",\"core\":\"\",\"length\":\"\"},\"patronus\":\"hare\",\"hogwartsStudent\":true,\"hogwartsStaff\":false,\"actor\":\"Evanna Lynch\",\"alive\":true,\"image\":\"http://hp-api.herokuapp.com/images/luna.jpg\"}]}"
}
Enter fullscreen mode Exit fullscreen mode

Deploying to AWS

If that works, we can deploy:

serverless deploy
Enter fullscreen mode Exit fullscreen mode

The Serverless Toolkit will now hand over our function to AWS using the infrastructure requirements we provided in our serverless.yml. When successfully finished, we should see this information in our terminal:

Screenshot of serverless deploy output

Under the endpoints output, we can see the (API Gateway-) generated URL we need to invoke our function. The path /dev/house not only contains the trailing /house as specified in our serverless.yml but also contains /dev/ as Serverless deploys to the dev environment by default (we could also deploy to production by using the --stage flag: serverless deploy --stage prod).

Now, we can check if all files have been deployed to Lambda successfully. In our AWS Management Console, we search for Lambda and select getRandomHouseAndHousemates. We should see something like this:

Screenshot service at AWS Lambda

Testing the Endpoint

We can try out our endpoint by simply copying it from the terminal and paste it into the address bar of our browser.

Screenshot browser output

If we use Postman, we get a neater looking result:

Screenshot Postman output

Now that our serverless function is up and running, we could access our newly created API from any web application (I'm planning to build a Sorting Hat App with React and TypeScript, but this is another story...).

Find the completed code of this Random Sorting Service on GitHub.

Top comments (0)