예제 #1
0
 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)
예제 #2
0
    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 []
예제 #3
0
    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")
예제 #4
0
    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
예제 #5
0
    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