def _marshaled_single_dispatch(self, request, dispatch_method=None): """ Dispatches a single method call :param request: A validated request dictionary :param dispatch_method: Custom dispatch method (for method resolution) :return: A JSON-RPC response dictionary, or None if it was a notification request """ method = request.get('method') params = request.get('params') # Prepare a request-specific configuration if 'jsonrpc' not in request and self.json_config.version >= 2: # JSON-RPC 1.0 request on a JSON-RPC 2.0 # => compatibility needed config = self.json_config.copy() config.version = 1.0 else: # Keep server configuration as is config = self.json_config try: # TODO - Use the multiprocessing if it is a notification # Call the method if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params, config) except: # Return a fault exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value), config=config) return fault.dump() if 'id' not in request or request['id'] in (None, ''): # It's a notification, no result needed # Do not use 'not id' as it might be the integer 0 return None # Prepare a JSON-RPC dictionary try: return jsonrpclib.dump(response, rpcid=request['id'], is_response=True, config=config) except: # JSON conversion exception exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value), config=config) return fault.dump()
def _marshaled_single_dispatch(self, request, dispatch_method=None): """ Dispatches a single method call :param request: A validated request dictionary :param dispatch_method: Custom dispatch method (for method resolution) :return: A JSON-RPC response dictionary, or None if it was a notification request """ # TODO - Use the multiprocessing and skip the response if # it is a notification method = request.get('method') params = request.get('params') # Prepare a request-specific configuration if 'jsonrpc' not in request and self.json_config.version >= 2: # JSON-RPC 1.0 request on a JSON-RPC 2.0 # => compatibility needed config = self.json_config.copy() config.version = 1.0 else: # Keep server configuration as is config = self.json_config try: # Call the method if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params, config) except: # Return a fault exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value), config=config) return fault.dump() if 'id' not in request or request['id'] in (None, ''): # It's a notification, no result needed # Do not use 'not id' as it might be the integer 0 return None # Prepare a JSON-RPC dictionary try: # TODO: use a copy of the configuration, to JSON-RPC version return jsonrpclib.dump(response, rpcid=request['id'], is_response=True, config=config) except: # JSON conversion exception exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value), config=config) return fault.dump()
def _unmarshaled_dispatch(self, request, dispatch_method=None): """ Loads the request dictionary (unmarshaled), calls the method(s) accordingly and returns a JSON-RPC dictionary (not marshaled) :param request: JSON-RPC request dictionary (or list of) :param dispatch_method: Custom dispatch method (for method resolution) :return: A JSON-RPC dictionary (or an array of) or None if the request was a notification :raise NoMulticallResult: No result in batch """ if not request: # Invalid request dictionary fault = Fault(-32600, 'Request invalid -- no request data.', config=self.json_config) _logger.warning("Invalid request: %s", fault) return fault.dump() if isinstance(request, utils.ListType): # This SHOULD be a batch, by spec responses = [] for req_entry in request: # Validate the request result = validate_request(req_entry, self.json_config) if isinstance(result, Fault): responses.append(result.dump()) continue # Call the method resp_entry = self._marshaled_single_dispatch(req_entry, dispatch_method) # Store its result if isinstance(resp_entry, Fault): # pylint: disable=E1103 responses.append(resp_entry.dump()) elif resp_entry is not None: responses.append(resp_entry) if not responses: # No non-None result _logger.error("No result in Multicall") raise NoMulticallResult("No result") return responses else: # Single call result = validate_request(request, self.json_config) if isinstance(result, Fault): return result.dump() # Call the method response = self._marshaled_single_dispatch(request, dispatch_method) if isinstance(response, Fault): # pylint: disable=E1103 return response.dump() return response
def _marshaled_single_dispatch(self, request, dispatch_method=None): """ Dispatches a single method call :param request: A validated request dictionary :param dispatch_method: Custom dispatch method (for method resolution) :return: A JSON-RPC response dictionary, or None if it was a notification request """ # TODO - Use the multiprocessing and skip the response if # it is a notification method = request.get('method') params = request.get('params') try: # Call the method if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params) except: # Return a fault exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value)) return fault.dump() if 'id' not in request or request['id'] in (None, ''): # It's a notification, no result needed # Do not use 'not id' as it might be the integer 0 return None # Prepare a JSON-RPC dictionary try: return jsonrpclib.dump(response, rpcid=request['id'], is_response=True) except: # JSON conversion exception exc_type, exc_value, _ = sys.exc_info() fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value)) return fault.dump()
def _marshaled_single_dispatch(self, request, dispatch_method=None): """ Dispatches a single method call :param request: A validated request dictionary :param dispatch_method: Custom dispatch method (for method resolution) :return: A JSON-RPC response dictionary, or None if it was a notification request """ method = request.get('method') params = request.get('params') # Prepare a request-specific configuration if 'jsonrpc' not in request and self.json_config.version >= 2: # JSON-RPC 1.0 request on a JSON-RPC 2.0 # => compatibility needed config = self.json_config.copy() config.version = 1.0 else: # Keep server configuration as is config = self.json_config # Test if this is a notification request is_notification = 'id' not in request or request['id'] in (None, '') if is_notification and self.__notification_pool is not None: # Use the thread pool for notifications if dispatch_method is not None: self.__notification_pool.enqueue(dispatch_method, method, params) else: self.__notification_pool.enqueue(self._dispatch, method, params, config) # Return immediately return None else: # Synchronous call try: # Call the method if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params, config) except Exception as ex: # Return a fault fault = Fault(-32603, '{0}:{1}'.format(type(ex).__name__, ex), config=config) _logger.error("Error calling method %s: %s", method, fault) return fault.dump() if is_notification: # It's a notification, no result needed # Do not use 'not id' as it might be the integer 0 return None # Prepare a JSON-RPC dictionary try: return jsonrpclib.dump(response, rpcid=request['id'], is_response=True, config=config) except Exception as ex: # JSON conversion exception fault = Fault(-32603, '{0}:{1}'.format(type(ex).__name__, ex), config=config) _logger.error("Error preparing JSON-RPC result: %s", fault) return fault.dump()