from twisted.internet import defer
from twisted.python import log
-from twisted.web import client
+from twisted.web import client, error
import deferred_resource
raise TypeError('code must be an int')
if not isinstance(message, unicode):
raise TypeError('message must be a unicode')
- self._code, self._message, self._data = code, message, data
+ self.code, self.message, self.data = code, message, data
def __str__(self):
- return '%i %s %r' % (self._code, self._message, self._data)
+ return '%i %s' % (self.code, self.message) + (' %r' % (self.data, ) if self.data is not None else '')
def _to_obj(self):
return {
- 'code': self._code,
- 'message': self._message,
- 'data': self._data,
+ 'code': self.code,
+ 'message': self.message,
+ 'data': self.data,
}
class Proxy(object):
- def __init__(self, url, auth=None):
+ def __init__(self, url, auth=None, timeout=5):
self._url = url
self._auth = auth
+ self._timeout = timeout
@defer.inlineCallbacks
def callRemote(self, method, *params):
id_ = 0
headers = {
- 'Content-Type': 'text/json',
+ 'Content-Type': 'application/json',
}
if self._auth is not None:
headers['Authorization'] = 'Basic ' + base64.b64encode(':'.join(self._auth))
- resp = json.loads((yield client.getPage(
- url=self._url,
- method='POST',
- headers=headers,
- postdata=json.dumps({
- 'jsonrpc': '2.0',
- 'method': method,
- 'params': params,
- 'id': id_,
- }),
- )))
+ try:
+ data = yield client.getPage(
+ url=self._url,
+ method='POST',
+ headers=headers,
+ postdata=json.dumps({
+ 'jsonrpc': '2.0',
+ 'method': method,
+ 'params': params,
+ 'id': id_,
+ }),
+ timeout=self._timeout,
+ )
+ except error.Error, e:
+ try:
+ resp = json.loads(e.response)
+ except:
+ raise e
+ else:
+ resp = json.loads(data)
if resp['id'] != id_:
raise ValueError('invalid id')
if 'error' in resp and resp['error'] is not None:
- raise Error(resp['error'])
+ raise Error(**unicode(resp['error']))
defer.returnValue(resp['result'])
def __getattr__(self, attr):
raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
class Server(deferred_resource.DeferredResource):
- extra_headers = None
-
@defer.inlineCallbacks
def render_POST(self, request):
# missing batching, 1.0 notifications
- data = request.content.read()
- if self.extra_headers is not None:
- for name, value in self.extra_headers.iteritems():
- request.setHeader(name, value)
+ id_ = None
try:
+ data = request.content.read()
+
try:
req = json.loads(data)
except Exception:
- raise RemoteError(-32700, u'Parse error')
- except Error, e:
- # id unknown
- request.write(json.dumps({
- 'jsonrpc': '2.0',
- 'id': None,
- 'result': None,
- 'error': e._to_obj(),
- }))
-
- id_ = req.get('id', None)
-
- try:
+ raise Error(-32700, u'Parse error')
+
try:
+ id_ = req.get('id', None)
method = req['method']
- if not isinstance(method, unicode):
+ if not isinstance(method, basestring):
raise ValueError()
params = req.get('params', [])
if not isinstance(params, list):
except Exception:
raise Error(-32600, u'Invalid Request')
- method_name = 'rpc_' + method
- if not hasattr(self, method_name):
+ method_meth = getattr(self, 'rpc_' + method, None)
+ if method_meth is None:
raise Error(-32601, u'Method not found')
- method_meth = getattr(self, method_name)
- if hasattr(method_meth, "takes_headers"):
- params = [request.received_headers] + list(params)
-
- try:
- result = yield method_meth(*params)
- except Exception:
- print 'Squelched JSON method error:'
- log.err()
- raise Error(-32099, u'Unknown error')
+ result = yield method_meth(request, *params)
if id_ is None:
return
- request.write(json.dumps({
- 'jsonrpc': '2.0',
- 'id': id_,
- 'result': result,
- 'error': None,
- }))
+ error = None
except Error, e:
- request.write(json.dumps({
- 'jsonrpc': '2.0',
- 'id': id_,
- 'result': None,
- 'error': e._to_obj(),
- }))
+ result = None
+ error = e._to_obj()
+ except Exception:
+ log.err(None, 'Squelched JSON error:')
+
+ result = None
+ error = Error(-32099, u'Unknown error')._to_obj()
+
+ data = json.dumps(dict(
+ jsonrpc='2.0',
+ id=id_,
+ result=result,
+ error=error,
+ ))
+ request.setHeader('Content-Type', 'application/json')
+ request.setHeader('Content-Length', len(data))
+ request.write(data)