Backend Camp: A Simple REST API
Tags: node, rest, express, backend
Published: 2021-05-12 15:14:28

## Introduction
If you're coming from Frontend Web, iOS, or Android app development your knowledge of backend development might only be limited on how to query an API endpoint and magically receive the exact data you need. If you're exclusively a client (web, iOS, Android) developer then you might find that you don't really need to fully understand how the backend is implemented but it might help you to understand at a high level what happens when you dispatch a request to a backend API. That's the purpose of this article. We are going to be using [nodejs](https://nodejs.org/en/), [expressjs](https://expressjs.com/), and [micronode-cli](https://www.npmjs.com/package/micronode-cli) to build a simple REST API.

## Prerequisites
In order to successfully complete this lesson you need to have the following software downloaded an installed on your computer:

 1. [nodejs](https://www.nodejs.org) - Runtime Environment to run Javascript applications outside of your browser
 2. Any code editor. We will be using [VSCode](https://code.visualstudio.com/) in this lesson but any editor is fine.
 3. [Postman](https://www.postman.com/) - To send requests to our API without needing a browser.

## Step One: Installation
Typically, when building a web server in nodejs, you'd need to manually install your dependencies which, at a minimum, usually consists of a **Web Framework**. A web framework provides some higher-level abstractions on top of some web protocol to make development of web services easy and seamless. While you *can* create a web server without using a framework, using battle tested software and web frameworks ensures that you are on the right track to building resilient and performant backend services. In this lesson, we are going to be using expressjs which is a web framework that makes it extremely simple to develop [REST (REpresentational State Transfer)](https://en.wikipedia.org/wiki/Representational_state_transfer) APIs. The standard steps to create a backend API would be as follows:
```shellscript
  $ npm init // initialize your Node JS project
  $ npm install express // install the express js framework as a dependency
  $ touch server.js // create a server.js file
```

When creating multiple services, these steps can seem repetitive which is a perfect example of something that can be automated. The `micronode-cli` application automates this process. We can install and run this script with the following commands:

    $ npm install -g micronode-cli // installs micronode-cli globally on your system

Now, in the directory of your choice, you can initialize (create) your service with the following commands:

    $ mn create-service first-service

You'll see the following output:

    Creating service named: first-service
    Directory: [PATH]
    Running npm init...
    Node Project Initialized
    Installing Dependencies...
    Dependencies Installed:
	    - express
	Creating Dockerfile...
	Initializing API...
	Creating index.js ...
	Dockerfile created.
	API Created.
	Server definition successfully created.




Both `mn` and `micronode` are valid versions of the command. In this case, we are using the shorthand `mn`. `create-service` is the action we want to run with the `mn` cli tool. The `create-service` command takes two arguments: 
1. a service name (`first-service` in this case) and 
2. An optional path to where to locate the service. The default is the current directory if left blank.

For reference, these are the arguments that are expected by `create-service`

    $ mn create-service [SERVICE_NAME] -d [LOCATION]

After running the above command, you should have the following directory structure where you chose to install.

    first-service/
	    node_modules/
	    api/
		    api.js
		index.js
	    Dockerfile
	    package.json
	    package-lock.json

Let's talk about each of these files in turn.

 1. `index.js` - This is where the definition of your service resides. By naming your server file `index.js` you can simply start your server by running: `$ node first-service`
 2. `Dockerfile` - This is a file that will allow you to create a docker image of your service for easy deployment
 3. `package.json` - This houses any configuration information related to your Node JS project. Each Node project has a package.json.
 4. `api/api.js` - This file houses all of the REST API Routes that your service uses. We'll get more into this later.
 5. `node_modules` - This is where all of your dependencies are installed.
 6. [package-lock.json](https://stackoverflow.com/questions/44297803/what-is-the-role-of-the-package-lock-json#:~:text=the%20npm%20docs:-,package-lock.,regardless%20of%20intermediate%20dependency%20updates.)
## Step Two: Running Our Server
As stated above, we can run our server by running:

    `$ node first-service`

You should see the following output

    first-service Service is listening on Port: 8000

Our service is now ready  to receive REST API requests on [port](https://en.wikipedia.org/wiki/Port_%28computer_networking%29) 8000 on `localhost (i.e your computer)`.

## Step Three: Querying our Service
Now that we have our service running, we can start sending requests to it. But how do we know which types of requests this service accepts? To understand this, we need to inspect our `index.js` and our `api/api.js` files. Let's take a look at the `api/api.js` first.

### api.js
Your `api.js` file should look something like this.
```javascript
const express = require('express');
const router = express.Router();

// Define Routes Here:

// CREATE
router.post("/", (req, res) => {
	const { body } = req;
	res.status(200).send("Response from Post Request");
});

// READ
router.get("/:id", (req, res) => {
	const { id } = req.params;
	res.status(200).send("Getting Data for: " + id);
});

  

// UPDATE
router.put("/:id", (req, res) => {
	const { id } = req.params;
	res.status(200).send("Updating Data for: " + id);
});

// DELETE
router.delete("/:id", (req, res) => {
	const { id } = req.params;
	res.status(200).send("Deleting data for: " + id);
});

module.exports = { router };
```
The `api.js` file simply defines a set of **routes** that are bound to certain **request method types** (i.e GET, POST, PUT, DELETE). Each expressjs request method accepts two parameters. The first parameter is a string denoting the path (url) that this particular method should be bound to. The second parameter is the *function* that should be executed when a request comes in. The *function* parameters are a `req (Request)` object and a `res (Response)` object. The response object is what we send back to a client that is querying our API. Let's take a closer look at the *get* request defined above.

```javascript
router.get("/:id", (req, res) => {
	const { id } = req.params;
	res.status(200).send("Getting Data for: " + id);
});
```
1. The `router.get("/:id", ...)` is saying "define a *get* route with the path "/" that expects a url parameter and name that parameter "id". You would query this url by saying "/10" and the ID in this case would be 10.
2. `(req, res)` are the anonymous function parameters. The expressjs documentation defines what is contained inside of the request and response objects. Generally speaking, the request object contains any information associated with a request (i.e parameters, query key-values, request body, headers, etc.)
3. `const { id } = req.params;` - This line is using destructuring which is javascript concept that allows us to pull out named object fields with the `{}` syntax. The equivalent syntax without destucturing would be `const id = req.params.id;`.
4. `res.status(200).send("Getting Data for: " + id);` - We are using the `response (res)` object to send a response back to the entity that sent a request to this endpoint. We do two things: 1. Set the response status code to OK (200), and we *send* some data. In this case it's a simple string, but in a real-world setting this would be some complex JSON data structure. Now let's look at our `index.js`

### index.js

Your `index.js` should look something like this.

```javascript
const express = require("express");
const app = express(); // creates our application
app.use(express.json()); // parses the body of the requst into json

const { router } = require("./api/api"); // pull in the routes from our api.js file
const port = process.env.PORT || 8000; // pick a port to listen to.
const serviceName = "first-service"

app.use(`/api/${serviceName}`, router); // the path that the API in api.js should be responsible for.

// start our server
app.listen(port, async () => {
	console.log(`${serviceName} Service is listening on Port: ${port}`);
});
```

The key difference with this file when compared to the `api/api.js` file is that we are *not* defining our API routes in the server file. Instead, we have placed them in a separate file and *imported (required)* them in the server file. This is beneficial for maintainability and testing purposes and keeps our `index.js` file lightweight and easy to understand. There are two important statements in this file: 

 1. `app.use("/api/first-service", router)` - We have substituted the templated string for illustrative purposes but basically, our server will use the routes associated with the router (think `api/api.js`) only when a request comes in with the path beginning with `/api/first-service`
 2. `app.listen` is the final statement in this file and it tells our service to start up and listen to whatever port we have defined. In this case, it's `8000`.
 
 Now, to query our API, we can send a simple *get* request to the following `route` using our web browser.

    http://localhost:8000/api/first-service/10

And your response should be the following single line of text:

    Getting Data for: 10

YAY! You've just built and queried your first API! Now, try to query some of the other endpoints using Postman!

## Summary
In this lesson, we created a simple REST API with very little code by using the `micronode-cli`. In reality, you would use `micronode-cli` to build a simple scaffold of your backend service, and then implement the *routes* based on your particular use-case. `nodejs` + `expressjs` make it extremely easy to build and test backend services and I would highly recommend getting familiar with the express documentation going forward.