Node is Simple — Part 1

1_q4C3LGm0jGTaDtoSco5d1w.jpg

tl;drThis is the first article of the Node is Simple article series. In this article series, I will be discussing how to create a simple and secure NodeJS, Express, MongoDB web application.

First of all let me give a big shout out to JavaScript, who’s going to turn 25 years old this year. W/O JavaScript, the world would be a much darker place indeed. 😁 In this article series what I am going to do is create an API with NodeJS, ExpressJS, and MongoDB. I know there is a vast ocean of tutorials out there, describing how to build an API with these technologies, but the thing is that I have never found a very comprehensive all in one tutorial where you get the knowledge of the following things.

  1. Setting up a basic NodeJS, Express web app with SSL/TLS.
  2. Setting up ESLint in your favorite editor or IDE.
  3. Adding MongoDB as the database.
  4. Creating basic CRUD endpoints and testing with Postman.
  5. Uploading files and view them using MongoDB GridFS.
  6. Creating custom middleware with Express.
  7. Add logging for the web application.
  8. Securing endpoints with JWT authentication.
  9. Validating the input using @Hapi/Joi.
  10. Adding an OpenAPI Swagger Documentation.
  11. Caching the responses with Redis.
  12. Load balancing with PM2.
  13. Testing the API using Chai, Mocha.
  14. Create a CI/CD pipeline.
  15. Deploying to your favorite platform.

Well if you have done all of these things with your web application, it would be awesome. Since I learned all of these the hard way, I want to share them with all of you. Because sharing is caring 😇.

Since this tutorial is a series I won’t be making this a long; boring to read one. In this first article, I will describe how to set up a simple NodeJS and Express app with SSL/TLS. Just that, nothing else.

maxresdefault

On your feet soldier, we are starting.

First of all, let’s create the folder structure of our web application.

1 jnP vv30BKCx84yOSHbTRQ

Figure 1: node-is-simple folder structure

As shown in figure 1, you need to create the folders and the index.js file. If you use Linux or, Git Bash on Windows, let’s make a simple script to do this. So you won’t have to do this again when you need to create another application. (We are so lazy aren’t we? 😂)

#!/usr/bin/env bash

############################################################
# Remember to create a folder for your project first       #
# And run `npm init` to initialize a node project          #
# Inside that project folder run this bootstrap.sh script  #
############################################################

# Create the folders
mkdir config controllers errors middleware models services swagger utilities database

# Create the index.js file
touch index.js

############################################################
# Remember to check if you have node and npm installed     #
# I assume you have installed node and npm                 #
############################################################

# Install required packages
npm install express chalk --save

#That's it folks!

Let’s go through it again.

First, you need to create a folder for your project and run npm init and initialize your application. With this, you can specify a great name to your project, your license of preference, and many more. Ah, I just forgot. You need to check if you have the current version of Node and NPM installed in your machine. I hope you know how to install NodeJS on your computer. If not please refer to the following links.

How to Download & Install Node.js - NPM on Windows

How To Install Node.js on Ubuntu 18.04

After doing that just run this bootstrap.sh bash script inside your project folder and it will create a simple Node, Express application. So simple right?

After creating the necessary folder structure let’s set up the Express application. Let’s go to the index.js file on the root folder and add these lines.

const express = require("express");
const chalk = require("chalk");
const http = require("http");
const https = require("https");
const config = require("./config");

const HTTP_PORT = config.HTTP_PORT;
const HTTPS_PORT = config.HTTPS_PORT;
const SERVER_CERT = config.SERVER_CERT;
const SERVER_KEY = config.SERVER_KEY;

const app = express();
const MainController = require("./controllers");

app.use("", MainController);
app.set("port", HTTPS_PORT);

/**
 * Create HTTPS Server
 */

const server = https.createServer(
  {
    key: SERVER_KEY,
    cert: SERVER_CERT
  },
  app
);

const onError = error => {
  if (error.syscall !== "listen") {
    throw error;
  }

  const bind =
    typeof HTTPS_PORT === "string"
      ? "Pipe " + HTTPS_PORT
      : "Port " + HTTPS_PORT;

  switch (error.code) {
    case "EACCES":
      console.error(chalk.red(`[-] ${bind} requires elevated privileges`));
      process.exit(1);
      break;
    case "EADDRINUSE":
      console.error(chalk.red(`[-] ${bind} is already in use`));
      process.exit(1);
      break;
    default:
      throw error;
  }
};

const onListening = () => {
  const addr = server.address();
  const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`;
  console.log(chalk.yellow(`[!] Listening on HTTPS ${bind}`));
};

server.listen(HTTPS_PORT);
server.on("error", onError);
server.on("listening", onListening);

/**
 * Create HTTP Server (HTTP requests will be 301 redirected to HTTPS)
 */
http
  .createServer((req, res) => {
    res.writeHead(301, {
      Location:
        "https://" +
        req.headers["host"].replace(
          HTTP_PORT.toString(),
          HTTPS_PORT.toString()
        ) +
        req.url
    });
    res.end();
  })
  .listen(HTTP_PORT)
  .on("error", onError)
  .on("listening", () =>
    console.log(chalk.yellow(`[!] Listening on HTTP port ${HTTP_PORT}`))
  );

module.exports = app;

Don’t run this yet, since we haven’t done anything yet. I know this is a bit too much just bear with me, I’ll explain everything. What we are doing here is, first we create an HTTP server and then we create an HTTPS server. Then we redirect all the HTTP traffic to the HTTPS server. First of all, we need to create certificates to use inside the HTTPS server. It is a little bit of pain, but it’ll worth it. This is a good resource about creating SSL certificates for your Node application.

How to Use SSL/TLS with Node.js

I am a little bit of a lazy person so I’ll just generate server.cert and server.key files using this link.

Self-Signed Certificate Generator

Inside the server name input, you just have to provide your domain name. For this purpose, I’ll use the localhost as the domain name.

After generating the *.cert and *.key files copy them to the /config folder. And rename them to server.cert and server.key.

Now let’s import the certificates and make them useful. Inside the /config folder create the file index.js and add these lines.

const fs = require("fs");

const SERVER_CERT = fs.readFileSync(__dirname + "/server.cert", "utf8");
const SERVER_KEY = fs.readFileSync(__dirname + "/server.key", "utf8");

module.exports = {
  SERVER_CERT,
  SERVER_KEY,
  HTTP_PORT: 8080,
  HTTPS_PORT: 8081
};

Not so simple after all right? Well, let’s see.

Now that we have set up the certificates, let’s create a simple controller (endpoint) to our application and check that out. First, let’s got to the /controllers folder and create an index.js file. Inside that add the following lines.

const router = require("express").Router();
const asyncWrapper = require("../utilities/async-wrapper");

/** @route  GET /
 *  @desc   Root endpoint
 *  @access Public
 */
router.get(
  "/",
  asyncWrapper(async (req, res) => {
    res.send({
      message: "Hello World!",
      status: 200
    });
  })
);

module.exports = router;

asyncWrapper what is that???

Let me tell you about that. Async Wrapper is a wrapper function that will catch all the errors happen inside your code and returns them to the error handling middleware. I’ll explain this a little more when I am discussing Express middleware. Now let’s create this infamous asyncWrapper. Go to the /utilities folder and create the two following files.

**async-wrapper.js**

module.exports = requestHandler => (req, res, next) =>
  requestHandler(req, res).catch(next);

**async.wrapper.d.ts** (Async wrapper type definition file)

We have done it, folks, we have done it. Now let’s check this beautiful Express app at work. Let’s run the web application first. Let’s go to the project folder and in the terminal (or Git Bash on Windows) run the following line.

node index.js

After that let’s fire up your favorite browser (mine is Chrome 😁) and hit the endpoint at,

https://localhost:8081/

Don’t worry if your browser says it is not secure to go to this URL. You trust yourself, don’t you? So let’s accept the risk and go ahead.

1 -j7gNIpPkuqIQj OQf9Y0A

This is the warning I told you about. (FYI, this screenshot is from Firefox)

Now if you can see something like this,

1 UNQTECXa-hXe2YM4ANG0DQ

Response from [https://localhost:8081](https://localhost:8081)

You have successfully created a NodeJS, Express application. Also since we have set up an HTTP server, you can try this URL too. http://localhost:8080

If you go to this URL, you’ll see that you’ll be redirected to https://localhost:8081

Now that’s the magic with our Express application. Awesome right? So this is it for this tutorial. In the next tutorial, I’ll tell you all about adding MongoDB as the database.

https://github.com/Niweera/node-is-simple

This is the GitHub repo for this tutorial and I’ll update this repo as the tutorial grows. Check for the commit messages for the snapshot of the repo for a particular tutorial. If you have any queries, don’t forget to hit me up on any social media as shown on my website.

https://niweera.gq/

So until we meet again with part two of this tutorial series, happy coding…

1_cuJOF_sqBLbMA69vCFMqEQ.jpeg
Nipuna Weerasekara

Part time web developer, full time dreamer… Find me @ https://niweera.gq