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
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.
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:
code
parameter will be used here/r
prefix. "r" stands for "redirect".
curl -X POST -d https://www.5minsofcode.com http://localhost/r
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:
randomstring
moduleapp.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.
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:
document.getElementById('input')
$.ajax
code
as part of payload and we need to form a short URL with it. For this purpose we are utilizing window.location.origin
- it will return hostname of the sitejquery
instead of document.getElementById
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:
Sources: https://github.com/5minute/examples/tree/main/url_shortener