Mercurial > hg > AuthRPC
comparison wibble/server/JsonRpcApp.py @ 0:6a61cfdf6930
Initial version
author | Ben Croston <ben@croston.org> |
---|---|
date | Tue, 30 Aug 2011 22:19:48 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6a61cfdf6930 |
---|---|
1 from webob import Request, Response, exc | |
2 try: | |
3 from json import loads, dumps | |
4 except: | |
5 from simplejson import loads, dumps | |
6 import traceback | |
7 import sys | |
8 | |
9 class JsonRpcApp(object): | |
10 """ | |
11 Serve the given object via json-rpc (http://json-rpc.org/) | |
12 """ | |
13 | |
14 def __init__(self, obj, auth=None): | |
15 """ | |
16 obj - a class of functions available using jsonrpc | |
17 auth - an authentication function (optional) | |
18 """ | |
19 self.obj = obj | |
20 self.auth = auth | |
21 | |
22 def __call__(self, environ, start_response): | |
23 req = Request(environ) | |
24 try: | |
25 resp = self.process(req) | |
26 except ValueError, e: | |
27 resp = exc.HTTPBadRequest(str(e)) | |
28 except exc.HTTPException, e: | |
29 resp = e | |
30 return resp(environ, start_response) | |
31 | |
32 def process(self, req): | |
33 if not req.method == 'POST': | |
34 raise exc.HTTPMethodNotAllowed("Only POST allowed").exception | |
35 | |
36 try: | |
37 json = loads(req.body) | |
38 except ValueError, e: | |
39 raise ValueError('Bad JSON: %s' % e) | |
40 | |
41 try: | |
42 method = json['method'] | |
43 params = json['params'] | |
44 id = json['id'] | |
45 username = json['username'] if 'username' in json else None | |
46 password = json['password'] if 'password' in json else None | |
47 except KeyError, e: | |
48 raise ValueError("JSON body missing parameter: %s" % e) | |
49 | |
50 if params is None: | |
51 params = [] | |
52 if not isinstance(params, list): | |
53 raise ValueError("Bad params %r: must be a list" % params) | |
54 text = traceback.format_exc() | |
55 exc_value = sys.exc_info()[1] | |
56 error_value = dict( | |
57 name='JSONRPCError', | |
58 code=100, | |
59 message=str(exc_value), | |
60 error=text) | |
61 return Response( | |
62 status=500, | |
63 content_type='application/json', | |
64 body=dumps(dict(result=None, | |
65 error=error_value, | |
66 id=id))) | |
67 | |
68 obj = self.obj | |
69 if isinstance(self.obj,tuple) or isinstance(self.obj,list): | |
70 for x in self.obj: | |
71 if method.startswith('%s.'%x.__class__.__name__): | |
72 obj = x | |
73 method = method.replace('%s.'%obj.__class__.__name__,'',1) | |
74 break | |
75 elif method.startswith('%s.'%self.obj.__class__.__name__): | |
76 method = method.replace('%s.'%self.obj.__class__.__name__,'',1) | |
77 if method.startswith('_'): | |
78 raise exc.HTTPForbidden("Bad method name %s: must not start with _" % method).exception | |
79 try: | |
80 method = getattr(obj, method) | |
81 except AttributeError: | |
82 raise ValueError("No such method %s" % method) | |
83 | |
84 if self.auth is not None: | |
85 try: | |
86 auth_result = self.auth(username, password, req.user_agent) | |
87 except: | |
88 text = traceback.format_exc() | |
89 exc_value = sys.exc_info()[1] | |
90 error_value = dict( | |
91 name='JSONRPCError', | |
92 code=100, | |
93 message=str(exc_value), | |
94 error=text) | |
95 return Response( | |
96 status=500, | |
97 content_type='application/json', | |
98 body=dumps(dict(result=None, | |
99 error=error_value, | |
100 id=id))) | |
101 if not auth_result: | |
102 raise exc.HTTPUnauthorized().exception | |
103 | |
104 try: | |
105 result = method(*params) | |
106 except: | |
107 text = traceback.format_exc() | |
108 exc_value = sys.exc_info()[1] | |
109 error_value = dict( | |
110 name='JSONRPCError', | |
111 code=100, | |
112 message=str(exc_value), | |
113 error=text) | |
114 return Response( | |
115 status=500, | |
116 content_type='application/json', | |
117 body=dumps(dict(result=None, | |
118 error=error_value, | |
119 id=id))) | |
120 | |
121 return Response( | |
122 content_type='application/json', | |
123 body=dumps(dict(result=result, | |
124 error=None, | |
125 id=id))) | |
126 |