Let's build a backend api like bit.ly using node js
Tags: node, webdev, mongodb, tutorial
Published: 2022-12-12 18:15:56

## Introduction

These days short links are used by almost everyone, developers, creators businesses and even working professionals, and there are popular tools like bit.ly, buff.ly, etc already available in the market. But have you ever wondered why it is very much easy to build a similar service like that? In this article, I will explain how you can easily integrate a short URL service to a node js project and that too within 100 lines of code.

Before I start explaining let me first tell you about the prerequisites.

*   Node js installed in your machine
    
*   Any code editor of your choice, I am using vs code
    
*   Tools like postman or insomnia for testing the API
    
*   Knowledge of nodejs callbacks, MongoDB
    

## Tech stack we are using

*   Nodejs for writing server-side code
    
*   MongoDB Atlas as a database
    
*   Node package Manager but one can use yarn too
    

## MongoDB setup

*   Head over to [mongodb.com](https://www.mongodb.com/home) and login to your dashboard
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670693612045/Fl5FEmsM5.png )
    
*   Move to the projects tab inside the organization(make sure to create one if you don't have one ) and click on the new project
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694097248/QJ-RFwQYO.png )
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694140275/-RwP8pvLz.png )
    
    next click on `Add Current IP Address`
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694181746/v4_ShgeV1.png )
    
*   Next click on `Build a Database` and after that select a shared cluster
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694297562/f8OXuMlfX.png )
    
*   Choose your prefered cloud provider and click on `create cluster`
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694365171/xHxL3H_gk.png )
    
*   Next set up a username and password
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694450297/kdbiiPB83.png )
    
*   Now move to the database tab and click on `connect`
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694674389/iFmbKRlLx.png )
    

Now click on connect your application grab the connection string for node js driver and save it for later use

![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670694812527/hSjt6EcAS.png )

## Setup the nodejs app

*   Folder structure
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670695059724/jV2L5oQap.png )
    
*   Now quickly open up the terminal in the root directory and install the dependencies using the command
    

`npm install body-parser cors dotenv express mongoose mongodb valid-url`

*   Now open the server.js file and set up an express server using the piece of code
    

```javascript
//set up an experss server
const express = require('express');
const app = express();
const port = 3000;
app.listen(port, function () {
  console.log(`Listening on port ${port}`);
});
```

Here we are setting up an express server using the `app` variable and `express()` function and setting a port address to 3000 using `app.listen()` so that our server can listen to http://localhost:3000/.

This piece of code will only set up a server but to build an API we need to create some requests will I will discuss later in this article first let us import some other important modules which we will use to build our API

*   Let's setup `body-parser`
    
    body-parser is an npm package which allows you to access the request body in simple words to build this API we need to receive the URL from the user and this will be delivered to our server through a post request to get access to the requested data we will use body-parser. Use the piece of code to set up `body-parser`
    
    ```javascript
    var bodyParser = require('body-parser');
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    ```
    
*   Now it's time to connect our database before we start building the requests. Here comes the concept of environment variables using the `dotenv` npm package and & a `.env` we can store our secrets from others. First, let's configure dotenv in our `server.js` . Using `process.env` we can access our environment variables.
    
    ```javascript
    require('dotenv').config();
    const dbUrl = process.env.DB_URI;
    const port = process.env.PORT || 3000;
    ```
    
*   Setup the `.env` file and paste your secrets there
    

```yaml
PORT=3000
DB_URI=mongodb+srv://<username>:<password>@cluster0.hjcrjts.mongodb.net/?retryWrites=true&w=majority
```

*   Let's write a Schema for creating a MongoDB model to store the URLs and also connect our server to MongoDB Atlas. A schema is a blueprint of what kind of data we want to store in our database, whether it's a string or an array or an integer, etc. Based on this schema a model will be generated and used so that we can perform our database operations. Keep in mind that to design a schema or model or to perform any sort of MongoDB operations we are using an npm package named `mongoose` can and to create an instance of a mongoose package use
    
    ```javascript
    const mongoose = require('mongoose');
    ```
    
    now add the following piece of code to define a schema, and model and connect the database with our server.
    

```javascript
mongoose.connect(dbUrl, { useNewUrlParser: true }).then(() => { console.log('connected to the database') },
  err => { console.log(err) })
const { Schema } = mongoose;
const urlSchema = new Schema({
  original_url: { type: String, required: true },
  short_url: String,
});
const urlSch = mongoose.model("urlsStore", urlSchema);
```

So we are storing two fields in our database one is the `original_url` and another is `short_url`

*   Let's write the first API request to store URLs and create new short URLs
    

```javascript
var validUrl = require('valid-url');
app.post('/api/shorturl', async (req, res) => {
  let url = req.body.url;
    //Checks weather a URL is valid or not 
  if (!validUrl.isHttpsUri(url)) {
    res.json({ "error": 'invalid url' });
  }
  else {
    try {
        //checks Given URL is already present the database
      let URL = await urlSch.findOne({ original_url: url });
      if (URL) {
        res.json({ 'original_url': URL.original_url, 'short_url': URL.short_url });
      }
      else {
        var query = urlSch.find();
        query.count((err, count) => {
          const URL = new urlSch({
            original_url: url,
            short_url: count + 1,
          });
          URL.save().then((URL) => {

            res.json({ 'original_url': URL.original_url, 'short_url': findOne.short_url })
          })
        })

      }
    }
    catch (err) {
      if (err) {
        console.log(err);
        res.status(500).json('server error')
      }
    }

  }
});
```

All we are doing here is grabbing the URL from the `request.body` and storing inside the variable `url` after that check for its validity using an npm package `valid-URL` , then we are checking to if the URL is already available in our database using the `findOne()` the method by passing the URL as a query parameter or not lastly if all the checks are passed then we are adding up the given URL to our database and sending the short URL as a JSON response. The logic behind generating the short URL is very simple we are first counting the total number of URLs present in our Database and storing it to a count variable then we are assigning the short\_url with `count+1` this means the 1st URL will be `someurl/1` and so on.

*   Now let's create a request for redirecting the users using the short URL
    
    ```javascript
    app.get('/api/shorturl/:short_url', async (req, res) => {
      let url = req.params.short_url;
      let already = await urlSch.findOne({ short_url: url }).exec();
      try {
    
        if (already) {
          res.redirect(already.original_url);
        }
        else {
          res.json({ error: 'invalid url' })
        }
      }
      catch (err) {
        if (err) {
          console.log(err);
          res.status(501).json({ error: 'invalid url' });
        }
      }
    })
    ```
    
    There were grab the URL from the parameter and check for its presence inside our database if it exists then we are redirecting our users to the link using the `res.redirect()`
    
*   Now let's write the code for fetching all the list of URLs present in our database
    
    ```javascript
    //get all URLs
    app.get('/api/urls', async (req, res) => {
      try {
        let urls = await urlSch.find({}).exec();
        res.json(urls);
      }
      catch (err) {
        console.log(err);
      }
    })
    ```
    
    Here we are using the `find()` the method in MongoDB and passing an `{}` inside it to get all the data inside the `urlSch` model and lastly returning a JSON object containing all the URLs inside our database.
    

## Start the server and see the results

use `node server.js` to start the server and test the API in postman

*   Creating a `POST` and passing a `url` parameter through the request body we are sending our server a `URL` and after processing this returns me a valid link and the shorturl id.
    

![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670698038546/S22mGzaqu.png )

*   Let's try out an invalid URL and see what it returns
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670764783207/B2lF02P5v.png )
    
    see it returns an error saying invalid URL
    
*   GET a URL
    
    use [http://localhost:3000/api/shorturl](http://localhost:3000/api/shorturl)/6 in your browser and you will be redirected
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670698337672/FAMDGZ3ot.png )
    
*   Get all URLs
    
    simply search for [http://localhost:3000/api/urls](http://localhost:3000/api/urls) using a browser and you get all the available URLs inside our database.
    
    ![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1670698496779/1wfB7ZWFA.png )
    
    ## Conclusion
    
    Ok, now we have reached the end make sure to share this article with friends and peers and make sure to hit a reaction. Follow Documatic and stay tuned for other amazing articles :)