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, timeout=5):
32 self._timeout = timeout
34 @defer.inlineCallbacks
35 def callRemote(self, method, *params):
39 'Content-Type': 'application/json',
41 if self._auth is not None:
42 headers['Authorization'] = 'Basic ' + base64.b64encode(':'.join(self._auth))
44 data = yield client.getPage(
54 timeout=self._timeout,
56 except error.Error, e:
58 resp = json.loads(e.response)
62 resp = json.loads(data)
65 raise ValueError('invalid id')
66 if 'error' in resp and resp['error'] is not None:
67 raise Error(**resp['error'])
68 defer.returnValue(resp['result'])
70 def __getattr__(self, attr):
71 if attr.startswith('rpc_'):
72 return lambda *params: self.callRemote(attr[len('rpc_'):], *params)
73 raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
75 class Server(deferred_resource.DeferredResource):
78 @defer.inlineCallbacks
79 def render_POST(self, request):
80 # missing batching, 1.0 notifications
81 request.setHeader('Content-Type', 'application/json')
82 data = request.content.read()
84 if self.extra_headers is not None:
85 for name, value in self.extra_headers.iteritems():
86 request.setHeader(name, value)
90 req = json.loads(data)
92 raise RemoteError(-32700, u'Parse error')
95 request.write(json.dumps({
102 id_ = req.get('id', None)
106 method = req['method']
107 if not isinstance(method, unicode):
109 params = req.get('params', [])
110 if not isinstance(params, list):
113 raise Error(-32600, u'Invalid Request')
115 method_name = 'rpc_' + method
116 if not hasattr(self, method_name):
117 raise Error(-32601, u'Method not found')
118 method_meth = getattr(self, method_name)
120 if hasattr(method_meth, "takes_request"):
121 params = [request] + list(params)
124 result = yield method_meth(*params)
126 print 'Squelched JSON method error:'
128 raise Error(-32099, u'Unknown error')
133 request.write(json.dumps({
140 request.write(json.dumps({
144 'error': e._to_obj(),