websockets: Make the JsonRPC class more generic
Allow JsonRPC to be used with transports other than the websocket. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
06bbca7ae3
commit
a7801db6e7
|
@ -142,8 +142,9 @@ class WebRequest:
|
||||||
return self._get_converted_arg(key, default, bool)
|
return self._get_converted_arg(key, default, bool)
|
||||||
|
|
||||||
class JsonRPC:
|
class JsonRPC:
|
||||||
def __init__(self) -> None:
|
def __init__(self, transport: str = "Websocket") -> None:
|
||||||
self.methods: Dict[str, RPCCallback] = {}
|
self.methods: Dict[str, RPCCallback] = {}
|
||||||
|
self.transport = transport
|
||||||
|
|
||||||
def register_method(self,
|
def register_method(self,
|
||||||
name: str,
|
name: str,
|
||||||
|
@ -156,35 +157,35 @@ class JsonRPC:
|
||||||
|
|
||||||
async def dispatch(self,
|
async def dispatch(self,
|
||||||
data: str,
|
data: str,
|
||||||
ws: WebSocket
|
conn: Optional[WebSocket] = None
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
response: Any = None
|
response: Any = None
|
||||||
try:
|
try:
|
||||||
request: Union[Dict[str, Any], List[dict]] = json.loads(data)
|
request: Union[Dict[str, Any], List[dict]] = json.loads(data)
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = f"Websocket data not json: {data}"
|
msg = f"{self.transport} data not json: {data}"
|
||||||
logging.exception(msg)
|
logging.exception(msg)
|
||||||
response = self.build_error(-32700, "Parse error")
|
response = self.build_error(-32700, "Parse error")
|
||||||
return json.dumps(response)
|
return json.dumps(response)
|
||||||
logging.debug(f"Websocket Request::{data}")
|
logging.debug(f"{self.transport} Request::{data}")
|
||||||
if isinstance(request, list):
|
if isinstance(request, list):
|
||||||
response = []
|
response = []
|
||||||
for req in request:
|
for req in request:
|
||||||
resp = await self.process_request(req, ws)
|
resp = await self.process_request(req, conn)
|
||||||
if resp is not None:
|
if resp is not None:
|
||||||
response.append(resp)
|
response.append(resp)
|
||||||
if not response:
|
if not response:
|
||||||
response = None
|
response = None
|
||||||
else:
|
else:
|
||||||
response = await self.process_request(request, ws)
|
response = await self.process_request(request, conn)
|
||||||
if response is not None:
|
if response is not None:
|
||||||
response = json.dumps(response)
|
response = json.dumps(response)
|
||||||
logging.debug("Websocket Response::" + response)
|
logging.debug(f"{self.transport} Response::{response}")
|
||||||
return response
|
return response
|
||||||
|
|
||||||
async def process_request(self,
|
async def process_request(self,
|
||||||
request: Dict[str, Any],
|
request: Dict[str, Any],
|
||||||
ws: WebSocket
|
conn: Optional[WebSocket]
|
||||||
) -> Optional[Dict[str, Any]]:
|
) -> Optional[Dict[str, Any]]:
|
||||||
req_id: Optional[int] = request.get('id', None)
|
req_id: Optional[int] = request.get('id', None)
|
||||||
rpc_version: str = request.get('jsonrpc', "")
|
rpc_version: str = request.get('jsonrpc', "")
|
||||||
|
@ -198,25 +199,28 @@ class JsonRPC:
|
||||||
params = request['params']
|
params = request['params']
|
||||||
if isinstance(params, list):
|
if isinstance(params, list):
|
||||||
response = await self.execute_method(
|
response = await self.execute_method(
|
||||||
method, req_id, ws, *params)
|
method, req_id, conn, *params)
|
||||||
elif isinstance(params, dict):
|
elif isinstance(params, dict):
|
||||||
response = await self.execute_method(
|
response = await self.execute_method(
|
||||||
method, req_id, ws, **params)
|
method, req_id, conn, **params)
|
||||||
else:
|
else:
|
||||||
return self.build_error(-32600, "Invalid Request", req_id)
|
return self.build_error(-32600, "Invalid Request", req_id)
|
||||||
else:
|
else:
|
||||||
response = await self.execute_method(method, req_id, ws)
|
response = await self.execute_method(method, req_id, conn)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
async def execute_method(self,
|
async def execute_method(self,
|
||||||
method: RPCCallback,
|
method: RPCCallback,
|
||||||
req_id: Optional[int],
|
req_id: Optional[int],
|
||||||
ws: WebSocket,
|
conn: Optional[WebSocket],
|
||||||
*args,
|
*args,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> Optional[Dict[str, Any]]:
|
) -> Optional[Dict[str, Any]]:
|
||||||
try:
|
try:
|
||||||
result = await method(ws, *args, **kwargs)
|
if conn is not None:
|
||||||
|
result = await method(conn, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
result = await method(*args, **kwargs)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
return self.build_error(
|
return self.build_error(
|
||||||
-32603, f"Invalid params:\n{e}", req_id, True)
|
-32603, f"Invalid params:\n{e}", req_id, True)
|
||||||
|
|
Loading…
Reference in New Issue