How To Create A REST Api With Express JS

Introduction

Hey there! Today I’m going to walk you through the process of creating a REST API with Express JS. REST APIs have become an essential part of modern web and mobile app development, and they allow us to build efficient and scalable backends for our applications.

Express JS is a powerful Node.js framework that makes building REST APIs easy and intuitive. In this article, I’ll guide you through the process of setting up your development environment, building your REST API, adding authentication, integrating with a database, testing your API, and deploying it to a production environment.

So, grab a cup of coffee, sit back, and let’s get started.

Setting Up The Development Environment

Before we start building our REST API, we need to set up our development environment. First, we need to make sure to have Node.js and NPM installed on our computer. If you don’t have them already, you can download them from the official website.

Once you have installed Node.js and NPM, we can proceed to install the Express JS framework. We can do this by running the following command in our terminal:

npm install express

This will install the latest version of Express JS in your project directory. Now that we have installed Express JS, we can create a new project directory where we will build our REST API. We can create a new directory by running the following command:

mkdir my-rest-api

We can navigate to our new project directory by running the following command:

cd my-rest-api

Building The REST API

Now that we have set up our development environment, we can start building our REST API. In Express JS, we can create routes for our API by using the express.Router() method. This method allows us to create a new instance of a router and define our routes on it.

Let’s create a new file called routes.js in our project directory where we will define our routes:

const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.json({ message: 'Hello World!' });
});

module.exports = router;

In this code snippet, we have imported the Express JS framework and created a new instance of a router. We have defined a GET route on the root / path of our API, which returns a JSON object with a message property.

Now that we have defined our routes, we can use them in our main Express JS application. Let’s create a new file called app.js in our project directory where we will define our main application:

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

const routes = require('./routes');

app.use('/', routes);

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

In this code snippet, we have created a new instance of an Express JS application and imported our routes from routes.js. We have used the app.use() method to use our routes on the root path of our application. Finally, we have defined a port number on which our application will run.

Now we can run our application by running the following command in our terminal:

node app.js

This will start our server on http://localhost:3000, and we can test our API by navigating to that URL in our web browser. We should see our “Hello World!” message displayed on the page.

Implementing Authentication

Now that we have built a basic REST API, let’s add some authentication to it. We have different options when it comes to implementing authentication in our Express JS application, but we’ll use JSON Web Tokens (JWT) in this tutorial.

JSON Web Tokens are a secure way to authenticate users in our API. They are particularly useful for building stateless backends that can scale easily and don’t rely on session data.

To use JWT in our Express JS application, we first need to install the jsonwebtoken package. We can do this by running the following command in our terminal:

npm install jsonwebtoken

Once we have installed the package, we can use it to generate and verify JWT tokens. Let’s create a new file called auth.js in our project directory where we will define our authentication logic:

const jwt = require('jsonwebtoken');

const secret = 'mysecretkey';

function generateToken(user) {
  const payload = {
    sub: user.id,
    name: user.name,
    email: user.email,
  };

  const token = jwt.sign(payload, secret, { expiresIn: '1h' });

  return token;
}

function verifyToken(token) {
  try {
    const payload = jwt.verify(token, secret);
    return payload;
  } catch (error) {
    return null;
  }
}

module.exports = {
  generateToken,
  verifyToken,
};

In this code snippet, we have imported the jsonwebtoken package and defined a secret key that will be used to sign our tokens. We have created two functions: generateToken() and verifyToken().

The generateToken() function takes a user object as an argument and generates a JWT token with the user’s data in the payload. The token is signed using our secret key and set to expire after one hour.

The verifyToken() function takes a token as an argument and verifies its authenticity using our secret key. If the token is valid, it returns the payload data. If the token is invalid or expired, it returns null.

Now we can use our authentication logic in our API routes. Let’s modify our routes.js file to add a new authentication route:

const express = require('express');
const router = express.Router();

const auth = require('./auth');

router.post('/login', (req, res) => {
  const { email, password } = req.body;

  // Authenticate user
  const user = { id: 1, name: 'John Doe', email: '[email protected]' };
  const token = auth.generateToken(user);

  res.json({ user, token });
});

router.get('/profile', (req, res) => {
  const token = req.headers.authorization.split(' ')[1];
  const payload = auth.verifyToken(token);

  if (!payload) {
    res.status(401).json({ message: 'Unauthorized' });
  } else {
    res.json({ user: payload });
  }
});

module.exports = router;

In this code snippet, we have added two new routes: /login

and /profile. The /login route takes a user’s email and password as parameters and generates a JWT token using our generateToken() function. We have hardcoded a user object for simplicity, but in a real application, we would authenticate the user using a database or another authentication method.

The /profile route is protected by authentication middleware. When a user requests this URL, the middleware checks for a valid JWT token in the request headers. If the token is valid, it returns the user’s payload data. If the token is invalid or expired, it returns an error message.

Now that we have added authentication to our API, we can test it using Postman or another API testing tool. We can simulate a login request by sending a POST request to http://localhost:3000/login with a JSON payload containing the user’s email and password. The API will respond with a user object and a JWT token.

