Skip to content

Instantly share code, notes, and snippets.

@Justasic
Last active May 25, 2024 23:23
Show Gist options
  • Save Justasic/5c461096b0d7ec8ba290dda6e3d74f1f to your computer and use it in GitHub Desktop.
Save Justasic/5c461096b0d7ec8ba290dda6e3d74f1f to your computer and use it in GitHub Desktop.
Actually URLShortener.tac but no syntax highlighting. This is an entire website for storing and redirecting URLs in a simple way. Post JSON to the site and it stores it, give someone a link and it redirects them.
#!/usr/bin/twistd3 -noy
import sqlite3, json, os
from twisted.application import service, internet
from twisted.web import static, server, proxy
from twisted.internet import reactor
from twisted.python import log
from klein import Klein
class ShortURL:
"""
# ShortURL (https://github.com/delight-im/ShortURL)
# Copyright (c) delight.im (https://www.delight.im/)
# Licensed under the MIT License (https://opensource.org/licenses/MIT)
ShortURL: Bijective conversion between natural numbers (IDs) and short strings
ShortURL.encode() takes an ID and turns it into a short string
ShortURL.decode() takes a short string and turns it into an ID
Features:
+ large alphabet (51 chars) and thus very short resulting strings
+ proof against offensive words (removed 'a', 'e', 'i', 'o' and 'u')
+ unambiguous (removed 'I', 'l', '1', 'O' and '0')
Example output:
123456789 <=> pgK8p
"""
_alphabet = '23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_'
_base = len(_alphabet)
def encode(self, number):
string = ''
while(number > 0):
string = self._alphabet[number % self._base] + string
number //= self._base
return string
def decode(self, string):
number = 0
for char in string:
number = number * self._base + self._alphabet.index(char)
return number
class NotFound(Exception):
pass
class UserError(Exception):
pass
class ServerError(Exception):
pass
class Page(object):
app = Klein()
encoder = ShortURL()
DEFAULT_PATH = os.path.join(os.path.dirname(__file__), 'urls.db')
conn = sqlite3.connect(DEFAULT_PATH)
@app.handle_errors(NotFound)
def notfound(self, request, failure):
request.setResponseCode(404)
return 'Not found, I say!'
@app.handle_errors(UserError)
def usererr(self, request, failure):
request.setResponseCode(400)
return 'You input invalid data.'
@app.handle_errors(ServerError)
def servererr(self, request, failure):
request.setResponseCode(500)
return 'OOps! We messed up! Maybe try again?'
@app.route("/", methods=['POST'])
def CreateShortURL(self, request):
data = json.loads(request.content.read())
self.conn.execute("CREATE TABLE IF NOT EXISTS ShortURLs(url TEXT NOT NULL)").execute("INSERT INTO ShortURLs (url) VALUES (?)", (data['url'],))
rowid = self.conn.execute("SELECT ROWID FROM ShortURLs WHERE url=?", (data['url'],))
id = rowid.fetchone()
if not id:
request.setResponseCode(500)
return json.dumps({"status": "Failure", "reason": "Database commitment failed."})
eid = self.encoder.encode(id[0])
request.setResponseCode(200)
return json.dumps({"status": "Success", "id": eid, "site": "https://s.justasic.net/"})
@app.route("/<shortid>")
def RedirectURL(self, request, shortid):
shortid = shortid.strip()
if not shortid:
raise NotFound()
try:
id = self.encoder.decode(shortid)
cur = self.conn.execute("SELECT url FROM ShortURLs WHERE ROWID=?", (id,))
url = cur.fetchone()
if not url:
raise NotFound()
return request.redirect(url[0])
except sqlite3.OperationalError:
raise NotFound()
except ValueError:
raise UserError()
application = service.Application("URLShortener")
herp = Page()
w = server.Site(herp.app.resource())
i = internet.TCPServer(6099, w)
i.setServiceParent(application)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment