Let's build a backend api like bit.ly using node js

Kumar Kalyan - Dec 12 '22 - - Dev Community

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 and login to your dashboard

    image

  • 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

    image

    next click on Add Current IP Address

    image

  • Next click on Build a Database and after that select a shared cluster

    image

  • Choose your prefered cloud provider and click on create cluster

    image

  • Next set up a username and password

    image

  • Now move to the database tab and click on connect

    image

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

image

Setup the nodejs app

  • Folder structure

    image

  • 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
//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}`);
});
Enter fullscreen mode Exit fullscreen mode

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

    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.

    require('dotenv').config();
    const dbUrl = process.env.DB_URI;
    const port = process.env.PORT || 3000;
    
  • Setup the .env file and paste your secrets there

PORT=3000
DB_URI=mongodb+srv://<username>:<password>@cluster0.hjcrjts.mongodb.net/?retryWrites=true&w=majority
Enter fullscreen mode Exit fullscreen mode
  • 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

    const mongoose = require('mongoose');
    

    now add the following piece of code to define a schema, and model and connect the database with our server.

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);
Enter fullscreen mode Exit fullscreen mode

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
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')
      }
    }

  }
});
Enter fullscreen mode Exit fullscreen mode

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

    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

    //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

  • Let's try out an invalid URL and see what it returns

    image

    see it returns an error saying invalid URL

  • GET a URL

    use http://localhost:3000/api/shorturl/6 in your browser and you will be redirected

    image

  • Get all URLs

    simply search for http://localhost:3000/api/urls using a browser and you get all the available URLs inside our database.

    image

    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 :)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .