loading...

Discussion on: How to build a URL Shortener like bitly or shorturl using Node.js

Collapse
eruizdechavez profile image
Erick Ruiz de Chavez

This is a nice example of a custom URL shortener. I myself have my own version in a php script (although completely different implementation).

I hope you don't mind if I leave some feedback here, as I think it would help you improve it.


Instead of using a config file, I suggest you to use environment variables. You can easily create default values, and override them on the fly with a start script, or something like dotenv.

In your index file you could do something like this:

const config =  {
    mongoURI: process.env.SHORTENER_MONGO_URI,
    baseURL: process.env.SHORTENER_BASE_URL,
    allowedClick: process.env.SHORTENER_ALLOWED_CLICK,
};

I think it would be better to validate the config below when the server starts, instead of waiting for a user to attempt to do something on the server to catch this error.

if(!validUrl.isUri(baseUrl)){
    return res.status(401).json("Internal error. Please come back later.");
}

Wrapping all your code inside an if is harder to read. It is considered a good practice to fail fast so you avoid unnecessary nesting.

Instead of this:

 if(validUrl.isUri(longUrl)){
// …
else{
    res.status(400).json("Invalid URL. Please enter a vlaid url for shortening.");
} 

You could do this:

if(!validUrl.isUri(longUrl)){
    return res.status(400).json("Invalid URL. Please enter a vlaid url for shortening.");
} 
// …

Users do not need to know your internal implementation details. Hide them by just returning what they need on their response:

Instead of returning this:

{
    "_id": "5eec662da11d145bd0be75da",
    "longUrl": "https://www.amazon.in/gp/product/B085VTLD43?pf_rd_r=MV8SV74D900FNTWRWSMT&pf_rd_p=649eac15-05ce-45c0-86ac-3e413b8ba3d4",
    "shortUrl": "http://localhost:8000/v1/bxd5-mqVB",
    "urlCode": "bxd5-mqVB",
    "clickCount": 0,
    "__v": 0
}

You could return this:

{
    "longUrl": "https://www.amazon.in/gp/product/B085VTLD43?pf_rd_r=MV8SV74D900FNTWRWSMT&pf_rd_p=649eac15-05ce-45c0-86ac-3e413b8ba3d4",
    "shortUrl": "http://localhost:8000/v1/bxd5-mqVB",
    "urlCode": "bxd5-mqVB",
    "clickCount": 0,
}

In your get handler, the user does not need to wait for the click count update to be redirected. You should respond to the user as soon as you can and let node do anything else after the user is well gone.

Instead of this:

await url.update({ clickCount });
return res.redirect(url.longUrl);

You could do this:

res.redirect(url.longUrl);
return url.update({ clickCount });

Last but not least, if you want to further optimize this specific example, you could remove Express and use Node's builtin http server; that would reduce a lot or dependencies you are not using at all. Another good option is to use restify which is pretty similar to Express but with less dependencies and focused on API development and not full fledged web apps.

Collapse
sachinsarawgi profile image
Sachin Sarawgi Author

Hi Erick that's a lot of valuable suggestions....I didn't know how to do env var thing in NodeJS.....but now I am surely going to use it.
Thanks for the guidance.

Collapse
eruizdechavez profile image
Erick Ruiz de Chavez

I use it a lot and it is very portable, specially when deploying your code to Docker images, or cloud services. I also use dotenv for my local development and I do not even need to include it in my source code; I just install dotenv as a devDependency and then start my local server with node -r dotenv/config myfile.js, that -r automatically requires your module.

github.com/motdotla/dotenv#preload

Thread Thread
sachinsarawgi profile image
Sachin Sarawgi Author

Thanks for mentioning the required steps.... I will update the code