예제 #1
0
def create_json_rpc_response(id: int,
                             errors: Optional[JSONRPCError] = None,
                             result: Optional[Any] = None,
                             encode: bool = True) -> JSONRPC20Response:
    """Creates a JSONRPC20Response object.

    Args:
        id (int): RPC ID

        errors (Optional[JSONRPCError], optional): Errors if encountered.
        Mutually exclusive with `result`.
        Defaults to None.

        result (Optional[Any], optional): Results if present.
        Mutually exclusive with `errors`
        Defaults to None.

    Returns:
        JSONRPC20Response: Response object contianing either results OR errors.
    """

    resp = (JSONRPC20Response(id=id, error=errors)
            if errors is not None else JSONRPC20Response(id=id, result=result))

    return resp.json.encode("utf-8") if encode else resp
예제 #2
0
파일: common.py 프로젝트: corvis/ws-sizzle
    async def handle(self, request_str, ctx: object) -> str:
        try:
            request = self._parse_request(request_str)
        except (TypeError, ValueError):
            return self._build_response_str(JSONRPC20Response(error=JSONRPCParseError()._data))
        except JSONRPCInvalidRequestException:
            return self._build_response_str(JSONRPC20Response(error=JSONRPCInvalidRequest()._data))

        # TODO: Middleware
        # TODO: Auth

        return self._build_response_str(await JSONRPCResponseAsyncManager.handle_request(request, self.dispatcher))
예제 #3
0
    async def handle(cls, request_str, dispatcher):
        if isinstance(request_str, bytes):
            request_str = request_str.decode("utf-8")

        try:
            data = json.loads(request_str)
        except (TypeError, ValueError):
            return JSONRPC20Response(error=JSONRPCParseError()._data)

        try:
            request = JSONRPCRequest.from_data(data)
        except JSONRPCInvalidRequestException:
            return JSONRPC20Response(error=JSONRPCInvalidRequest()._data)

        return await cls.handle_request(request, dispatcher)
예제 #4
0
    def handle(
        cls,
        http_request: HTTPRequest,
        task_manager: TaskManager,
    ) -> JSONRPC20Response:
        request_str: str
        if isinstance(http_request.data, bytes):
            request_str = http_request.data.decode("utf-8")
        else:
            request_str = http_request.data

        try:
            data = json.loads(request_str)
        except (TypeError, ValueError):
            return JSONRPC20Response(error=dict(
                code=JSONRPCParseError.CODE,
                message=JSONRPCParseError.MESSAGE,
            ))

        if data.get('jsonrpc', None) != '2.0':
            return JSONRPC20Response(error=dict(
                code=JSONRPCInvalidRequest.CODE,
                message=JSONRPCInvalidRequest.MESSAGE,
            ))

        try:
            request = JSONRPCRequest.from_data(data)
        except (ValueError, JSONRPCInvalidRequestException):
            return JSONRPC20Response(error=dict(
                code=JSONRPCInvalidRequest.CODE,
                message=JSONRPCInvalidRequest.MESSAGE,
            ))

        if not isinstance(request, JSONRPC20Request):
            return JSONRPC20Response(error=dict(
                code=JSONRPCInvalidRequest.CODE,
                message=JSONRPCInvalidRequest.MESSAGE,
            ))

        result = cls.handle_valid_request(
            http_request, request, task_manager
        )

        return result
예제 #5
0
 def app (request):
   # auth with simplified version of equal op (timing attack secure)
   if (username != "" or password != "") and \
      (getattr(request.authorization,"username","") != username or \
       int(sha256(bytes(getattr(request.authorization,"password",""), "utf8")).hexdigest(), 16) - \
       password != 0):
     json = JSONRPC20Response(error={"code":403, "message": "Invalid username or password!"}).json
     return Response(json, 403, mimetype='application/json')
   response = JSONRPCResponseManager.handle(request.data, dispatcher)
   return Response(response.json, mimetype='application/json')
