<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eva Greiner-Anzenbacher</title>
    <description>The latest articles on DEV Community by Eva Greiner-Anzenbacher (@evagrean).</description>
    <link>https://dev.to/evagrean</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F447103%2Fb052ed3d-e2e9-41a1-974f-1a089dd003e6.jpg</url>
      <title>DEV Community: Eva Greiner-Anzenbacher</title>
      <link>https://dev.to/evagrean</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/evagrean"/>
    <language>en</language>
    <item>
      <title>Building a Serverless Hogwarts Sorting Service with Node and AWS Lambda</title>
      <dc:creator>Eva Greiner-Anzenbacher</dc:creator>
      <pubDate>Thu, 31 Dec 2020 13:27:33 +0000</pubDate>
      <link>https://dev.to/evagrean/building-a-serverless-hogwarts-sorting-service-with-node-and-aws-lambda-4ahm</link>
      <guid>https://dev.to/evagrean/building-a-serverless-hogwarts-sorting-service-with-node-and-aws-lambda-4ahm</guid>
      <description>&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;As I'm currently re-reading the Harry Potter book series, I had the idea to build a &lt;em&gt;Sorting Service&lt;/em&gt; 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 &lt;a href="https://hp-api.herokuapp.com/" rel="noopener noreferrer"&gt;Harry Potter API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;Node&lt;/code&gt;, &lt;code&gt;Serverless Toolkit&lt;/code&gt;, &lt;code&gt;AWS Lambda&lt;/code&gt;, and &lt;code&gt;API Gateway&lt;/code&gt; we'll build a simple API that returns a random Hogwarts house as well as some housemates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before we can start with the actual project, we need to have &lt;code&gt;Node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; installed, as well as &lt;a href="https://aws.amazon.com/de/premiumsupport/knowledge-center/create-and-activate-aws-account/" rel="noopener noreferrer"&gt;create and activate our own AWS account&lt;/a&gt;.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the Serverless Toolkit and Creating a Serverless Service
&lt;/h3&gt;

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

&lt;p&gt;To install &lt;code&gt;Serverless&lt;/code&gt; globally and create a &lt;code&gt;Node&lt;/code&gt; template, we run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g serverless
serverless create --template aws-nodejs --path random-sorting-service
cd random-sorting-service
npm init // creates a package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our directory structure should look like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦random-sorting-service
┣ 📜.gitignore
┣ 📜handler.js   // here we'll write our sorting function
┣ 📜package.json
┗ 📜serverless.yml // here we'll configure our function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring AWS Credentials
&lt;/h3&gt;

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

&lt;p&gt;To achieve this, we have to follow these steps:&lt;/p&gt;

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

&lt;p&gt;Back in our terminal, we run the following command (using our own credentials):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless config credentials --provider aws --key ACCESS_KEY_ID --secret SECRET_ACCESS_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring and Setting Up &lt;code&gt;serverless.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;We now open the &lt;code&gt;serverless.yml&lt;/code&gt; file in our code editor and declare our sections as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhtxvh453g7wz3e7p086l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhtxvh453g7wz3e7p086l.png" alt="Screenshot of serverless.yml set up" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing the Lambda Function
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The Random House Generator
&lt;/h4&gt;

&lt;p&gt;We open the &lt;code&gt;handler.js&lt;/code&gt; file, delete the dummy code, and replace it with the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2g7s3t8k3hf2v7jfoht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb2g7s3t8k3hf2v7jfoht.png" alt="Screenshot of code to get a random house" width="601" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a closer look at the code example above: &lt;/p&gt;

&lt;p&gt;The function is named &lt;code&gt;getRandomHouseAndHousemates&lt;/code&gt; because in Step 2 we'll also fetch data of associated house members.&lt;/p&gt;

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

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

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

&lt;h4&gt;
  
  
  Testing the Random House Generator
&lt;/h4&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless invoke local --function getRandomHouseAndHousemates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works as expected, we should see something like this in our terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*"
    },
    "body": "{\"randomHouse\":\"Hufflepuff\"}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that works, we can go on and implement the additional logic to fetch and return data about our new housemates.&lt;/p&gt;

&lt;h4&gt;
  
  
  Getting data from 3rd party API
&lt;/h4&gt;

&lt;p&gt;In order to be able to make requests to the &lt;a href="https://hp-api.herokuapp.com/" rel="noopener noreferrer"&gt;Harry Potter API&lt;/a&gt;, inside our &lt;code&gt;random-sorting-service&lt;/code&gt; folder, we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our &lt;code&gt;handler.js&lt;/code&gt;, we add the code we need to get and return our housemates' data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F10nptj5e0x78fljr1fl4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F10nptj5e0x78fljr1fl4.png" alt="Screenshot of completed code" width="758" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a closer look at this code example, too: &lt;/p&gt;

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

&lt;p&gt;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 &lt;code&gt;filter()&lt;/code&gt; method to the API response as well. &lt;/p&gt;

&lt;h4&gt;
  
  
  Testing the API Request
&lt;/h4&gt;

&lt;p&gt;Now it is time to test our function locally again before we finally can deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless invoke local --function getRandomHouseAndHousemates 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should see something similar to that in our terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "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\"}]}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying to AWS
&lt;/h3&gt;

&lt;p&gt;If that works, we can deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;serverless deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mbj6pwz5pmtwq7himuu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mbj6pwz5pmtwq7himuu.png" alt="Screenshot of serverless deploy output" width="755" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

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

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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkxqwy9ox55ervxt89c3z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkxqwy9ox55ervxt89c3z.png" alt="Screenshot service at AWS Lambda" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the Endpoint
&lt;/h3&gt;

&lt;p&gt;We can try out our endpoint by simply copying it from the terminal and paste it into the address bar of our browser. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmszo6bw95vekumf0402.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcmszo6bw95vekumf0402.png" alt="Screenshot browser output" width="800" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we use Postman, we get a neater looking result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwvmif7rf4jnirzh0el98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwvmif7rf4jnirzh0el98.png" alt="Screenshot Postman output" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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...). &lt;/p&gt;

&lt;p&gt;Find the completed code of this &lt;a href="https://github.com/evagrean/random-sorting-service" rel="noopener noreferrer"&gt;Random Sorting Service on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>serverless</category>
      <category>aws</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
