|
#!/usr/bin/env python |
|
# -*- coding: utf-8 -*- |
|
|
|
import string |
|
from random import SystemRandom as SR |
|
from datetime import datetime |
|
|
|
from flask import Flask, request, jsonify, url_for, make_response, redirect |
|
from flask_sqlalchemy import SQLAlchemy |
|
|
|
app = Flask(__name__) |
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/url.db' |
|
db = SQLAlchemy(app) |
|
|
|
# length of shorten uri |
|
URI_LENGTH = 6 |
|
|
|
|
|
class Url(db.Model): |
|
shorten_url = db.Column(db.String(URI_LENGTH), primary_key=True) |
|
original_url = db.Column(db.String(255), nullable=False) |
|
created_at = db.Column(db.DateTime, default=datetime.utcnow) |
|
|
|
def __init__(self, original_url, shorten_url): |
|
self.original_url = original_url |
|
self.shorten_url = shorten_url |
|
|
|
def __repr__(self): |
|
return '<ShortenUrl: %r with OrignalUrl: %r>' % (self.shorten_url, |
|
self.original_url) |
|
# create database |
|
db.create_all() |
|
|
|
|
|
def generate_uri(length=URI_LENGTH): |
|
"""Generate a random string with `length` chacracter |
|
""" |
|
return ''.join(SR().choice(string.ascii_letters + string.digits) |
|
for _ in range(length)) |
|
|
|
|
|
@app.route("/", methods=['GET']) |
|
def index(): |
|
return "URL Shorten application" |
|
|
|
|
|
@app.route("/<string:url>", methods=['GET']) |
|
def read(url): |
|
"""This API receives an HTTP GET request with shorten url passed and |
|
lookup the shorten url in database. If original url is found, redirects |
|
user to original url. Otherwise, return JSON reponse of HTTP code 404 |
|
""" |
|
url = Url.query.filter_by(shorten_url=url).first() |
|
if url: |
|
original_url = url.original_url |
|
if not original_url.startswith('http'): |
|
original_url = 'http://' + original_url |
|
return redirect(original_url) |
|
else: |
|
resp = jsonify({'original_url': 'Not found'}) |
|
return make_response(resp, 404) |
|
|
|
|
|
@app.route("/api/v1/url", methods=['POST']) |
|
def write(): |
|
"""Write API receives original url and return shorten url |
|
""" |
|
# if original url already shorten, grab shorten url and return |
|
original_url = request.form['original_url'] |
|
url = Url.query.filter_by(original_url=original_url).first() |
|
if url: |
|
shorten_url = url_for("read", url=url.shorten_url, _external=True) |
|
resp = jsonify({'shorten_url': shorten_url}) |
|
else: |
|
# if shorten uri already existed, re-generate |
|
while True: |
|
shorten_uri = generate_uri() |
|
uri = Url.query.filter_by(shorten_url=shorten_uri).first() |
|
if shorten_uri != uri: |
|
break |
|
|
|
shorten_url = url_for("read", url=shorten_uri, _external=True) |
|
i = Url(original_url, shorten_uri) |
|
db.session.add(i) |
|
db.session.commit() |
|
resp = jsonify({'shorten_url': shorten_url}) |
|
return make_response(resp, 201) |
|
|
|
if __name__ == '__main__': |
|
app.run(debug=True) |