Error.__init__(self, code, *args, **kwargs)
return NarrowError
+
class Proxy(object):
- def __init__(self, url, headers={}, timeout=5):
- self._url = url
- self._headers = headers
- self._timeout = timeout
-
- @defer.inlineCallbacks
- def callRemote(self, method, *params):
- id_ = 0
-
- try:
- data = yield client.getPage(
- url=self._url,
- method='POST',
- headers=dict(self._headers, **{'Content-Type': 'application/json'}),
- 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_for_code(resp['error']['code'])(resp['error']['message'], resp['error'].get('data', None))
- defer.returnValue(resp['result'])
+ def __init__(self, func, services=[]):
+ self._func = func
+ self._services = services
def __getattr__(self, attr):
if attr.startswith('rpc_'):
- return lambda *params: self.callRemote(attr[len('rpc_'):], *params)
- raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
+ return lambda *params: self._func('.'.join(self._services + [attr[len('rpc_'):]]), params)
+ elif attr.startswith('svc_'):
+ return Proxy(self._func, self._services + [attr[len('svc_'):]])
+ else:
+ raise AttributeError('%r object has no attribute %r' % (self.__class__.__name__, attr))
-class Server(deferred_resource.DeferredResource):
- def __init__(self, provider):
- deferred_resource.DeferredResource.__init__(self)
- self._provider = provider
-
- @defer.inlineCallbacks
- def render_POST(self, request):
+@defer.inlineCallbacks
+def _handle(data, provider, preargs=(), response_handler=None):
id_ = None
try:
try:
- data = request.content.read()
-
try:
req = json.loads(data)
except Exception:
raise Error_for_code(-32700)(u'Parse error')
+ if 'result' in req or 'error' in req:
+ response_handler(req['id'], req['result'] if 'error' not in req or req['error'] is None else
+ failure.Failure(Error_for_code(resp['error']['code'])(resp['error']['message'], resp['error'].get('data', None))))
+ defer.returnValue(None)
+
id_ = req.get('id', None)
method = req.get('method', None)
if not isinstance(method, basestring):
if not isinstance(params, list):
raise Error_for_code(-32600)(u'Invalid Request')
- method_meth = getattr(self._provider, 'rpc_' + method, None)
+ for service_name in method.split('.')[:-1]:
+ provider = getattr(provider, 'svc_' + service_name, None)
+ if provider is None:
+ raise Error_for_code(-32601)(u'Service not found')
+
+ method_meth = getattr(provider, 'rpc_' + method.split('.')[-1], None)
if method_meth is None:
raise Error_for_code(-32601)(u'Method not found')
- result = yield method_meth(request, *params)
+ result = yield method_meth(*list(preargs) + list(params))
error = None
except Error:
raise
result = None
error = e._to_obj()
- data = json.dumps(dict(
+ defer.returnValue(json.dumps(dict(
jsonrpc='2.0',
id=id_,
result=result,
error=error,
- ))
+ )))
+
+# HTTP
+
+@defer.inlineCallbacks
+def _http_do(url, headers, timeout, method, params):
+ id_ = 0
+
+ try:
+ data = yield client.getPage(
+ url=url,
+ method='POST',
+ headers=dict(headers, **{'Content-Type': 'application/json'}),
+ postdata=json.dumps({
+ 'jsonrpc': '2.0',
+ 'method': method,
+ 'params': params,
+ 'id': id_,
+ }),
+ timeout=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_for_code(resp['error']['code'])(resp['error']['message'], resp['error'].get('data', None))
+ defer.returnValue(resp['result'])
+HTTPProxy = lambda url, headers={}, timeout=5: Proxy(lambda method, params: _http_do(url, headers, timeout, method, params))
+
+class HTTPServer(deferred_resource.DeferredResource):
+ def __init__(self, provider):
+ deferred_resource.DeferredResource.__init__(self)
+ self._provider = provider
+
+ @defer.inlineCallbacks
+ def render_POST(self, request):
+ data = yield _handle(request.content.read(), self._provider, preargs=[request])
+ assert data is not None
request.setHeader('Content-Type', 'application/json')
request.setHeader('Content-Length', len(data))
request.write(data)