Skip to content

Instantly share code, notes, and snippets.

@tomotaka
Created December 16, 2013 10:18
Show Gist options
  • Save tomotaka/7984876 to your computer and use it in GitHub Desktop.
Save tomotaka/7984876 to your computer and use it in GitHub Desktop.
mongo-based url shorten service engine
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# requirements: pip install mongoengine simplejson bottle
import mongoengine
import string
from bottle import (
route, run, HTTPResponse, request
)
import simplejson
mongo_db_name = 't110me'
mongoengine.connect(mongo_db_name)
counter_name = 'count'
class Counter(mongoengine.Document):
name = mongoengine.StringField()
value = mongoengine.IntField()
class ShortenedUrl(mongoengine.Document):
url = mongoengine.StringField()
key = mongoengine.StringField()
key_n = mongoengine.IntField()
meta = {
'indexes': ['key']
}
class URLShortenManager(object):
def shorten(self, url):
count = self._get_current_count_and_count_up()
key = self._num_to_key(count)
shortened_url = ShortenedUrl()
shortened_url.url = url
shortened_url.key = key
shortened_url.key_n = count
shortened_url.save()
return key
def find(self, key):
s_url = ShortenedUrl.objects(key=key).first()
return s_url
def _get_current_count_and_count_up(self):
c = Counter.objects(name=counter_name).first()
if c is None:
c = Counter()
c.name = counter_name
c.value = -1 # will be zero
ret = c.value
c.value = c.value + 1
c.save()
return ret
def _num_to_key(self, num):
chars = string.ascii_letters + string.digits
base_n = len(chars)
n = num
ret = ""
while True:
amari = n % base_n
n = n / base_n
ret = chars[amari] + ret
if n == 0:
break
return ret
@route('/control/shorten', method=['GET', 'POST'])
def web_shorten():
if request.method == 'GET':
url = request.query.get('url')
else:
url = request.forms.get('url')
m = URLShortenManager()
key = m.shorten(url)
result = {'status': 'ok', 'result': {'key': key, 'url': url}}
r = HTTPResponse(status=200, body=simplejson.dumps(result))
r.set_header('Content-Type', 'application/json')
return r
@route('/control/info/<key>')
def web_info(key):
m = URLShortenManager()
info = m.find(key)
status = 200
if info:
result = {'status': 'ok', 'result': {'key': key, 'url': info.url, 'key_n': info.key_n}}
else:
result = {'status': 'error', 'result': None, 'message': 'no such key'}
status = 500
r = HTTPResponse(status=status, body=simplejson.dumps(result))
r.set_header('Content-Type', 'application/json')
return r
@route('/<key>')
def web_jump(key):
m = URLShortenManager()
info = m.find(key)
if info:
r = HTTPResponse(status=302)
r.set_header('Location', info.url)
return r
else:
result = {'status': 'error', 'result': None, 'message': 'no such key'}
r = HTTPResponse(status=500, body=simplejson.dumps(result))
r.set_header('Content-Type', 'application/json')
return r
if __name__ == '__main__':
run(host='0.0.0.0', port=7780, debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment