def test_batch_response(): response = BatchResponse( {SuccessResponse("foo", id=1), SuccessResponse("bar", id=2)} ) expected = [ {"jsonrpc": "2.0", "result": "foo", "id": 1}, {"jsonrpc": "2.0", "result": "bar", "id": 2}, ] assert response.wanted == True for r in response.deserialized(): assert r in expected
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))
async def call_requests(requests: Union[Request, Iterable[Request]], methods: Methods, caller: Caller, debug: bool) -> Response: if isinstance(requests, collections.Iterable): responses = (safe_call(r, methods, caller=caller, debug=debug) for r in requests) return BatchResponse(await asyncio.gather(*responses)) return await safe_call(requests, methods, caller=caller, debug=debug)
async def dispatch(self, methods, context=None): """ Process a JSON-RPC request. Calls the requested method(s), and returns the result. :param methods: Collection of methods to dispatch to. Can be a ``list`` of functions, a ``dict`` of name:method pairs, or a ``Methods`` object. :param context: Optional context object which will be passed through to the RPC methods. """ # Init may have failed to parse the request, in which case the response # would already be set if not self.response: # Batch request if isinstance(self.requests, list): # First convert each to a Request object requests = [ self.request_type(r, context=context) for r in self.requests ] # Call each request response = await asyncio.gather( *[r.call(methods) for r in requests]) for request in self.requests: self.futures.extend(request.futures) # Remove notification responses (as per spec) response = [r for r in response if not r.is_notification] # If the response list is empty, return nothing self.response = BatchResponse( response) if response else NotificationResponse() # Single request else: # Convert to a Request object request = self.request_type(self.requests, self.websocket, context=context) # Call the request self.response = await request.call(methods) self.futures.extend(request.futures) assert self.response, 'Response must be set' assert self.response.http_status, 'Must have http_status set' if config.log_responses: self.log_response(self.response) return self.response
def test(self): # pylint: disable=no-self-use str(BatchResponse())
def test(self): str(BatchResponse())
def dispatch(methods, request): """Dispatch JSON-RPC requests to a collection of methods:: r = dispatch([cat, dog], {'jsonrpc': '2.0', 'method': 'cat', 'id': 1}) The first parameter can be either: - A *list* of methods, 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, use a **dictionary**:: >>> dispatch({'cat': cat, 'max_ten': max_ten}, ...) The :mod:`methods` module also gives nice and easy ways to build the collection of methods. :param methods: Collection of methods to dispatch to. :param request: JSON-RPC request - can be a JSON-serializable object, or a string. Strings must be valid json (use double quotes!). :returns: A :mod:`response` object. """ # Process the request response = None try: # Log the request request_log.info(request) # If the request is a string, convert it to a dict first if isinstance(request, string_types): request = _string_to_dict(request) # Batch requests if isinstance(request, list): # An empty list is invalid if len(request) == 0: raise InvalidRequest() # Process each request response = BatchResponse() for r in request: try: req = Request(r) except InvalidRequest as e: resp = ExceptionResponse(e, None) else: resp = req.process(methods) response.append(resp) # Remove Notification responses response = BatchResponse([ r for r in response if not isinstance(r, NotificationResponse) ]) # "Nothing is returned for all notification batches" if not response: response = NotificationResponse() # pylint: disable=redefined-variable-type # Single request else: response = Request(request).process(methods) except JsonRpcServerError as e: response = ExceptionResponse(e, None) # Batch requests can have mixed results, just return 200 http_status = 200 if isinstance(request, list) else response.http_status # Log the response response_log.info(str(response), extra={ 'http_code': http_status, 'http_reason': HTTP_STATUS_CODES[http_status] }) return response
def dispatch(methods, request): """Dispatch JSON-RPC requests to a collection of methods:: r = dispatch([cat, dog], {'jsonrpc': '2.0', 'method': 'cat', 'id': 1}) The first parameter can be either: - A *list* of methods, 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, use a **dictionary**:: >>> dispatch({'cat': cat, 'max_ten': max_ten}, ...) The :mod:`methods` module also gives nice and easy ways to build the collection of methods. :param methods: Collection of methods to dispatch to. :param request: JSON-RPC request - can be a JSON-serializable object, or a string. Strings must be valid json (use double quotes!). :returns: A :mod:`response` object. """ # Process the request response = None try: # Log the request request_log.info(request) # If the request is a string, convert it to a dict first if isinstance(request, string_types): request = _string_to_dict(request) # Batch requests if isinstance(request, list): # An empty list is invalid if len(request) == 0: raise InvalidRequest() # Process each request response = BatchResponse() for r in request: try: req = Request(r) except InvalidRequest as e: resp = ExceptionResponse(e, None) else: resp = req.process(methods) response.append(resp) # Remove Notification responses response = BatchResponse( [r for r in response if not isinstance( r, NotificationResponse)]) # "Nothing is returned for all notification batches" if not response: response = NotificationResponse() # pylint: disable=redefined-variable-type # Single request else: response = Request(request).process(methods) except JsonRpcServerError as e: response = ExceptionResponse(e, None) # Batch requests can have mixed results, just return 200 http_status = 200 if isinstance(request, list) else response.http_status # Log the response response_log.info(str(response), extra={ 'http_code': http_status, 'http_reason': HTTP_STATUS_CODES[http_status]}) return response