Building a Node.js REST API
Tags: node, rest, express, tutorial
Published: 2021-08-04 05:29:20

This article is the first of a series outlining the steps to build a REST API from scratch that runs in Node.js using the Express web application framework. In this article, we will show how to set up the project. The following articles will build on this by adding features such as request / response validation and a Swagger UI page for online documentation.

## Project setup
The configuration needed for following along in your own project is minimal. All that is required to get started is a *package.json* file generated using `npm init`.

*Ensure that `"type": "module"` is set within the package.json file. This declares our package as an ES 6 module so we can use `import` syntax to import packages in our source code.*

## Add a basic web server
Add the Express package as a run-time dependency:
```
npm install --save express
```
Then create a new file *server.js* in a folder named *src* with the following contents:
{% gist https://gist.github.com/bhaeussermann/93af5b6fe49f5dd8427a35c681c801cd %}

And just like that we have a working web endpoint listening at port 3000!

In the code above, we have defined a single route which we can use to test that the service is running.

Testing that our endpoint works is easy as:
1. Run node `src/server.js`
1. Using your favourite REST API testing tool (I recommend [Postman](https://www.postman.com/downloads/)), request GET `localhost:3000/greeting`

We should get a 200-response containing some text as a JSON string.

## Adding automatic restarts

Running our server script as above means that whenever a change is made to a source file, we need to manually stop and start the program for the changes to take effect. This is easy to fix, thanks to a simple tool called *nodemon*. We can easily add a script that will restart our application whenever a source file is changed.

First, we add *nodemon* as a development dependency to the project:
```
npm install --save-dev nodemon
```

We then define the following set of scripts in *package.json*:

```
"scripts": {
  "run": "node src/server.js",
  "run:watch": "nodemon src/server.js --watch src",
  "start": "npm run run:watch"
},
```

The *run* script will run the API without automatic restarts as before if we execute `npm run run`

The *run:watch* script will run the API, restarting it whenever any file inside the *src* folder changes.

The *start* script will simply run the *run:watch* script but can be executed merely as `npm start`

## Structuring the code based on REST resources

Most REST APIs have their routes arranged based on a number of resources. We will define *employees* as a REST resource with CRUD (create, retrieve, update, delete) operations. Keeping with REST conventions, we will define the following routes:

- GET `/employees`: Return the list of all employees.
- GET `/employees/{employee-id}`: Gets the single employee having the ID `{employee-id}`. Return a 404 (Not Found) response code if no employee with the specified ID was found.
- POST `/employees`: Add a new employee entry.
- PUT `/employees/{employee-id}`: Update the details of the employee having the ID `{employee-id}`.
- DELETE `/employees/{employee-id}`: Delete the employee having the ID `{employee-id}`.

If we keep on defining all our routes and the code implementing them directly in *server.js*, the code will quickly become unmanageable. To help keep the code organized, I recommend defining each REST resource's routes in one file and implementing them in another. We call the file defining the routes the "controller" and the file containing the implementation the "service".

Implementing the *employees* resource leads to the following folder structure:

```
src
   controllers
      employees-controller.js
   services
      employees-service.js
   server.js
```

Here is a simple implementation of *employees-service.js*.

*Whereas in a typical application the objects would be persisted in some kind of a database, we store the list of employees in memory for simplicity's sake.*

{% gist https://gist.github.com/bhaeussermann/95f2a6c6f22ad3158521e89a53e7a6e9 %}

The `EmployeeNotFoundError` class is defined in a file named *employee-not-found-error.js* as:

{% gist https://gist.github.com/bhaeussermann/06c216498203de84255154d65b930232 %}

Note that `EmployeesService` does not contain any logic that relates to REST notions like query parameters, response statuses etc. The `EmployeesService` is concerned solely with the details of how employees are persisted. This is in adherence to the [Single-responsibility principle](https://en.wikipedia.org/wiki/Single-responsibility_principle). It also makes the class easier to test using some testing framework.

The `EmployeesController` class deals with the REST-related  specifics and hooks up the REST routes to their respective implementations in the *employees* service:

{% gist https://gist.github.com/bhaeussermann/24e10105a9c12cd72688bd5793e4f08d %}

Note the block-comment before the `registerRoutes()` method. This is a [JSDoc](https://jsdoc.app/) comment that specifies descriptions to use when generating documentation using JSDoc. However, in this case, we add the block-comment only to inform our IDE of the expected types of the method's parameters. Visual Studio Code, for instance, has built-in support for JSDoc and will interpret the type-declarations of the `app` and `controller` parameters inside the block-comment to inform its IntelliSense and code completion functionality.

We define the `ExpressError` class to represent a REST error which is to be handled by a generic error route handler function in *server.js*:

{% gist https://gist.github.com/bhaeussermann/429ecf3f795c68da8d2937163aed28ab %}

Finally, we make the following changes to *server.js*:
1. To register the routes, we now simply call `registerRoutes()` passing in the Express application and a new instance of `EmployeesService`.
1. We also add a route handler for returning the proper response when an error is thrown.
1. To parse the request body of the POST and PUT operations as JSON payloads, we add the statement `app.use(express.json())`

{% gist https://gist.github.com/bhaeussermann/614cf45fbaedba4c6929158f56e35ef2 %}

We can now use our favourite REST client to test the different routes to verify the behaviour is as expected:

1. *Get all employees*

        GET localhost:3000/employees

1. *Get employee 1*

        GET localhost:3000/employees/1

1. *Get employee 2 (doesn't exist)*

        GET localhost:3000/employees/2

1. *Update employee 1's first name*

        PUT localhost:3000/employees/1
        {
          "firstName": "André"
        }

1. *Add a new employee*

        POST localhost:3000/employees
        {
          "lastName": "King",
          "firstName": "Robert",
          "title": "Sales Representative"
        }

1. *Delete employee*

        DELETE localhost:3000/employees/2

## In conclusion

Getting a REST API off the ground using Node.js and Express is relatively straightforward to do, and by defining separate controller and service classes for each type of API resource, we keep the REST-specific details separate from the underlying implementation details of each operation.

Future posts will show how we can quickly add middleware such as request / response validation and Swagger documentation thanks to Node.js packages that are available for this.

*The code for the API developed in this article is available on GitHub [here](https://github.com/bhaeussermann/node-js-rest-api).*