Skip to content

A full stack URL shortener that uses a SQLite database with an Express server and a React front end.

Notifications You must be signed in to change notification settings

fermentationist/urly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

urly


A URL shortener made by Dennis Hodges.

Use

  1. Clone this repo. git clone https://github.com/fermentationist/urly.git (Or, if you prefer, download the zip.)
  2. cd into project root. cd urly.
  3. Type npm install. This will install dependencies. (If you don't have Node.js installed, you can download it here.)
  4. To build and run app, type npm start. (Or, to run dev server, type npm run dev.)
  5. After build is complete, open localhost:4000 in your browser. (Or, if running dev server, go to localhost:3000 instead.)

Tests

  • To run API and unit tests, type npm test.

Description

  • Data Storage: Implementation: For the sake of simplicity and portability (I didn't want the user to have to configure a local env among other things), I chose a SQLite database. A simple table, named redirects, was used:
    CREATE TABLE IF NOT EXISTS redirects(
        id INTEGER PRIMARY KEY NOT NULL,
        url TEXT NOT NULL UNIQUE
      );
    Scaling: While a SQLite database is not a very scalable storage solution, a more robust SQL database would probably still be an appropriate choice to store redirects. (There are also solutions like Vitess and services like Planetscale that can horizontally scale a MySQL database.) A relational table fits the data as well or better than a document-based storage solution, in my opinion.
  • URL Generation: Implementation: Short (7 or 8 chars), unique alphanumeric ids are generated by converting the current Unix timestamp in milliseconds to a base62 string. They are appended to the host URL to create the shortened link. These ids will be unique as long as they are created at least 1ms apart (a rate limiter is in place to guarantee this). The integer-based timestamp value used to construct the id is used as a primary key in the database, instead of the base62 version, for faster indexing. Scaling: I chose this solution for ease of implementation, but its limitations mean that a different solution will be needed at scale. For instance, the uniqueness of the ids is dependent on generating no more than one in any given millisecond. Currently, a rate limiter is being used to prevent this, but guaranteeing uniqueness will be more difficult if there are multiple servers. Some other possible solutions: A true UUID can be used, but it will result in a significantly longer URL, which we probably don't want. A better solution might be to create a database table full of pre-generated ids, each already known to be unique (allowing them to remain short - for example, there are 62^6, or over 56 billion possible 6-character alphanumeric combinations, if using upper and lower case letters). A single table could be used to avoid joins. The table would look like this:
    CREATE TABLE IF NOT EXISTS redirects(
      integer_id BIGINT PRIMARY KEY NOT NULL,
      short_id VARCHAR(6) NOT NULL UNIQUE,
      url VARCHAR(2048) DEFAULT NULL
    );
    To add a url would take three queries (current implementation requires two, one SELECT and one INSERT): First, to check if the URL is already in the database: SELECT short_id FROM redirects WHERE url=? Then another, to get the ids: SELECT short_id, integer_id FROM redirects WHERE url IS NULL LIMIT 1; and then: UPDATE redirects SET url=? WHERE integer_id=?
  • Server: Implementation: I have used a Node.js (Express) server, both because it is well-suited to the task, and because of my preexisting familiarity with it, making it a fast and easy option. It is also easier to consolidate into a single repo with the React front end than it would be using a Python framework. The API consists of three endpoints: POST /api/shorten-url, GET /api/test and GET /:redirectID. The first does the work of returning a shortened URL, the second is just for testing, and then the redirect path for shortened URLs. Scaling: Node.js is asynchronous and capable of handling up to ~15K requests/second, making it a decent choice as the project scales. Of course, a load balancer would be needed once multiple servers become necessary.
  • User Interface: Implementation: The front end is built with React, largely because I have a lot of familiarity with it, making it fast and easy to develop with. The app works as I intended and is fairly fast, but there are probably other, more lightweight front end solutions that could have been used (maybe Svelte or vanilla JS), especially given the simplicity of the app. Scaling: The choice of client is not a concern of scale to the same degree that decisions around the back end are. This SPA should work fine at scale, though it should perhaps first be optimized for performance and undergo some design refinement.

About

A full stack URL shortener that uses a SQLite database with an Express server and a React front end.

Resources

Stars

Watchers

Forks

Releases

No releases published

Languages