Mercurial > hg > AuthRPC
view server/JsonRpcApp.py @ 2:c7a236de5214
-
author | Ben Croston <ben@croston.org> |
---|---|
date | Tue, 30 Aug 2011 23:37:53 +0100 |
parents | wibble/server/JsonRpcApp.py@6a61cfdf6930 |
children |
line wrap: on
line source
from webob import Request, Response, exc try: from json import loads, dumps except: from simplejson import loads, dumps import traceback import sys class JsonRpcApp(object): """ Serve the given object via json-rpc (http://json-rpc.org/) """ def __init__(self, obj, auth=None): """ obj - a class of functions available using jsonrpc auth - an authentication function (optional) """ self.obj = obj self.auth = auth def __call__(self, environ, start_response): req = Request(environ) try: resp = self.process(req) except ValueError, e: resp = exc.HTTPBadRequest(str(e)) except exc.HTTPException, e: resp = e return resp(environ, start_response) def process(self, req): if not req.method == 'POST': raise exc.HTTPMethodNotAllowed("Only POST allowed").exception try: json = loads(req.body) except ValueError, e: raise ValueError('Bad JSON: %s' % e) try: method = json['method'] params = json['params'] id = json['id'] username = json['username'] if 'username' in json else None password = json['password'] if 'password' in json else None except KeyError, e: raise ValueError("JSON body missing parameter: %s" % e) if params is None: params = [] if not isinstance(params, list): raise ValueError("Bad params %r: must be a list" % params) text = traceback.format_exc() exc_value = sys.exc_info()[1] error_value = dict( name='JSONRPCError', code=100, message=str(exc_value), error=text) return Response( status=500, content_type='application/json', body=dumps(dict(result=None, error=error_value, id=id))) obj = self.obj if isinstance(self.obj,tuple) or isinstance(self.obj,list): for x in self.obj: if method.startswith('%s.'%x.__class__.__name__): obj = x method = method.replace('%s.'%obj.__class__.__name__,'',1) break elif method.startswith('%s.'%self.obj.__class__.__name__): method = method.replace('%s.'%self.obj.__class__.__name__,'',1) if method.startswith('_'): raise exc.HTTPForbidden("Bad method name %s: must not start with _" % method).exception try: method = getattr(obj, method) except AttributeError: raise ValueError("No such method %s" % method) if self.auth is not None: try: auth_result = self.auth(username, password, req.user_agent) except: text = traceback.format_exc() exc_value = sys.exc_info()[1] error_value = dict( name='JSONRPCError', code=100, message=str(exc_value), error=text) return Response( status=500, content_type='application/json', body=dumps(dict(result=None, error=error_value, id=id))) if not auth_result: raise exc.HTTPUnauthorized().exception try: result = method(*params) except: text = traceback.format_exc() exc_value = sys.exc_info()[1] error_value = dict( name='JSONRPCError', code=100, message=str(exc_value), error=text) return Response( status=500, content_type='application/json', body=dumps(dict(result=None, error=error_value, id=id))) return Response( content_type='application/json', body=dumps(dict(result=result, error=None, id=id)))