Introduction to Node.js for beginners- Build a REST API in 10 minutes

Introduction to Node.js for beginners- Build a REST API in 10 minutes

Learn how to write a REST API in Node! Some experience with programming and API development is helpful but not required to follow the examples.

ยท

8 min read

What is Node.js

The easiest way to describe what Node is: something that can run Javascript on your computer. The more correct technical term is that Node is an asynchronous event-driven Javascript runtime. Or simplified: a Javascript engine.

Javascript was originally a programming language running only in your browser. But when Node came around in 2011, it was suddenly possible to run Javascript directly on the computer OS. This made it possible to develop backend systems in Javascript and opened up a whole new world to developers. Frontend developers who wanted to explore backend development could become full-stack developers and backend developers who were tired of Java, PHP and Python could start using Node to build APIs and programs.

Installing Node

The install process depends on your OS and I will not go through installing in detail. Visit the Node homepage and follow the download and install instructions.

To verify that Node and NPM (Node package manager) is installed, open the terminal and check the version by typing node -v and hit Enter, then npm -v and Enter again. The versions will be printed if it's installed. You don't need the exact same version as me to follow along with the examples in this article.

$ node -v
14.0.0

$ npm -v
6.14.4

Node in the terminal

Open your terminal and write node. You now have a Node terminal ready to start programming in. It should look something like this.

$ node
Welcome to Node.js v14.0.0
Type ".help" for more information
>

Let's try something easy first. Type 2+2 and press Enter. Node will calculate the result and print 4.

$ node
Welcome to Node.js v14.0.0
Type ".help" for more information
> 2+2
4

Congratulations! You just wrote your first code in Node. But running Node in the terminal like this is too simple for most use cases. Let's try to write a Node program in a Javascript file and use Node to execute it.

Your first Node program

Make a file called index.js wherever you want on your computer, write the following code and save the file.

const result = 2 + 2;
console.log(result);

Open a terminal in the directory of the file, write node index, and hit Enter. This will tell Node to run your file.

$ node index
4

What happened is that Node read the file and executed the Javascript inside it. Since we used console.log the result (4) was printed in the terminal. Yay!

Node packages and npm packages

When programming in Node you almost always import packages, either from the built-in packages in Node (Node v 14 docs) or by installing external packages using NPM, the Node package manager.

The internal Node packages cover just about everything you need to make programs, such as interacting with the OS, files, and HTTP to name a few. But they are often low level and might require much code and boilerplate to do what you need to.

Since many developers are facing the same problems when making programs, it makes sense that we don't reinvent the wheel every time. Enter NPM packages. NPM is a Node package registry where open-source developers can publish their packages so that their code can be reused. NPM is currently hosting around 1.3 million packages, solving just about every reoccurring problem in programming.

Building your first Node API

As promised, we are going to create a REST API in Node in 10 minutes. To achieve this we need to put some packages from NPM in our toolbox.

Let's start by creating a new NPM project. Create a folder called node-rest or any other name and open a terminal inside it. Type npm init -y. This creates a file named package.json inside your project folder. It should look something like this.

{
  "name": "node-rest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Package.json is a special file that is the heart of every Node project. It holds important metadata about the project such as installed packages and much more.

Let's install some packages from NPM to help us build the API.

npm install express uuid

This command will install two packages in your project, express and uuid. Your package.json now contains metadata about the packages in the dependencies section.

{
  "name": "node-rest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "uuid": "^8.3.2"
  }
}

Create a file named index.js at the root of your project. Enter the following code and save the file.

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello World')
});

const port = 3000;

app.listen(port, () => {
    console.log(`Your REST API is live at port ${port}`);
});

Run the project from the terminal with node index and hit Enter. You will see this message in the terminal if everything is ok.

$ node index
Your REST API is live at port 3000

You now have a fully functioning API with one endpoint running on a simple web server on your machine. Cool! Let's try to hit the endpoint and see what happens.

Open your browser and go to the address http://localhost:3000/. Your browser should show Hello world. You have a response from your API!

Make a complete REST API to store books

Let's make a more useful API for the storage of book data. We are going to create multiple endpoints for CRUD (Create-Read-Update-Delete) operations of the books.

To limit the scope of this article we will not connect to a proper database but rather use an array living in application memory. This means that the stored books will exist only until we stop our API.

Request body validation is also omitted, but you should always validate requests to your APIs in production systems.

We are going to create the following endpoints:

  • POST /books
  • GET /books
  • GET /books/:bookId
  • PUT /books/:bookId
  • DELETE /books/:bookId

Update index.js so it looks like this and start it with node index in the terminal.

// Import packages

// Web application framework
const express = require('express');

// ID generator for book IDs
const generateId = require('uuid').v4;

// Initalize an express app
const app = express();

// Parses JSON request data onto request.body
app.use(express.json()); 

// Simple array to store books while the server is running
let booksDatabase = []; 

// Hello world test endpoint
app.get('/', (req, res) => {
  res.send('Hello World');
});

// Create a new book
app.post('/books', (req, res) => {
    const bookId = generateId();
    let newBook = req.body.book;
    newBook.id = bookId;
    booksDatabase.push(newBook);
    res.send({ book: newBook });
});

// Get all books
app.get('/books', (req, res) => {
    res.send({ books: booksDatabase });
});

// Get a single book by book ID
app.get('/books/:bookId', (req, res) => {
    const book = booksDatabase.find(book => book.id === req.params.bookId);
    if(!book) {
        res.sendStatus(404);
    }
    else {
        res.send({ book });
    }
});

// Update a book by book ID
app.put('/books/:bookId', (req, res) => {
    const bookIndex = booksDatabase.findIndex(book => book.id === req.params.bookId);
    if(bookIndex === -1) {
        res.sendStatus(404);
    }
    else {
        booksDatabase[bookIndex] = { ...booksDatabase[bookIndex], ...req.body.book };
        res.send({ book: booksDatabase[bookIndex] });
    }
});

// Delete a book by book ID
app.delete('/books/:bookId', (req, res) => {
    const bookIndex = booksDatabase.findIndex(book => book.id === req.params.bookId); 
    if(bookIndex === -1) {
        res.sendStatus(404);
    }
    else {
        const deletedBook = booksDatabase.splice(bookIndex, 1);
        res.send({ book: deletedBook });
    }
});

// Which port the server should run on
const port = 3000;

// Start our express web server on the specified port, and print a message on successful startup
app.listen(port, () => {
    console.log(`Your REST API is live at port ${port}`);
});

Your book API is up and running on port 3000! Let's try to use it by sending HTTP requests.

Use the books API with Postman

I will use Postman to send HTTP requests, but you can use any other HTTP client if you want to.

Get all books (GET /books)

postman_get_all_books_empty.PNG

As expected the array of books is empty! Let's create a book.

Create a book (POST /books)

postman_post_book.PNG

The API returned HTTP 200 OK and the newly created book object. Seems everything was ok, but let's check by fetching the newly created book by its book id.

Get a single book (GET /books/:bookId)

Remember to replace the book ID with your exact book id.

postman_get_book_by_id_1.PNG

Get all books again (GET /books)

postman_get_all_books_1.PNG

Our book is returned in the array as expected.

Update a book (PUT /books/:bookId)

Send a request to update the title of the book.

postman_put_book_1.PNG

As you can see the returned book object has the new title.

Delete the book (DELETE /books/:bookId)

postman_delete_book_1.PNG

The API returned 200 OK and the deleted book object. Now if we try to get the book again by id we should get a HTTP 404 Not Found.

postman_get_book_notfound.PNG

Seems like the API works as expected! You have just developed your first CRUD REST API in Node!

Next steps

You can play around with the API to learn more about how it works. If you want to expand your knowledge try to implement new features such as:

  • PATCH /books/:bookId to update a single field on the book without sending the whole book
  • Request validation. Try Joi or another NPM package.
  • Replace the books array with a real database like MongoDB or Postgres.
ย