-
Notifications
You must be signed in to change notification settings - Fork 5
/
shortener.py
71 lines (58 loc) · 1.85 KB
/
shortener.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from __future__ import print_function
import flask
import os
from hashlib import md5
from base64 import b64encode
from pynamodb.models import Model
from pynamodb.indexes import GlobalSecondaryIndex, AllProjection
from pynamodb.attributes import UnicodeAttribute
class Url(Model):
class Meta:
table_name = "shortened-urls"
host = "http://127.0.0.1:8000"
region = "us-west-2"
class CodeIndex(GlobalSecondaryIndex):
class Meta:
read_capacity_units = 1
write_capacity_units = 1
projection = AllProjection()
code = UnicodeAttribute(hash_key=True)
url = UnicodeAttribute(hash_key=True)
code = UnicodeAttribute()
code_index = CodeIndex()
def save(self, **kwargs):
"""
Generates the shortened code before saving
"""
self.code = b64encode(
md5(self.url.encode('utf-8')).hexdigest()[-4:].encode('utf-8')
).decode('utf-8').replace('=', '').replace('/', '_')
super(Url, self).save(**kwargs)
app = flask.Flask(__name__)
app.config.update(DEBUG=True)
@app.route('/')
def index():
return flask.render_template(
"index.html",
url_root = flask.request.url_root)
@app.route('/shorten/<path:url>')
def shorten(url):
model = Url(url)
model.save()
return flask.Response(model.code)
@app.route('/<path:code>')
def resolve(code):
# next() in Python3 is __next__()
try:
model = Url.code_index.query(code).next()
except AttributeError:
model = Url.code_index.query(code).__next__()
except StopIteration:
flask.abort(404)
finally:
return flask.redirect(model.url)
if __name__ == "__main__":
if not Url.exists():
print("Creating table...")
Url.create_table(wait=True, read_capacity_units=1, write_capacity_units=1)
app.run(host='0.0.0.0')