1 from __future__ import division
6 from twisted.internet import defer
7 from twisted.python import log
8 from twisted.web import client, error
10 import deferred_resource
12 class Error(Exception):
13 def __init__(self, code, message, data=None):
14 if not isinstance(code, int):
15 raise TypeError('code must be an int')
16 if not isinstance(message, unicode):
17 raise TypeError('message must be a unicode')
18 self._code, self._message, self._data = code, message, data
20 return '%i %s' % (self._code, self._message) + (' %r' % (self._data, ) if self._data is not None else '')
24 'message': self._message,
29 def __init__(self, url, auth=None):
33 @defer.inlineCallbacks
34 def callRemote(self, method, *params):
38 'Content-Type': 'text/json',
40 if self._auth is not None:
41 headers['Authorization'] = 'Basic ' + base64.b64encode(':'.join(self._auth))
43 data = yield client.getPage(
54 except error.Error, e:
55 resp = json.loads(e.response)
57 resp = json.loads(data)
60 raise ValueError('invalid id')
61 if 'error' in resp and resp['error'] is not None:
62 raise Error(**resp['error'])
63 defer.returnValue(resp['result'])
65 def __getattr__(self, attr):
66 if attr.startswith('rpc_'):
67 return lambda *params: self.callRemote(attr[len('rpc_'):], *params)
68 raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
70 class Server(deferred_resource.DeferredResource):
73 @defer.inlineCallbacks
74 def render_POST(self, request):
75 # missing batching, 1.0 notifications
76 data = request.content.read()
78 if self.extra_headers is not None:
79 for name, value in self.extra_headers.iteritems():
80 request.setHeader(name, value)
84 req = json.loads(data)
86 raise RemoteError(-32700, u'Parse error')
89 request.write(json.dumps({
96 id_ = req.get('id', None)
100 method = req['method']
101 if not isinstance(method, unicode):
103 params = req.get('params', [])
104 if not isinstance(params, list):
107 raise Error(-32600, u'Invalid Request')
109 method_name = 'rpc_' + method
110 if not hasattr(self, method_name):
111 raise Error(-32601, u'Method not found')
112 method_meth = getattr(self, method_name)
114 if hasattr(method_meth, "takes_headers"):
115 params = [request.received_headers] + list(params)
118 result = yield method_meth(*params)
120 print 'Squelched JSON method error:'
122 raise Error(-32099, u'Unknown error')
127 request.write(json.dumps({
134 request.write(json.dumps({
138 'error': e._to_obj(),