def process_request(self): encoding = self.request.encoding or 'utf-8' payload = self.loads(self.request.body.decode(encoding)) if isinstance(payload, dict): # Store current request id, or None if request is a notification self.request_id = payload.get('id') return self.process_single_request(payload) elif isinstance(payload, (list, tuple)): batch_result = JSONRPCBatchResult() for single_payload in payload: try: try: request_id = single_payload.get('id') except AttributeError: request_id = None raise RPCInvalidRequest( 'Single RPC call payload must be a struct') result = self.process_single_request(single_payload) # As stated in documentation: # "A Response object SHOULD exist for each Request object, except that there SHOULD NOT be any # Response objects for notifications." if request_id: batch_result.results.append( self.json_success_response(result, override_id=request_id)) except AuthenticationFailed as e: raise e except RPCException as e: logger.warning( 'RPC Exception raised in a JSON-RPC batch handling: {}' .format(e), exc_info=settings.MODERNRPC_LOG_EXCEPTIONS) batch_result.results.append( self.json_error_response(e, override_id=request_id)) except Exception as e: logger.warning( 'Exception raised in a JSON-RPC batch handling: {}'. format(e), exc_info=settings.MODERNRPC_LOG_EXCEPTIONS) rpc_exception = RPCInternalError(str(e)) batch_result.results.append( self.json_error_response(rpc_exception, override_id=request_id)) return batch_result else: raise RPCInvalidRequest('Bad JSON-RPC payload: {}'.format( str(payload)))
def process_request(self): encoding = self.request.encoding or 'utf-8' payload = self.loads(self.request.body.decode(encoding)) if isinstance(payload, dict): # Store current request id, or None if request is a notification self.request_id = payload.get('id') return self.process_single_request(payload) elif isinstance(payload, (list, tuple)): batch_result = JSONRPCBatchResult() for single_payload in payload: try: try: request_id = single_payload.get('id') except AttributeError: request_id = None raise RPCInvalidRequest() result = self.process_single_request(single_payload) if request_id: # As stated in documentation: # "A Response object SHOULD exist for each Request object, except that there SHOULD NOT be any # Response objects for notifications." batch_result.results.append( self.json_success_response(result, override_id=request_id)) except RPCException as e: batch_result.results.append( self.json_error_response(e, override_id=request_id)) except Exception as e: rpc_exception = RPCInternalError(str(e)) batch_result.results.append( self.json_error_response(rpc_exception, override_id=request_id)) return batch_result else: raise RPCInvalidRequest()
def process_single_request(self, payload): if 'jsonrpc' not in payload: raise RPCInvalidRequest('Missing parameter "jsonrpc"') elif 'method' not in payload: raise RPCInvalidRequest('Missing parameter "method"') if payload['jsonrpc'] != '2.0': raise RPCInvalidRequest( 'The attribute "jsonrpc" must contain "2.0"') method_name = payload['method'] params = payload.get('params') args = params if isinstance(params, (list, tuple)) else [] kwargs = params if isinstance(params, dict) else {} return self.execute_procedure(method_name, args=args, kwargs=kwargs)
def process_request(self): encoding = self.request.encoding or 'utf-8' data = self.request.body.decode(encoding) params, method_name = self.loads(data) if method_name is None: raise RPCInvalidRequest('Missing methodName') return self.execute_procedure(method_name, args=params)
def loads(self, str_data): try: try: # Python 3 return xmlrpc_client.loads(str_data, use_builtin_types=settings. MODERNRPC_XMLRPC_USE_BUILTIN_TYPES) except TypeError: # Python 2 return xmlrpc_client.loads( str_data, use_datetime=settings.MODERNRPC_XMLRPC_USE_BUILTIN_TYPES) except xml.parsers.expat.ExpatError as e: raise RPCParseError(e) except xmlrpc_client.ResponseError: raise RPCInvalidRequest('Bad XML-RPC payload') except Exception as e: # pragma: no cover raise RPCInvalidRequest(e)
def can_handle(self): # Get the content-type header from incoming request. Method differs depending on current Django version try: # Django >= 1.10 content_type = self.request.content_type except AttributeError: # Django up to 1.9 content_type = self.request.META['CONTENT_TYPE'] if not content_type: # We don't accept a request with missing Content-Type request raise RPCInvalidRequest('Missing header: Content-Type') return content_type.lower() in self.valid_content_types()
def process_single_request(self, payload): if 'jsonrpc' not in payload: raise RPCInvalidRequest('Missing parameter "jsonrpc"') elif 'method' not in payload: raise RPCInvalidRequest('Missing parameter "method"') if payload['jsonrpc'] != '2.0': raise RPCInvalidRequest( 'The attribute "jsonrpc" must contains "2.0"') params = payload.get('params') if isinstance(params, (list, tuple)): rpc_request = RPCRequest(payload['method'], args=params) elif isinstance(params, dict): rpc_request = RPCRequest(payload['method'], kwargs=params) else: rpc_request = RPCRequest(payload['method']) return rpc_request.execute(self)