def error(self, error): assert isinstance(error, Exception), "%s must be Exception" % error data = { "type": error.__class__.__name__, "args": error.args, "message": str(error), } ret = JSONRPC20Response(_id=self.rid, error=JSONRPCServerError(data=data)._data) if DEBUG: print("-->", ret) self.conn.send(ret.json)
def handle_request(cls, request, service_id, method_id, dispatcher): """ Handle request data. At this moment request has correct jsonrpc format. :param dict request: data parsed from request_str. :param jsonrpc.dispatcher.Dispatcher dispatcher: .. versionadded: 1.8.0 """ def response(**kwargs): return MQTTRPC10Response( _id=request._id, **kwargs) try: method = dispatcher[(service_id, method_id)] except KeyError: output = response(error=JSONRPCMethodNotFound()._data) else: try: result = method(*request.args, **request.kwargs) except JSONRPCDispatchException as e: output = response(error=e.error._data) except Exception as e: data = { "type": e.__class__.__name__, "args": e.args, "message": str(e), } if isinstance(e, TypeError) and is_invalid_params( method, *request.args, **request.kwargs): output = response( error=JSONRPCInvalidParams(data=data)._data) else: logger.exception("API Exception: {0}".format(data)) output = response( error=JSONRPCServerError(data=data)._data) else: output = response(result=result) finally: if not request.is_notification: return output else: return []
async def post(self): dispatcher = self.request.app.get("jsonrpc_dispatcher", None) if dispatcher is None: raise IskHttpServerException( "JSONRPC dispatcher not found. Place it in server app") request_text = await self.request.text() # TODO: Make this non-blocking # TODO: Meaningful error handling of JSON-RPC calls try: response = JSONRPCResponseManager.handle(request_text, dispatcher) except Exception: response = JSONRPCServerError() logger.error("JSON-RPC Error", exc_info=True) return self.basic_response(text=response.json, content_type="application/json")
async def run(self): async for req in self.requests: req = JSONRPC20Request.from_data(req) if req._id != None: assert req._id not in self.ids, "Replayed id: %s" % req._id self.ids.add(req._id) if req.method not in self.methods: logging.error("Unknown method: %s" % req.method) await write_error(self.transport, req._id, JSONRPCMethodNotFound()) return f = self.methods[req.method] try: if isinstance(req.params, list): t = asyncio.ensure_future(f(*req.params, __context=self.context)) else: # It's a dict req.params['__context'] = self.context t = asyncio.ensure_future(f(**req.params)) asyncio.ensure_future(self._response(req._id, time(REQ_TIME, future=t))) self.tasks[req._id] = t #def clean_task(f): #del self.tasks[req._id] #t.add_done_callback(clean_task) for cb in self.callbacks: t.add_done_callback(cb) except Exception as e: if self.raven_client is None: raven_id = None else: raven_id = self.raven_client.captureException() await write_error(self.transport, req._id, JSONRPCServerError( message=str(e), data=dict(raven_id=raven_id))) return
async def _get_responses(cls, requests, dispatcher): # noqa: C901 """ Response to each single JSON-RPC Request. :return iterator(JSONRPC20Response): .. versionadded: 1.9.0 TypeError inside the function is distinguished from Invalid Params. """ for request in requests: def make_response(**kwargs): response = cls.RESPONSE_CLASS_MAP[request.JSONRPC_VERSION]( _id=request._id, **kwargs) response.request = request return response output = None try: method = dispatcher[request.method] except KeyError: output = make_response(error=JSONRPCMethodNotFound()._data) else: try: result = method(*request.args, **request.kwargs) if inspect.isawaitable(result): result = await result # Find pydantic models and convert them to dict if isinstance(result, pydantic.BaseModel): result = result.dict() elif isinstance(result, list): result = [ x.dict() if isinstance(x, pydantic.BaseModel) else x for x in result ] except JSONRPCDispatchException as e: output = make_response(error=e.error._data) except Exception as e: err_args = e.args if e.__class__.__name__ == 'ValidationError': err_args = None data = { "type": e.__class__.__name__, "args": err_args, "message": str(e), } logger.exception("API Exception: {0}".format(data)) if isinstance(e, TypeError) and is_invalid_params( method, *request.args, **request.kwargs): output = make_response(error=JSONRPCInvalidParams( data=data)._data) else: output = make_response(error=JSONRPCServerError( data=data)._data) else: output = make_response(result=result) finally: if not request.is_notification: yield output