🍌URL Shortener - bnon.xyz
Building a url shortener for fun and no profit!
This was a fun full stack project weeknight project and I learned a lot while doing it and would love to share the process with you all!
When starting any project it we should start by working through the SDLC to maximize our productivity and minimize wasted time.
Stage One - Planning
Q: What are we trying to build?
A: A URL Shortener.
A: It’s a fun project!
Stage Two - Analysis
Q: Is this something people would use?
A: Totally! There are many out there, but this one is mine.
Q: Potential for abuse?
A: Yes, must consider mitigations.
Q: Am I worried about monetization?
A: Not so much.
Stage Three - Design
Let’s think about what we want our user experience (UX) to be once they land on our page. I want this to be simple and easy
Going for a very simple google-esque design and using a design mockup tool I settled on something like this.
The backend is the workhorse of this application, it has TWO main jobs.
- Shorten Links
- Unshorten Links
def shorten(val): # Take a "long" value and return a "short" value pass def unshorten(val): # Take a "short" value and return its corresponding "long" value pass
All of our data will be stored in a database and for our purposes I chose to use SQLite, although for this implementation any database where you can have a unique primary key for every entry will work fine. If you want to use another method, you’re on your own. For our short url purposes we only want to have valid, non special characters; upper and lowercase alphabet a-z,A-Z and numbers 0-9. This gives us a key space of 62 characters or base62; our database uses just numbers, or base10.
Cool! Heavy lifting done!
Long to short => base10 -> base62
Short to long => base62 -> base10
from baseconvert import base def shorten(val): # Take a "long" value and return a "short" value return base(val, 10, 62, string=True) def unshorten(val): # Take a "short" value and return its corresponding "long" value return base(val, 62, 10, string=True)
Lets add some API endpoints using Flask
from flask import Flask import sqlite3 app = Flask(__name__) db = sqlite3.connect('file.db') @app.route('/add', methods=['POST']): def add_url(): # Add url to database & get ID row_id = db.add(url).lastrowid # shorten short_id = shorten(row_id) # return to user return short_id @app.route('/<string:shortURL>', methods=['GET']): def get_url(shortURL): # lengthen row id value (shortURL) row_id = unshorten(shortURL) # get url from database row = db.get(row_id) # return to user return row['url']
We’ve got our big pieces designed out and some psudocode written; it’s time to move to the next stage!
Stage Four - Implementation
There is no public repo for my code but check out the running implementation here - https://bnon.xyz
Front end is hosted for free on netlify, backend & database is hosted on Digital Ocean on small droplet.
Security was kept in mind during the implementation of the project. Recaptcha is used to minimize automated shortlinking and of course this is validated on the backend as well as front.
A feature I would like to add at a later date is VirusTotal link rating to mitigate any malicious actors using this service to deliver payloads or bypass network filtering devices.
Stage Five - Testing & Integration
I spent an afternoon testing and securing this application. This was a really fun project and I’m receptive to any and all bug or vulnerability reports, there’s always something to learn and improve on.
Stage Six - Maintenance
So far so good, I’ve knocked down all the items and bugs on my list. Did I miss any?
Enjoyed the post? Let me know! 💛🦄🔖