async def server_handle(websocket, path): request = await websocket.recv() json_request = json.loads(request) if isinstance(json_request, list): if any(i["method"] == "test_cancel" for i in json_request): got_cancel.set_result(True) response = BatchResponse() for i in json_request: response.append(RequestResponse(i["id"], ["CANCELLED"])) elif any(i["method"] == "test_progress" for i in json_request): response = BatchResponse() for i in json_request: progress_notification = rockets.Request( "progress", {"amount": 0.5, "operation": "almost done", "id": i["id"]}, ) await websocket.send(progress_notification.json) response.append(RequestResponse(i["id"], "DONE")) else: response = await methods.dispatch(request) else: response = await methods.dispatch(request) if not response.is_notification: await websocket.send(str(response))
async def server_handle(websocket, path): request = await websocket.recv() json_request = json.loads(request) if isinstance(json_request, list): if any(i['method'] == 'test_cancel' for i in json_request): got_cancel.set_result(True) response = BatchResponse() for i in json_request: response.append(RequestResponse(i['id'], ['CANCELLED'])) elif any(i['method'] == 'test_progress' for i in json_request): response = BatchResponse() for i in json_request: progress_notification = rockets.Request( 'progress', { 'amount': 0.5, 'operation': 'almost done', 'id': i['id'] }) await websocket.send(progress_notification.json) response.append(RequestResponse(i['id'], 'DONE')) else: response = await methods.dispatch(request) else: response = await methods.dispatch(request) if not response.is_notification: await websocket.send(str(response))
def test(self): response = RequestResponse(1, 'foo') self.assertEqual({ 'jsonrpc': '2.0', 'result': 'foo', 'id': 1 }, response)
def test(self): response = RequestResponse(1, "foo") self.assertEqual({ "jsonrpc": "2.0", "result": "foo", "id": 1 }, response)
async def server_handle(websocket, path): request = await websocket.recv() json_request = json.loads(request) method = json_request['method'] if method == 'test_progress': progress_notification = rockets.Request('progress', { 'amount': 0.5, 'operation': 'almost done', 'id': json_request['id'] }) await websocket.send(progress_notification.json) response = RequestResponse(json_request['id'], 'DONE') elif method == 'test_cancel': await websocket.recv() response = RequestResponse(json_request['id'], 'CANCELLED') else: response = await methods.dispatch(request) if not response.is_notification: await websocket.send(str(response))
async def server_handle(websocket, path): request = await websocket.recv() json_request = json.loads(request) method = json_request["method"] if method == "test_progress": progress_notification = rockets.Request( "progress", { "amount": 0.5, "operation": "almost done", "id": json_request["id"] }, ) await websocket.send(progress_notification.json) response = RequestResponse(json_request["id"], "DONE") elif method == "test_cancel": await websocket.recv() response = RequestResponse(json_request["id"], "CANCELLED") else: response = await methods.dispatch(request) if not response.is_notification: await websocket.send(str(response))
def process(self, methods): """Calls the method and returns a Response object.""" error = None try: result = _call(methods, self.method_name, self.args, self.kwargs) # Catch any JsonRpcServerError raised (Invalid Request, etc) except JsonRpcServerError as e: error = e # Catch uncaught exceptions and respond with ServerError except Exception as e: # pylint: disable=broad-except # Log the uncaught exception logger.exception(e) error = e # pylint: disable=redefined-variable-type if error: if self.is_notification and not self.notification_errors: return NotificationResponse() else: return ExceptionResponse(error, self.request_id) # Success if self.is_notification: return NotificationResponse() else: return RequestResponse(self.request_id, result)
def test_str(self): response = RequestResponse(1, 'foo') self.assertEqual('{"jsonrpc": "2.0", "result": "foo", "id": 1}', str(response))
def test_no_result(self): # Perfectly fine. response = RequestResponse(1, None) self.assertEqual({'jsonrpc': '2.0', 'result': None, 'id': 1}, response)
def test_no_id(self): # Not OK - requests must have an id. with self.assertRaises(ValueError): RequestResponse(None, 'foo')
def test_no_result(self): # Perfectly fine. response = RequestResponse(1, None) self.assertEqual({"jsonrpc": "2.0", "result": None, "id": 1}, response)
def dispatch(methods, request, notification_errors=False): """Dispatch JSON-RPC requests to a list of methods:: r = dispatch([cat], {'jsonrpc': '2.0', 'method': 'cat', 'id': 1}) The first parameter can be either: - A *list* of functions, each identifiable by its ``__name__`` attribute. - Or a *dictionary* of name:method pairs. When using a **list**, the methods must be identifiable by a ``__name__`` attribute. Functions already have a ``__name__`` attribute:: >>> def cat(): ... return 'meow' ... >>> cat.__name__ 'cat' >>> dispatch([cat], ...) Lambdas require setting it:: >>> cat = lambda: 'meow' >>> cat.__name__ = 'cat' >>> dispatch([cat], ...) As do partials:: >>> max_ten = partial(min, 10) >>> max_ten.__name__ = 'max_ten' >>> dispatch([max_ten], ...) Alternatively, consider using a **dictionary** instead:: >>> dispatch({'cat': cat, 'max_ten': max_ten}, ...) See the `Methods`_ module for another easy way to build the list of methods. :param methods: List or dict of methods to dispatch to. :param request: JSON-RPC request. This can be in dict or string form. Byte arrays should be `decoded <https://docs.python.org/3/library/codecs.html#codecs.decode>`_ first. :param notification_errors: Should `notifications <http://www.jsonrpc.org/specification#notification>`_ get error responses? Typically notifications don't receive any response, except for "Parse error" and "Invalid request" errors. Enabling this will include all other errors such as "Method not found". A notification is then similar to many unix commands - *"There was no response, so I can assume the request was successful."* :returns: A `Response`_ object - either `RequestResponse`_, `NotificationResponse`_, or `ErrorResponse`_ if there was a problem processing the request. In any case, the return value gives you ``body``, ``body_debug``, ``json``, ``json_debug``, and ``http_status`` values. """ # Process the request r = None error = None try: # Log the request request_log.info(str(request)) # Create request object (also validates the request) r = Request(request) # Call the requested method result = _call(methods, r.method_name, r.args, r.kwargs) # Catch any JsonRpcServerError raised (Invalid Request, etc) except JsonRpcServerError as e: error = e # Catch uncaught exceptions, respond with ServerError except Exception as e: # pylint: disable=broad-except # Log the uncaught exception logger.exception(e) # Create an exception object, used to build the response error = ServerError(str(e)) # Now build a response. # Error if error: # Notifications get a non-response - see spec if r and r.is_notification and not notification_errors: response = NotificationResponse() else: # Get the 'id' part of the request, to include in error response request_id = r.request_id if r else None response = ErrorResponse(error.http_status, request_id, error.code, error.message, error.data) # Success else: # Notifications get a non-response if r and r.is_notification: response = NotificationResponse() else: response = RequestResponse(r.request_id, result) # Log the response and return it response_log.info(response.body, extra={ 'http_code': response.http_status, 'http_reason': HTTP_STATUS_CODES[response.http_status] }) return response