URL shortener in 5 minutes

About

URL shortener is a service that can conver long URL into much shorter URL.
This can be very useful for contexts where message size matters. For example - tweets has message limit.
There are many URL shorteners on the market. But do you know how they work?
In this mini-project we'll focus on core functionality - generate short URL and redirect to original URL.
We will use the following technologies: node.js, express and MongoDB (plus a bit of Docker).

Link to Wikipedia: https://en.wikipedia.org/wiki/URL_shortening

Live coding

Here is a live coding session that shows how it can be done.

Duration: 5:34 (coding - 4:59)

Disclaimer: never use this code in production. It was created for fun.

Breakdown

Let's break down the solution and comment on some complex or interesting things.

0:30 - initialization of the project. As we are using node.js the initialization is done using npm init -y. It creates minimalistic package.json file in current folder.
Also right away instailling express - it will be used as web server framework.

0:43 - create server skeleton, basically initializing express and listening on port 80. Port 80 is the default one for HTTP protocol and it can be used in browser without explicitly defining the port. It will be helpful in the end of the project during end-to-end demo.

0:58 - define the API skeleton. We will need 2 operations:

Note that both endpoints will have /r prefix. "r" stands for "redirect".
In the end the API can be used like this:
Create short URL: curl -X POST -d https://www.5minsofcode.com http://localhost/r
Redirect using short URL: curl -L http://localhost/r/XYZ1234

1:10 - we need to store the mapping between short URL and real URL somewhere. Persistent storage is required. There are multiple options for free storages. Maybe the most natural choice would be Redis - it is a key-value storage that fits nicely (key is short URL code and value is original URL).
However let's use MongoDB here. It is a document-oriented NoSQL database that integrates nicely with node.js based applications.
First of all we need to install mongodb package - it is a client for MongoDB.
Next question - where to host the database. One of the options is to use some cloud hosting, for example MongoDB Atlas provides a free tier.
Or alternatively we can use local installation. I run it using Docker via the following command:
docker run -p 27017:27017 mongo
It starts a new instance and exposes port 27017 (this is standard MongoDB port) that we'll connect to.

1:44 - create MongoDB client. We need to specify connection URL and collection name (it will be created automatically).
Note here that we are using initialization in async block. Reason for it is that in connection open operation is asynchronous therefore the whole function should be also marked as async.
Refer to Mozilla documentation for details about async functions in JavaScript.

2:10 - next step is to implement how we can shorten the URL. My strategy will be very simple - generate random string and use it the key for original URL.
How many URLs can we code this way? Let's calculate. Imagine we will use the following set: [a-zA-Z0-9] (in total 62 characters). If we take 7 characters long code it will give us around 3.5 trillion distinct values. I think it is more than enough.
To make our life a bit easier we can reuse existing module randomstring that has great flexibility for configuring how our random string will look like. However for us default configuration is good enough.
Once module is installed we can add it to the project.

2:30 - implement logics for short URL generation. This process has several steps:

Important - we exprect that the request body contains just original URL. That's why we need app.use(express.text({type: '*/*'}));. This command instructs express that it should parse POST request body and for every content type (*/*) it should be treated as just plain text.
This implementation does not check for generated random strings collisions (i.e. it can potentially generate the code that was already generated). But taking into account the number of possible random strings this probability is very low.

2:50 - implement redirect to original URL based on short URL.
Here the implementation is very simple. We take code path parameter from the URL and try to lookup corresponding document from MongoDB.
Also here we cutting the corner and not handling the case when such code is not found. In this case the API should return status code 404 (not found). Leaving it up to you as homework.
Notice that we do res.redirect(result.url); that will issue 302 (found) HTTP response code and Location response header containing the redirect URL. All the rest will be handled by the browser.

3:06 - the last bit of server-side implemenation - allowing express to serve static content.
Our solution will have second part - simple HTML page for the user - and we want to use the existing web server to serve it.
At this point in time our server is ready and we can start it.

3:19 - starting to work on HTML page that will be visible to the user.
Our design will be very simple and minimalistic. In general there will be 3 components on the screen:

3:45 - in this project we will use jquery library for one task that we will need a bit later.
We will need to call API on the server. Of course it all can be done using JavaScript XMLHTTPRequest object, but with jquery it looks better.
Importing jquery script from CDN (content delivery network).

3:54 - implementing shorten function. It will do the following:

Actually most of operations with DOM also could have been done using jquery instead of document.getElementById
Lastly don't forget to adjust our button to call shorten function when the button is clicked.

4:50 - now it's time for demo. To make it more interesting and simulate how it work with real domain name I've made a configuration on my local machine (it's Unix-based, but I think the same can be applied for Windows as well).
Unix-based machines have /etc/hosts file that is used by operating system to translate hostnames to IP addresses.
I included the following line there: 127.0.0.1 sho.rt
This line instructs my OS to use 127.0.0.1 IP address when resolving sho.rt hostname. As result when opening http://sho.rt in the browser it will serve content from 127.0.0.1.
Also remember that our express server was running on port 80 - this also gives us nice URL without port.

5:01 - demo time - let's open http://sho.rt in browser and try to shorten some URL, for example https://www.5minsofcode.com.
Much shorter short URL will be generated and if we try to open it new browser window it will lead us to https://www.5minsofcode.com.

This concludes this mini-project. It can be extended further with following features:

Resources

Sources: https://github.com/5minute/examples/tree/main/url_shortener