Skip to content

Guides CreatingAnApplication Nodejs

Braden Hitchcock edited this page Feb 13, 2020 · 19 revisions

Creating A Node.js Application Using Scootr Studio

View this tutorial in Python

This guide will walk you through the creation of a simple RESTful API for user information using Scootr Studio. Our API will consist of two endpoints:

Endpoint Method Functionality
/users POST Create a new user in our database with a randomly generated ID.
/users/{id} GET Get a single item from our database

The items in this guide will have the following format:

Property Type Description
id integer An integer between 1000 and 9999 that represents the unique identifier of our user.
name string The name of the user.
username string The username of the user.
email string The email address of the user.

We will be using the Node.js 12.X runtime.

Throughout the guide, configuration input names will be given in itallics and their values will be given in bold.

1. Setup General Configuration

The first thing we need to do is configure our Scootr application. Using the inputs in the toolbar at the top of the blueprint canvas:

  1. Set the application name to UserApplication
  2. Set the provider to AWS
  3. Set the region to US West 2

2. Create Our First HTTP Event

Since we are creating a RESTful API, we need to create some HTTP events that we can use to trigger our business logic.

  1. Drag an External Event from the resource bar to the left of the blueprint canvas and drop it onto the canvas
  2. Set the name of the External Event resource to CreateUser
  3. Give the event a type of HTTP
  4. Set the URL of the HTTP event to /users
  5. Set the method to POST

3. Create Our First Event Handler

Now that we have an HTTP event configured, we need to create a Compute Resource to handle it.

  1. Drag a Compute Resource from the resource bar and drop it onto the blueprint canvas
  2. Set the name of the Compute Resource to CreateUserHandler
  3. Set the runtime to Node.js 12.x

In the code editor inside the "Code" tab pane, we are going to place the Node.js code that will create a new user based on information we get from the request body. Take a moment to read through the code below to help you understand how the compute resource will operate.

'use strict';

// This is the AWS SDK for Node.js. We will be using it to access 
// our storage resource later.
const AWS = require('aws-sdk');

/**
 * This is the entrypoint for our code and contains the business
 * logic for our handler.
 */
async function handler(event, context) {
  // Creating our Document Client
  const client = new AWS.DynamoDB.DocumentClient();

  // We will generate a (non-secure) random numerical ID.
  const id = Math.floor(Math.random() * 10000);

  // We need to parse the JSON body content in order to use it.
  const body = JSON.parse(event.body);

  // Create the item we will add to the database.
  const item = {
    id: id,
    name: body.name,
    username: body.username,
    email: body.email
  };

  const params = {
    // We will come back to the `CreateUserToStorageRef` environment
    // variable in a moment
    TableName: process.env.CreateUserToStorageRef,
    Item: item
  };

  // Make our request
  try {
    await client.put(params).promise();
    return createJsonResponse(201, item);
  } catch (err) {
    return createJsonResponse(500, {
      message: 'Failed to create user',
      details: err.message
    });
  }
}

/**
 * This is a helper function that create the JSON response to the HTTP
 * request in the format that AWS Lambda is expecting.
 */
function createJsonResponse(statusCode, body = '', headers = {}) {
  return {
    statusCode,
    headers: {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': '*',
      ...headers
    },
    body: body === '' ? '' : JSON.stringify(body)
  };
}

// Export out handler so that AWS can invoke it.
module.exports = handler;

Now, copy and paste the code into the code editor in The Studio.

4. Create Our Storage Resource

Now we need a place to store our user data. Since we are using AWS, we are going to use their DynamoDB key-value store for our database.

  1. Drag a Storage Resource from the resource panel onto the canvas
  2. Give it a name of UserStorage
  3. Set it's type to Key-Value
  4. Set the database engine to DynamoDB
  5. Give it a collection name of Users
  6. Give it a primary key name of id
  7. Set the primary key type to Number

5. Add Connections

At this point, we have a valid External Event of type HTTP, a Compute Resource, and a Storage Resource. But, in order to do anything userful, we need to connect them all together.

Add A Trigger

We'll start by creating a Trigger from our CreateUser event to our CreateUserHandler Compute resource.

  1. Click and hold on the gray dot to the right of the CreateUser event and start dragging to create a new connection
  2. Drag the connection to the dot to the left of the CreateUserHandler
  3. Drop the connection onto the endpoint to create a new Trigger connection

Triggers do not need any additional configuration, so now we can move on to creating a Reference.

Add And Configure A Reference

Next, we will add a Reference from our CreateUserHandler to the UserStorage resource.

  1. Click and hold on the gray dot to the right of the CreateUserHandler event and start dragging to create a new connection
  2. Drag the connection to the dot to the left of the UserStorage
  3. Drop the connection onto the endpoint to create a new Reference connection
  4. Set the name of the reference to CreateUserToStorageRef
  5. Set the allowed action to Create

Using the Reference In Code

Remember how in our code from Step 3 above we had the following code as a parameter for our DynamoDB Document Client put method?

const params = {
  TableName: process.env.CreateUserToStorageRef,
  Item: item
};

