|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +__author__ = 'Michael Liao' |
| 5 | + |
| 6 | +''' |
| 7 | +JSON API definition. |
| 8 | +''' |
| 9 | + |
| 10 | +import re, json, logging, functools |
| 11 | + |
| 12 | +from transwarp.web import ctx |
| 13 | + |
| 14 | +def dumps(obj): |
| 15 | + return json.dumps(obj) |
| 16 | + |
| 17 | +class APIError(StandardError): |
| 18 | + ''' |
| 19 | + the base APIError which contains error(required), data(optional) and message(optional). |
| 20 | + ''' |
| 21 | + def __init__(self, error, data='', message=''): |
| 22 | + super(APIError, self).__init__(message) |
| 23 | + self.error = error |
| 24 | + self.data = data |
| 25 | + self.message = message |
| 26 | + |
| 27 | +class APIValueError(APIError): |
| 28 | + ''' |
| 29 | + Indicate the input value has error or invalid. The data specifies the error field of input form. |
| 30 | + ''' |
| 31 | + def __init__(self, field, message=''): |
| 32 | + super(APIValueError, self).__init__('value:invalid', field, message) |
| 33 | + |
| 34 | +class APIResourceNotFoundError(APIError): |
| 35 | + ''' |
| 36 | + Indicate the resource was not found. The data specifies the resource name. |
| 37 | + ''' |
| 38 | + def __init__(self, field, message=''): |
| 39 | + super(APIResourceNotFoundError, self).__init__('value:notfound', field, message) |
| 40 | + |
| 41 | +class APIPermissionError(APIError): |
| 42 | + ''' |
| 43 | + Indicate the api has no permission. |
| 44 | + ''' |
| 45 | + def __init__(self, message=''): |
| 46 | + super(APIPermissionError, self).__init__('permission:forbidden', 'permission', message) |
| 47 | + |
| 48 | +def api(func): |
| 49 | + ''' |
| 50 | + A decorator that makes a function to json api, makes the return value as json. |
| 51 | +
|
| 52 | + @app.route('/api/test') |
| 53 | + @api |
| 54 | + def api_test(): |
| 55 | + return dict(result='123', items=[]) |
| 56 | + ''' |
| 57 | + @functools.wraps(func) |
| 58 | + def _wrapper(*args, **kw): |
| 59 | + try: |
| 60 | + r = dumps(func(*args, **kw)) |
| 61 | + except APIError, e: |
| 62 | + r = json.dumps(dict(error=e.error, data=e.data, message=e.message)) |
| 63 | + except Exception, e: |
| 64 | + logging.exception(e) |
| 65 | + r = json.dumps(dict(error='internalerror', data=e.__class__.__name__, message=e.message)) |
| 66 | + ctx.response.content_type = 'application/json' |
| 67 | + return r |
| 68 | + return _wrapper |
| 69 | + |
| 70 | +if __name__=='__main__': |
| 71 | + import doctest |
| 72 | + doctest.testmod() |
0 commit comments