X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/python-jsonrpclib.git/blobdiff_plain/9cb9396c901daeeb9bf47675bbce707671b5e6af..1cb797f048ae5131a01086a93d87952c03e8abe7:/jsonrpclib/SimpleJSONRPCServer.py diff --git a/jsonrpclib/SimpleJSONRPCServer.py b/jsonrpclib/SimpleJSONRPCServer.py index f049f85..75193b2 100644 --- a/jsonrpclib/SimpleJSONRPCServer.py +++ b/jsonrpclib/SimpleJSONRPCServer.py @@ -8,20 +8,35 @@ import fcntl import sys def get_version(request): - if type(request) not in (types.ListType, types.DictType): - return None - if type(request) is types.ListType: - if len(request) == 0: - return None - if 'jsonrpc' not in request[0].keys(): - return None - return '2.0' # must be a dict if 'jsonrpc' in request.keys(): return 2.0 if 'id' in request.keys(): return 1.0 return None + +def validate_request(request): + if type(request) is not types.DictType: + fault = Fault( + -32600, 'Request must be {}, not %s.' % type(request) + ) + return fault + rpcid = request.get('id', None) + version = get_version(request) + if not version: + fault = Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid) + return fault + request.setdefault('params', []) + method = request.get('method', None) + params = request.get('params') + param_types = (types.ListType, types.DictType, types.TupleType) + if not method or type(method) not in types.StringTypes or \ + type(params) not in param_types: + fault = Fault( + -32600, 'Invalid request parameters or method.', rpcid=rpcid + ) + return fault + return True class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher): @@ -34,34 +49,42 @@ class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher): response = None try: request = jsonrpclib.loads(data) - except: - fault = Fault(-32600, 'Request %s invalid.' % data) - response = fault.response() - return response - version = get_version(request) - if not version: - fault = Fault(-32600, 'Request %s invalid.' % data) + except Exception, e: + fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e)) response = fault.response() return response + if not request: + fault = Fault(-32600, 'Request invalid -- no request data.') + return fault.response() if type(request) is types.ListType: # This SHOULD be a batch, by spec responses = [] for req_entry in request: + result = validate_request(req_entry) + if type(result) is Fault: + responses.append(result.response()) + continue resp_entry = self._marshaled_single_dispatch(req_entry) if resp_entry is not None: responses.append(resp_entry) - response = '[%s]' % ','.join(responses) - else: + if len(responses) > 0: + response = '[%s]' % ','.join(responses) + else: + response = '' + else: + result = validate_request(request) + if type(result) is Fault: + return result.response() response = self._marshaled_single_dispatch(request) return response def _marshaled_single_dispatch(self, request): # TODO - Use the multiprocessing and skip the response if # it is a notification - method = request['method'] - params = request['params'] # Put in support for custom dispatcher here # (See SimpleXMLRPCServer._marshaled_dispatch) + method = request.get('method') + params = request.get('params') try: response = self._dispatch(method, params) except: