- Published on
System Design: Bit.ly
- Authors
- Name
- Loi Tran
Introduction
1. Requirements
Functional Requirements
- As a user I navigate I can enter a URL and get a shortened URL
- As a user if I navigate to the shortened URL I'm redirected to the original URL I entered
Generate UIDs
// 1. Use Hashing(ensures same url gets same shortened URL)
const crypto = require('crypto')
function hashUrl(url, length = 7) {
const hash = crypto.createHash('sha256').update(url).digest('base64url')
return hash.slice(0, length)
}
// 2. Use Id
const urlToId = new Map()
const idToUrl = new Map()
let counter = 1000
const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
function toBase62(num) {
let str = ''
while (num > 0) {
str = BASE62[num % 62] + str
num = Math.floor(num / 62)
}
return str || '0'
}
function shortenUrl(url) {
if (urlToId.has(url)) {
return toBase62(urlToId.get(url))
}
const id = counter++
urlToId.set(url, id)
idToUrl.set(id, url)
return toBase62(id)
}
function expandShortCode(shortCode) {
const id = parseInt(shortCode, 62)
return idToUrl.get(id)
}
Flip Key/Values
function flipSelective(obj) {
const flipped = {}
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'number' || typeof value === 'string') {
flipped[value] = key
} else {
flipped[key] = value
}
}
return flipped
}
API Endpoint
const express = require('express')
const app = express()
const urlMap = {
'uid-123': 'https://example.com/some-long-url',
'uid-456': 'https://google.com',
}
app.get('/:uid', (req, res) => {
const { uid } = req.params
const redirectUrl = urlMap[uid]
if (redirectUrl) {
return res.redirect(302, redirectUrl)
}
res.status(404).send('URL not found')
})
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})