Notice how the CreateUserToStorageRef environment variable is named the same as the Reference we just created. The library behind the scenes of the Studio makes the resource identifier we need for the TableName property available to us as this environment variable. Since the library is generating our resources for us, we can't always predict what it will be, but the library will make sure that our code has access to this identifier no matter what the generated name is so long as we use this environment variable.

5. Deploy And Test

Congratulations! You've created your first request/response chain in Scootr Studio! Let's deploy it so that we can test how it works.

  1. Click on the Deploy button in the toolbar above the blueprint canvas

You'll be able to see status updates about your deployment in the left of the status bar at the bottom of the application (bottom left of the screen). Once the deployment has finished, the loading circle will disappear and a message indicating the deployment success will appear.

Testing An External Event

The Studio makes it easy to test our external HTTP events by providing a RESTful API testing tool in the "Test" pane of the External Event resource.

  1. Click on the CreateUser event

  2. Click on the "Test" tab to open the event testing pane

  3. Enter the following as our request body for our test:

    {
      "name": "Luke Skywalker",
      "username": "masterjedi",
      "email": "skywalker@starwars.com"
    }
  4. Click on the "Send Request" button

  5. Take note of the response. You should see the following (minus header values):

    HTTP/1.1 201 Created
    
    {
        "id": <integer>,
        "name": "Luke Skywalker",
        "username": "masterjedi",
        "email": "skywalker@starwars.com"
    }
    
  6. Make note of the returned id. We will be using it later.

Viewing Compute Resource Logs

Once a compute resource has started receiving events, we can view logs from the processing that takes place in the "Logs" tab of the Compute resource details pane.

  1. Click on the CreateUserHandler resource
  2. Click on the "Logs" tab
  3. Wait for the Studio to connect to the log stream. Once it is connected and starts receiving events, you will be able to see the logs from AWS CloudWatch.

NOTE: Logs are polled once a second, so it may take some time for all of the logs to be displayed after the resource has received an event.

NOTE: The Studio shows logs up to 30 minutes before the "Logs" pane was opened

6. Create Our Second HTTP Event

Now let's add our second API endpoint to the application.

  1. Drag and drop another External Event onto the canvas
  2. Give it a name of GetUser
  3. Set its type to HTTP
  4. Give it a url of /users/{id}
  5. Set the method to GET

7. Create Our Second Compute Resource

Time to set up the handler for our second HTTP event.

  1. Drag and drop another Compute resource onto the canvas
  2. Give it a name of GetUserHandler
  3. Set the runtime to Node.js 12.x

Use the following as the code for this Compute resource:

'use strict';

const AWS = require('aws-sdk');

/**
 * This is the entrypoint for our code and contains the business
 * logic for our handler.
 */
async function handler(event, context) {
  // Creating our Document Client
  const client = new AWS.DynamoDB.DocumentClient();

  // Get the ID from the URL. It will be a string, so we need to turn
  // it into a number, since this is the type of the primary key in
  // our database.
  const id = Number(event.pathParameters.id);

  const params = {
    TableName: process.env.GetUserToStorageRef,
    Key: {
      id: id
    }
  };

  // Make our request
  try {
    const response = await client.get(params).promise();
    return createJsonResponse(200, response.Item);
  } catch (err) {
    return createJsonResponse(500, {
      message: 'Failed to get user with id: ' + id,
      details: err.message
    });
  }
}

/**
 * This is a helper function that create the JSON response to the HTTP
 * request in the format that AWS Lambda is expecting.
 */
function createJsonResponse(statusCode, body = '', headers = {}) {
  return {
    statusCode,
    headers: {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': '*',
      ...headers
    },
    body: body === '' ? '' : JSON.stringify(body)
  };
}

// Export out handler so that AWS can invoke it.
module.exports = handler;

8. Create Another Trigger and Reference

Now let's connect the dots between the resources implementing this new endpoint's logic.

  1. Create another Trigger by connectiong the GetUser event to the GetUserHandler Compute resource
  2. Create a Reference by connecting the GetUserHandler resource to the UserStorage resource we created in Step 4
  3. Give this new Reference a name of GetUserToStorageRef
  4. Set the allowed action to Read

At this point, your blueprint canvas should look similar to the following:

9. Deploy Changes and Test

Now we need to update our deployed application with our changes.

  1. Click on the "Deploy Changes" button again to deploy the changes you've made to your application to the cloud

Once the deployment has completed:

  1. Click on the GetUser event

  2. Click on the "Test" tab

  3. Enter the ID from your original test of the CreateUser event as the value for the id path parameter

  4. Click on "Send Request". You should see a response similar to the one below (minus headers):

    HTTP/1.1 200 OK
    
    {
        "id": <integer>,
        "name": "Luke Skywalker",
        "username": "masterjedi",
        "email": "skywalker@starwars.com"
    }
    

If you didn't save or don't remember the ID, you can always create a new User by testing the CreateUser event again.

Conclusion

And that's it! You've successfully created a simple RESTful API for user information using Scootr Studio. Feel free to extend your user application by adding more endpoints for updating a user, deleting a user, and getting a list of all the users. You may find the Scootr AWS Driver documentation helpful for implementing these additional functionalities.