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
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))
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)
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
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')
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(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)
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
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)
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
def result(self, result): ret = JSONRPC20Response(_id=self.rid, result=result) if DEBUG: print("-->", ret) self.conn.send(ret.json)
def _response(raw): raw['_id'] = raw['id'] return JSONRPC20Response(**raw)