oyster/oyster/web.py
2012-02-13 18:33:41 -05:00

108 lines
2.8 KiB
Python

import re
import json
import datetime
import functools
import flask
import pymongo.objectid
from oyster.conf import settings
from oyster.core import kernel
class JSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
elif isinstance(obj, pymongo.objectid.ObjectId):
return str(obj)
else:
return super(JSONEncoder, self).default(obj)
def _path_fixer(url):
""" this exists because werkzeug seems to collapse // into / sometimes
certainly a hack, but given that werkzeug seems to only do the mangling
*sometimes* being a bit aggressive was the only viable option
"""
return re.sub(r'(http|https|ftp):/([^/])', r'\1://\2', url)
def api_wrapper(template=None):
def wrapper(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
data = func(*args, **kwargs)
if 'json' in flask.request.args or not template:
return json.dumps(data, cls=JSONEncoder)
else:
return flask.render_template(template, **data)
return newfunc
return wrapper
app = flask.Flask('oyster')
@app.route('/')
@api_wrapper('index.html')
def index():
status = {
'tracking': kernel.db.tracked.count(),
'need_update': kernel.get_update_queue_size(),
'logs': list(kernel.db.logs.find().sort('$natural', -1).limit(20)),
'mongo_host': settings.MONGO_HOST,
}
return status
@app.route('/status/')
@api_wrapper()
def doc_list():
status = {
'tracking': kernel.db.tracked.count(),
'need_update': kernel.get_update_queue_size(),
}
return status
@app.route('/log/')
@api_wrapper('logs.html')
def log_view():
offset = int(flask.request.args.get('offset', 0))
size = 100
prev_offset = max(offset - size, 0)
next_offset = offset + size
logs = kernel.db.logs.find().sort('$natural', -1).skip(offset).limit(size)
return dict(logs=list(logs), prev_offset=prev_offset,
next_offset=next_offset, offset=offset)
@app.route('/tracked/')
@api_wrapper()
def tracked():
tracked = list(kernel.db.tracked.find())
return json.dumps(tracked, cls=JSONEncoder)
@app.route('/tracked/<path:url>')
def tracked_view(url):
url = _path_fixer(url)
doc = kernel.db.tracked.find_one({'url': url})
return json.dumps(doc, cls=JSONEncoder)
@app.route('/doc/<path:url>/<version>')
def show_doc(url, version):
url = _path_fixer(url)
if version == 'latest':
version = -1
doc = kernel.get_version(url, version)
resp = flask.make_response(doc.read())
resp.headers['content-type'] = doc.content_type
return resp
if __name__ == '__main__':
app.run(debug=True)