We can then use the token to access the protected /profile route by sending a GET request to http://localhost:3000/profile with an Authorization header containing the token. The API will respond with the user’s payload data.

Adding Database Integration

Now that we have added authentication to our API, let’s integrate it with a database. We’ll use MongoDB as our database and the Mongoose library to interact with it.

To use Mongoose in our Express JS application, we first need to install the mongoose package. We can do this by running the following command in our terminal:

npm install mongoose

Once we have installed the package, we can connect to our MongoDB database using Mongoose. Let’s create a new file called db.js in our project directory where we will define our database connection:

const mongoose = require('mongoose');

const url = 'mongodb://localhost/mydatabase';

mongoose.connect(url, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log('Database connected');
});

In this code snippet, we have imported the mongoose package and defined the URL of our MongoDB database. We have used the mongoose.connect() method to connect to the database and set some options to ensure Mongoose uses the latest URL parser and unified topology engine.

We have also defined event listeners for the error and open events of our database connection. If the connection encounters an error, we log it to the console. If the connection is successful, we log a message to the console.

Now that we have connected to our MongoDB database, we can define a schema for our user objects. Let’s create a new file called user.js in our project directory where we will define our user schema:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
});

const userModel = mongoose.model('User', userSchema);

module.exports = userModel;

In this code snippet, we have created a new Mongoose schema for our user objects. The schema defines three fields: name, email, and password. The required property is set to true for all fields to ensure they are present when we save the user object to the database. The email field is also set to unique to ensure that each user has a unique email address.

We have then defined a Mongoose model for our schema and exported it.

Now that we have defined our user schema, let’s modify our auth.js file to use the Mongoose model to authenticate users:

const userModel = require('./user');

// ...

router.post('/login', async (req, res) => {
  const { email, password } = req.body;

  // Authenticate user
  const user = await userModel.findOne({ email, password });

  if (!user) {
    res.status(401).json({ message: 'Unauthorized' });
  } else {
    const token = auth.generateToken(user);
    res.json({ user, token });
  }
});

// ...

In this modified code snippet, we have imported our user model and used the findOne() method to find a user object with the given email and password. If the user is not found, we return an error message. If the user is found, we generate a JWT token and return the user object and token.

We have also added the async keyword to our route function and awaited the findOne() method to make sure it returns a Promise.

Finally, let’s modify our routes.js file to save and retrieve user objects from our MongoDB database:

const express = require('express');
const router = express.Router();

const auth = require('./auth');
const userModel = require('./user');

router.post('/signup', async (req, res) => {
  const { name, email, password } = req.body;

  try {
    const user = new userModel({ name, email, password });
    await user.save();
    res.json({ message: 'User created' });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

// ...

router.get('/users', async (req, res) => {
  const users = await userModel.find({});
  res.json(users);
});

module.exports = router;

In this code snippet, we have added a new /signup route that creates a new user object and saves it to the database using the save() method. We have also added a new /users route that retrieves all user objects from the database using the find() method.

We have wrapped our route functions inside a try-catch block to handle potential errors. If an error occurs while creating or retrieving user objects, we return an error message with a 500 status code.

Testing The REST API

Now that we have built our REST API and integrated it with a database, let’s test it. We can use Postman or another API testing tool to send requests to our API and see how it responds.

For example, we can send a POST request to http://localhost:3000/signup with a JSON payload containing a new user’s name, email, and password. The API will create a new user object in the database and return a “User created” message.

We can then send a POST request to http://localhost:3000/login with the same email and password to generate a JWT token. The API will return the user object and token.

We can use the token to access the protected /profile route by sending a GET request to http://localhost:3000/profile with an Authorization header containing the token. The API will return the user’s payload data.

We can also send a GET request to http://localhost:3000/users to retrieve all user objects from the database. The API will return an array of user objects.

Conclusion

In this article, we have learned how to create a REST API with Express JS. We have covered the basics of creating routes, handling requests, and sending responses. We have also added authentication and database integration to our API.

By following the steps outlined in this article, you should now have a working REST API that you can use to build web and mobile applications. You can further customize your API by adding more routes, middleware functions, and integrating with other third-party services.

I hope you found this article helpful. Happy coding!

JIRA Cloud Api
REST Apis

JIRA Cloud Api

Introduction As a project manager, I understand the importance of using tools and technology to streamline workflows and increase productivity. That’s why I want to share my experience using Jira Cloud API, a powerful tool for customizing, automating, and integrating Jira Cloud with other applications. In this article, I’ll introduce you to Jira Cloud API […]

How To Use The Cyberark Rest Api
REST Apis

How To Use The Cyberark Rest Api

Introduction: CyberArk REST API is one of the most powerful tools in the CyberArk suite of products. This API allows for seamless integration with third-party applications, making it possible to deploy automated processes that can help organizations reduce the risks associated with managing privileged accounts and passwords. As a software developer, I have personally experienced […]

How To Use GitHub REST Api
REST Apis

How To Use GitHub REST Api

As a software developer, I know the importance of version control and keeping track of changes to code. That’s why I was thrilled when I first discovered Github API. Github API is a powerful tool used by developers to access and manipulate data within Github repositories. In this article, I’ll take a deep dive into […]