This is a URL_Shortener app.
Front-end: React, Ant-design
Back-end: Django
Database: Sqllite3
Deployment: Docker
You can find the demo of the app in this YouTube video.
- Django contains a secret key that usually is hidden using
.env
variables. Each developer in the team should individually set up.env
file and MUST NOT upload it to the GitHub. However, for this project and for the simplicity, this secret key is exposed to GitHub. Therefore, you can run the server. - To deploy front-end, we should deploy the
build
version since it is faster and lighter. I've assumed I can deploy the front-end usingdev
resources. - The database should not be uploaded to GitHub as it might contain users' sensitive information. However, this project doesn't contain any sensitive data (only long url and short url is stored). Threfore, we can assume that we can upload database to GitHub.
Each long url requires a unique key associated to it.
Q: The natural question is how we can generate this key and make sure it is unique?
A: When a pair of (long url,short url) is added to the database, a unique identifier named as id
is assigned to the entry. id
is also a default primary key. We can leverage this value to generate the unique key for each long url.
To generate the unique key, we can use Base62. As you may know, +
and /
are reserved characters in URL. Base62 is considered as a safe way to generate unique key for short URL since Base62 doesn't produce +
or /
.
unique_key = base62(id)
short_url = "localhost:3000/" + unique_key
Each entry in the database is somehow a tuple.
# entry to be stored in database
entry = (id, long_url, unique_key)
let's see how many urls the database can store using the base62 approach.
The number of carachters for the SMS is limited to 67. We know that 15 out of 67 chars are occupied by the domain (domain is localhost:3000/
according to the assumptions). So, we have 52 characters available for the unique key.
Since we are working with base62, the last item in the database (after that, the database is full) has a unique key with the size of 52 chars.
The largest number with the size of 52 chars in base62 can be approximately calculated to decimal using the following approach.
62 ^ 52 ~= 3.67 x 10^78
As we can observe, this is a very big number (much larger than the number of atoms in the observable universe). Therefore, the short URL can be expanded up to 52 characters as well as the number of generated short URLs can be up to 3.67 * 10^78
.
For running the app, you need to have Docker installed.
Please note that there is a docker client and docker server that needs to be installed.
Once the docker server is running, you can simply enter the command below to build
and run
the container.
docker-compose up --build
Note: Running front-end server can take up to 10 mins. The reasons are mainly:
create-react-app
is a popular environment for setting up React apps. Desipte the popularity, runnningdev
server usingcreate-react-app
can be slow.- The
dev
version is being deployed to the docker. As a future work, instead ofdev
, we can deploy thebuild
version which is faster and lightweight. Then, we can setup anginx
docker image for serving the front-endbuild
release.
I've leveraged React to develope the front-end application.
The front-end follows MVC architecture. This architecture seperates Model from View from Controller for easier maintenance.
- Model: the model in front-end application referes to network calls. All API calls exists inside Network folder.
- View: all the components forming UI come in Views folder.
- Controller: the files inside View consist of several components. These modules are called
Components
and are stored withinComponents
folder.
I've used .gitignore
for preventing redundant files to be uploaded to GitHub.
The used dependenice are as follows:
- Ant-design: React UI library.
- axios: Http and Https calls.
- react-router: navigating between different pages of the front-end app.
I've used Django-Rest-Framework as the back-end web framework for developing the server.
Django requires the developer to follow MVC architecture.
- Assign a short URL to a long URL (POST): This API is used to return an unique short URL corresponding to a long address. If the long address exists in the database, the API simply returns the unique short address. Otherwise, the back-end creates a unique short address associated to the long URL and returns it.
- Get the long URL of a specific short URL: returns the long URL associated the the short URL, not found, otherwise.
I've used sqllite3 for the sake of simplicity.
id | URL | unique key |
---|---|---|
PK | required | required |
id = models.BigAutoField(primary_key=True)
long_url = models.URLField(max_length=2083)
unique_key = models.CharField(max_length=20)
- Django
- Djangorestframework
- python-decouple: for hiding SECRET_KEY
- pybase62: for calculating base62.