예제 #6
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)
예제 #7
0
    def handle(cls, http_request, task_manager):
        # pretty much just copy+pasted from the original, with slight tweaks to
        # preserve the request
        request_str = http_request.data
        if isinstance(request_str, bytes):
            request_str = request_str.decode("utf-8")

        try:
            data = json.loads(request_str)
        except (TypeError, ValueError):
            return JSONRPC20Response(error=JSONRPCParseError()._data)

        try:
            request = JSONRPCRequest.from_data(data)
        except JSONRPCInvalidRequestException:
            return JSONRPC20Response(error=JSONRPCInvalidRequest()._data)

        track_rpc_request(request.method)
        dispatcher = RequestDispatcher(http_request, request, task_manager)

        return cls.handle_request(request, dispatcher)
예제 #8
0
def extract_rpc_response(response: ByteString) -> JSONRPC20Response:
    """Decodes a bytestring into a JSONRPC20Response

    Args:
        response (ByteString): INcoming response from a client

    Returns:
        JSONRPC20Response: Response object
    """

    try:
        response = response.decode("utf-8")
        return JSONRPC20Response.from_json(response)
    except (json.JSONDecodeError, JSONRPCError):
        return None
예제 #9
0
    def _handle_request(self, request):
        """Execute corresponding handler for the recieved request

        Args:
            request (JSONRPCBaseRequest): Request to act upon

        Note:
            Requests are handled asynchronously if the handler returns a callable, otherwise they are handle
            synchronously by the main thread
        """
        if self._shutdown and request.method != 'exit':
            return

        output = None
        try:
            maybe_handler = self._message_handler(
                request.method,
                request.params if request.params is not None else {})
        except MissingMethodException as e:
            log.debug(e)
            # Do not need to notify client of failure with notifications
            output = JSONRPC20Response(_id=request._id,
                                       error=JSONRPCMethodNotFound()._data)
        except JSONRPCDispatchException as e:
            output = _make_response(request, error=e.error._data)
        except Exception as e:  # pylint: disable=broad-except
            log.exception(
                'synchronous method handler exception for request: %s',
                request)
            output = _make_response(request,
                                    error={
                                        'code': JSONRPCServerError.CODE,
                                        'message': traceback.format_exc()
                                    })
        else:
            if request._id in self._received_requests:
                log.error('Received request %s with duplicate id',
                          request.data)
            elif callable(maybe_handler):
                log.debug('Async request %s', request._id)
                self._handle_async_request(request, maybe_handler)
            else:
                output = _make_response(request, result=maybe_handler)
        finally:
            if not request.is_notification and output is not None:
                log.debug('Sync request %s', request._id)
                self._message_manager.write_message(output)
예제 #10
0
    def get_messages(self):
        """Generator that produces well structured JSON RPC message.

        Yields:
            message: received message

        Note:
            This method is not thread safe and should only invoked from a single thread
        """
        while not self.rfile.closed:
            request_str = self._read_message()

            if request_str is None:
                break
            if isinstance(request_str, bytes):
                request_str = request_str.decode("utf-8")

            try:
                try:
                    message_blob = json.loads(request_str)
                    request = JSONRPCRequest.from_data(message_blob)
                    if isinstance(request, JSONRPC20BatchRequest):
                        self._add_batch_request(request)
                        messages = request
                    else:
                        messages = [request]
                except JSONRPCInvalidRequestException:
                    # work around where JSONRPC20Reponse expects _id key
                    message_blob['_id'] = message_blob['id']
                    # we do not send out batch requests so no need to support batch responses
                    messages = [JSONRPC20Response(**message_blob)]
            except (KeyError, ValueError):
                log.exception("Could not parse message %s", request_str)
                continue

            for message in messages:
                yield message
예제 #11
0
    def result(self, result):
        ret = JSONRPC20Response(_id=self.rid, result=result)
        if DEBUG:
            print("-->", ret)

        self.conn.send(ret.json)
예제 #12
0
def _response(raw):
    raw['_id'] = raw['id']
    return JSONRPC20Response(**raw)