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': 'text/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 data = request.content.read()
83 if self.extra_headers is not None:
84 for name, value in self.extra_headers.iteritems():
85 request.setHeader(name, value)
89 req = json.loads(data)
91 raise RemoteError(-32700, u'Parse error')
94 request.write(json.dumps({
101 id_ = req.get('id', None)
105 method = req['method']
106 if not isinstance(method, unicode):
108 params = req.get('params', [])
109 if not isinstance(params, list):
112 raise Error(-32600, u'Invalid Request')
114 method_name = 'rpc_' + method
115 if not hasattr(self, method_name):
116 raise Error(-32601, u'Method not found')
117 method_meth = getattr(self, method_name)
119 if hasattr(method_meth, "takes_headers"):
120 params = [request.received_headers] + list(params)
123 result = yield method_meth(*params)
125 print 'Squelched JSON method error:'
127 raise Error(-32099, u'Unknown error')
132 request.write(json.dumps({
139 request.write(json.dumps({
143 'error': e._to_obj(),