def render(self, request): t_in = time.time() request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError: return server.failure functionPath = parsed.get("method") args = parsed.get('params') id = parsed.get('id') version = parsed.get('jsonrpc') peer = request.transport.getPeer() if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault, f: self._cbRender(f, request, id, version)
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() if not content and request.method=='GET' and request.args.has_key('request'): content=request.args['request'][0] self.callback = request.args['callback'][0] if request.args.has_key('callback') else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") args = parsed.get('params', []) id = parsed.get('id') version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault, f: self._cbRender(f, request, id, version)
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() if not content and request.method=='GET' and 'request' in request.args: content=request.args['request'][0] self.callback = request.args['callback'][0] if 'callback' in request.args else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") args = parsed.get('params', []) id = parsed.get('id') version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "text/json") else: request.setHeader("content-type", "text/javascript") d = defer.maybeDeferred(function, *args) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) return server.NOT_DONE_YET
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() log.msg("Client({}): {}".format(request.client, content)) if not content and request.method == 'GET' and request.args.has_key( 'request'): content = request.args['request'][0] self.callback = request.args['callback'][0] if request.args.has_key( 'callback') else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") params = parsed.get('params', {}) args, kwargs = [], {} if params.__class__ == list: args = params else: kwargs = params id = parsed.get('id') token = None if request.requestHeaders.hasHeader(self.auth_token): token = request.requestHeaders.getRawHeaders(self.auth_token)[0] version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) d = None if hasattr(function, 'requires_auth'): d = defer.maybeDeferred(self.auth, token, functionPath) except jsonrpclib.Fault as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "application/json") else: request.setHeader("content-type", "text/javascript") if hasattr(function, 'with_request'): args = [request] + args elif d: d.addCallback(context.call, function, *args, **kwargs) else: d = defer.maybeDeferred(function, *args, **kwargs) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) def _responseFailed(err, call): call.cancel() request.notifyFinish().addErrback(_responseFailed, d) return server.NOT_DONE_YET
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() if isinstance(content, six.binary_type): content = content.decode('utf-8') log.msg("Client({}): {}".format(request.client, content)) if not content and request.method == 'GET' and 'request' in request.args: content = request.args['request'][0] self.callback = request.args['callback'][0] if 'callback' in request.args else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") params = parsed.get('params', {}) args, kwargs = [], {} if params.__class__ == list: args = params else: kwargs = params id = parsed.get('id') token = None if request.requestHeaders.hasHeader(self.auth_token): token = request.requestHeaders.getRawHeaders(self.auth_token)[0] version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) d = None if hasattr(function, 'requires_auth'): d = defer.maybeDeferred(self.auth, token, functionPath) except jsonrpclib.Fault as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "application/json") else: request.setHeader("content-type", "text/javascript") if hasattr(function, 'with_request'): args = [request] + args elif d: d.addCallback(context.call, function, *args, **kwargs) else: d = defer.maybeDeferred(function, *args, **kwargs) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) def _responseFailed(err, call): call.cancel() request.notifyFinish().addErrback(_responseFailed, d) return server.NOT_DONE_YET
def stringReceived(self, string): try: received = jsonrpclib.loads(string) except jsonrpclib.ParseError: return self.unhandledError(failure.Failure()) if "result" in received or "error" in received: return self._receivedResult(received) else: return self._receivedRequest(received)
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() if not content and request.method=='GET' and request.args.has_key('request'): content=request.args['request'][0] self.callback = request.args['callback'][0] if request.args.has_key('callback') else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") params = parsed.get('params') args, kwargs = [], {} if isinstance(params, list): args = params elif isinstance(params, dict): kwargs = params id = parsed.get('id') version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "application/json") else: request.setHeader("content-type", "text/javascript") if hasattr(function, 'with_request'): args = [request] + args d = defer.maybeDeferred(function, *args, **kwargs) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) def _responseFailed(err, call): call.cancel() request.notifyFinish().addErrback(_responseFailed, d) return server.NOT_DONE_YET
def parseResponse(self, contents): if not self.deferred: return try: # Convert the response from JSON-RPC to python. result = jsonrpclib.loads(contents) if self.version != jsonrpclib.VERSION_PRE1: result = result["result"] elif isinstance(result, list): result = result[0] except Exception, error: self.deferred.errback(error) self.deferred = None
def _cbRender(self, result, request, id, version): if self.debug == 2: request.content.seek(0, 0) content = request.content.read() if not content and request.method == 'GET' and 'request' in request.args: content = request.args['request'][0] parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") try: txt = jsonrpclib.dumps(result, id=id, version=2.0) except TypeError: txt = result self.safe_log("%s: %s" % (functionPath, lightLogVar(txt, 1000)), "DEBUG - ANSWER") return JSONRPC._cbRender(self, result, request, id, version)
def parseResponse(self, contents): if not self.deferred: return try: # Convert the response from JSON-RPC to python. result = jsonrpclib.loads(contents) #response = jsonrpclib.loads(contents) #result = response['result'] #error = response['error'] #if error: # self.deferred.errback(error) if isinstance(result, list): result = result[0] except Exception, error: self.deferred.errback(error) self.deferred = None
def parseResponse(self, contents): if not self.deferred: return try: # Convert the response from JSON-RPC to python. try: result = jsonrpclib.loads(contents) except ValueError: # In Python 3, the exception message is not very # user friendly. raise ValueError('No JSON object could be decoded') if self.version != jsonrpclib.VERSION_PRE1: result = result["result"] elif isinstance(result, list): result = result[0] except Exception as error: self.deferred.errback(error) self.deferred = None else: self.deferred.callback(result) self.deferred = None
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") args = parsed.get('params', []) id = parsed.get('id') version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault, f: self._cbRender(f, request, id, version)
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") if functionPath not in ["search", "announce_sd", "check_available"]: return server.failure args = parsed.get('params') if len(args) != 1: return server.failure arg = args[0] id = parsed.get('id') version = parsed.get('jsonrpc') try: log.info("%s@%s: %s" % (functionPath, request.getClientIP(), arg)) except Exception as err: log.error(err.message) if self.unique_clients.get(request.getClientIP(), None) is None: self.unique_clients[request.getClientIP()] = [[ functionPath, arg, time.time() ]] else: self.unique_clients[request.getClientIP()].append( [functionPath, arg, time.time()]) if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) except jsonrpclib.Fault, f: self._cbRender(f, request, id, version)
def render(self, request): request.content.seek(0, 0) # Unmarshal the JSON-RPC data. content = request.content.read() log.msg("Client({}): {}".format(request.client, content)) if not content and request.method=='GET' and request.args.has_key('request'): content=request.args['request'][0] self.callback = request.args['callback'][0] if request.args.has_key('callback') else None self.is_jsonp = True if self.callback else False parsed = jsonrpclib.loads(content) functionPath = parsed.get("method") params = parsed.get('params', {}) args, kwargs = [], {} if params.__class__ == list: args = params else: kwargs = params id = parsed.get('id') token = None if request.requestHeaders.hasHeader(self.auth_token): token = request.requestHeaders.getRawHeaders(self.auth_token)[0] version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 # XXX this all needs to be re-worked to support logic for multiple # versions... try: function = self._getFunction(functionPath) d = None if hasattr(function, 'requires_auth'): d = defer.maybeDeferred(self.auth, token, functionPath) except jsonrpclib.Fault, f: self._cbRender(f, request, id, version)
def render(self, request): time_in = utils.now() assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid finished_deferred = request.notifyFinish() if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(self.OK) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET else: session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError: log.warning("Unable to decode request json") self._render_error_string('Invalid JSON', request, None) return server.NOT_DONE_YET function_name = parsed.get('method') args = parsed.get('params', {}) id_ = parsed.get('id') token = parsed.pop('hmac', None) version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id_) reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( err, request, id_, version=version, response_code=AuthJSONRPCServer.UNAUTHORIZED) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: function = self._get_jsonrpc_method(function_name) except (UnknownAPIMethodError, NotAllowedDuringStartupError) as err: log.warning('Failed to get function %s: %s', function_name, err) self._render_error(err, request, version) return server.NOT_DONE_YET if args == EMPTY_PARAMS or args == []: d = defer.maybeDeferred(function) elif isinstance(args, dict): d = defer.maybeDeferred(function, **args) elif len(args) == 1 and isinstance(args[0], dict): # TODO: this is for backwards compatibility. Remove this once API and UI are updated # TODO: also delete EMPTY_PARAMS then d = defer.maybeDeferred(function, **args[0]) else: # d = defer.maybeDeferred(function, *args) # if we want to support positional args too raise ValueError('Args must be a dict') # finished_deferred will callback when the request is finished # and errback if something went wrong. If the errback is # called, cancel the deferred stack. This is to prevent # request.finish() from being called on a closed request. finished_deferred.addErrback(self._handle_dropped_request, d, function_name) d.addCallback(self._callback_render, request, id_, version, reply_with_next_secret) # TODO: don't trap RuntimeError, which is presently caught to # handle deferredLists that won't peacefully cancel, namely # get_lbry_files d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError) d.addErrback( log.fail(self._render_error, request, id_, version=version), 'Failed to process %s', function_name) d.addBoth(lambda _: log.debug("%s took %f", function_name, (utils.now() - time_in).total_seconds())) return server.NOT_DONE_YET
def test_loads(self): jsonInput = ["1", '"a"', '{"apple": 2}', '[1, 2, "a", "b"]'] expectedResults = [1, "a", {"apple": 2}, [1, 2, "a", "b"]] for input, expected in zip(jsonInput, expectedResults): unmarshalled = loads(input) self.assertEquals(unmarshalled, expected)
def test_loads(self): with self.assertRaises(j.ParseError): j.loads("bigboom") r = {"foo" : [1, 2, 3]} self.assertEqual(r, j.loads(json.dumps(r)))
def _render(self, request): time_in = utils.now() # assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid finished_deferred = request.notifyFinish() if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(200) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET else: session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError: log.warning("Unable to decode request json") self._render_error(JSONRPCError(None, JSONRPCError.CODE_PARSE_ERROR), request, None) return server.NOT_DONE_YET id_ = None try: function_name = parsed.get('method') args = parsed.get('params', {}) id_ = parsed.get('id', None) token = parsed.pop('hmac', None) except AttributeError as err: log.warning(err) self._render_error( JSONRPCError(None, code=JSONRPCError.CODE_INVALID_REQUEST), request, id_ ) return server.NOT_DONE_YET reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( JSONRPCError.create_from_exception( err.message, code=JSONRPCError.CODE_AUTHENTICATION_ERROR, traceback=format_exc() ), request, id_ ) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: fn = self._get_jsonrpc_method(function_name) except UnknownAPIMethodError as err: log.warning('Failed to get function %s: %s', function_name, err) self._render_error( JSONRPCError(None, JSONRPCError.CODE_METHOD_NOT_FOUND), request, id_ ) return server.NOT_DONE_YET except NotAllowedDuringStartupError: log.warning('Function not allowed during startup: %s', function_name) self._render_error( JSONRPCError("This method is unavailable until the daemon is fully started", code=JSONRPCError.CODE_INVALID_REQUEST), request, id_ ) return server.NOT_DONE_YET if args == EMPTY_PARAMS or args == []: args_dict = {} _args, _kwargs = (), {} elif isinstance(args, dict): args_dict = args elif len(args) == 1 and isinstance(args[0], dict): # TODO: this is for backwards compatibility. Remove this once API and UI are updated # TODO: also delete EMPTY_PARAMS then args_dict = args[0] _args, _kwargs = (), args else: # d = defer.maybeDeferred(function, *args) # if we want to support positional args too raise ValueError('Args must be a dict') params_error, erroneous_params = self._check_params(fn, args_dict) if params_error is not None: params_error_message = '{} for {} command: {}'.format( params_error, function_name, ', '.join(erroneous_params) ) log.warning(params_error_message) self._render_error( JSONRPCError(params_error_message, code=JSONRPCError.CODE_INVALID_PARAMS), request, id_ ) return server.NOT_DONE_YET d = defer.maybeDeferred(fn, self, **args_dict) # finished_deferred will callback when the request is finished # and errback if something went wrong. If the errback is # called, cancel the deferred stack. This is to prevent # request.finish() from being called on a closed request. finished_deferred.addErrback(self._handle_dropped_request, d, function_name) d.addCallback(self._callback_render, request, id_, reply_with_next_secret) # TODO: don't trap RuntimeError, which is presently caught to # handle deferredLists that won't peacefully cancel, namely # get_lbry_files d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError) d.addErrback(self._render_error, request, id_) d.addBoth(lambda _: log.debug("%s took %f", function_name, (utils.now() - time_in).total_seconds())) return server.NOT_DONE_YET
def _render(self, request): time_in = utils.now() # if not self._check_headers(request): # self._render_error(Failure(InvalidHeaderError()), request, None) # return server.NOT_DONE_YET session = request.getSession() session_id = session.uid finished_deferred = request.notifyFinish() if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(200) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET else: session.touch() request.content.seek(0, 0) content = request.content.read().decode() try: parsed = jsonrpclib.loads(content) except json.JSONDecodeError: log.warning("Unable to decode request json") self._render_error( JSONRPCError(None, code=JSONRPCError.CODE_PARSE_ERROR), request, None) return server.NOT_DONE_YET request_id = None try: function_name = parsed.get('method') args = parsed.get('params', {}) request_id = parsed.get('id', None) token = parsed.pop('hmac', None) except AttributeError as err: log.warning(err) self._render_error( JSONRPCError(None, code=JSONRPCError.CODE_INVALID_REQUEST), request, request_id) return server.NOT_DONE_YET reply_with_next_secret = False if self._use_authentication: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( JSONRPCError.create_from_exception( str(err), code=JSONRPCError.CODE_AUTHENTICATION_ERROR, traceback=format_exc()), request, request_id) return server.NOT_DONE_YET request.addCookie("TWISTED_SESSION", session_id) self._update_session_secret(session_id) reply_with_next_secret = True try: fn = self._get_jsonrpc_method(function_name) except UnknownAPIMethodError as err: log.warning('Failed to get function %s: %s', function_name, err) self._render_error( JSONRPCError(None, code=JSONRPCError.CODE_METHOD_NOT_FOUND), request, request_id) return server.NOT_DONE_YET if args in (EMPTY_PARAMS, []): _args, _kwargs = (), {} elif isinstance(args, dict): _args, _kwargs = (), args elif len(args) == 1 and isinstance(args[0], dict): # TODO: this is for backwards compatibility. Remove this once API and UI are updated # TODO: also delete EMPTY_PARAMS then _args, _kwargs = (), args[0] elif len(args) == 2 and isinstance(args[0], list) and isinstance( args[1], dict): _args, _kwargs = args else: raise ValueError('invalid args format') params_error, erroneous_params = self._check_params(fn, _args, _kwargs) if params_error is not None: params_error_message = '{} for {} command: {}'.format( params_error, function_name, ', '.join(erroneous_params)) log.warning(params_error_message) self._render_error( JSONRPCError(params_error_message, code=JSONRPCError.CODE_INVALID_PARAMS), request, request_id) return server.NOT_DONE_YET try: result = fn(self, *_args, **_kwargs) if isinstance(result, Deferred): d = result elif isinstance(result, Failure): d = defer.fail(result) elif asyncio.iscoroutine(result): d = Deferred.fromFuture(asyncio.ensure_future(result)) else: d = defer.succeed(result) except: d = defer.fail(Failure(captureVars=Deferred.debug)) # finished_deferred will callback when the request is finished # and errback if something went wrong. If the errback is # called, cancel the deferred stack. This is to prevent # request.finish() from being called on a closed request. finished_deferred.addErrback(self._handle_dropped_request, d, function_name) d.addCallback(self._callback_render, request, request_id, reply_with_next_secret) d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError) d.addErrback(self._render_error, request, request_id) d.addBoth(lambda _: log.debug("%s took %f", function_name, (utils.now() - time_in).total_seconds())) return server.NOT_DONE_YET
def render(self, request): notify_finish = request.notifyFinish() assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(self.OK) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError as err: log.warning("Unable to decode request json") self._render_error(err, request) return server.NOT_DONE_YET function_name = parsed.get('method') args = parsed.get('params') id = parsed.get('id') token = parsed.pop('hmac', None) version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id) try: self._run_subhandlers(request) except SubhandlerError as err: self._render_error(err, request, version) return server.NOT_DONE_YET reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( err, request, version=version, response_code=AuthJSONRPCServer.UNAUTHORIZED) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: function = self._get_jsonrpc_method(function_name) except AttributeError as err: log.warning("Unknown method: %s", function_name) self._render_error(err, request, version) return server.NOT_DONE_YET if args == [{}]: d = defer.maybeDeferred(function) else: d = defer.maybeDeferred(function, *args) # cancel the response if the connection is broken notify_finish.addErrback(self._response_failed, d) d.addCallback(self._callback_render, request, version, reply_with_next_secret) d.addErrback( log.fail(self._render_error, request, version=version), 'Failed to process %s', function_name ) return server.NOT_DONE_YET
def render(self, request): if self.open_cors: request.setHeader("Access-Control-Allow-Origin", "*") from_ip = "" if request.getHeader("x-forwarded-for"): from_ip = " from %s" % request.getHeader("x-forwarded-for") # Unmarshal the JSON-RPC data. request.content.seek(0, 0) content = request.content.read() if not content and request.method == 'GET' and 'request' in request.args: content = request.args['request'][0] self.callback = request.args['callback'][0] if 'callback' in request.args else None self.is_jsonp = True if self.callback else False try: parsed = jsonrpclib.loads(content) except ValueError: parsed = {"content": content, "method": None, "params": {}} functionPath = parsed.get("method") if self.debug: parsedcopy = deepcopy(parsed) if functionPath in ["start_corpus", "create_corpus"] and len(parsedcopy["params"]) > 1: parsedcopy["params"][1] = "********" self.safe_log(parsedcopy, "DEBUG - QUERY%s" % from_ip) params = parsed.get('params', {}) args, kwargs = [], {} if params.__class__ == list: args = params else: kwargs = params id = parsed.get('id') token = None #if request.requestHeaders.hasHeader(self.auth_token): # token = request.requestHeaders.getRawHeaders(self.auth_token)[0] version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 try: function = self._getFunction(functionPath) d = None #if hasattr(function, 'requires_auth'): # d = maybeDeferred(self.auth, token, functionPath) except (jsonrpclib.Fault, AttributeError) as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "application/json") else: request.setHeader("content-type", "text/javascript") if hasattr(function, 'with_request'): args = [request] + args elif d: d.addCallback(context.call, function, *args, **kwargs) else: d = maybeDeferred(function, *args, **kwargs) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) def _responseFailed(err, call): call.cancel() request.notifyFinish().addErrback(_responseFailed, d) return server.NOT_DONE_YET
def render(self, request): notify_finish = request.notifyFinish() assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(self.OK) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError as err: log.warning("Unable to decode request json") self._render_error(err, request) return server.NOT_DONE_YET function_name = parsed.get('method') args = parsed.get('params') id = parsed.get('id') token = parsed.pop('hmac', None) version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id) try: self._run_subhandlers(request) except SubhandlerError as err: self._render_error(err, request, version) return server.NOT_DONE_YET reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( err, request, version=version, response_code=AuthJSONRPCServer.UNAUTHORIZED) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: function = self._get_jsonrpc_method(function_name) except AttributeError as err: log.warning("Unknown method: %s", function_name) self._render_error(err, request, version) return server.NOT_DONE_YET if args == [{}]: d = defer.maybeDeferred(function) else: d = defer.maybeDeferred(function, *args) # cancel the response if the connection is broken notify_finish.addErrback(self._response_failed, d) d.addCallback(self._callback_render, request, version, reply_with_next_secret) d.addErrback(self._log_and_render_error, request, version=version) return server.NOT_DONE_YET
def _render(self, request): time_in = utils.now() # assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid finished_deferred = request.notifyFinish() if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(200) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET else: session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError: log.warning("Unable to decode request json") self._render_error( JSONRPCError(None, JSONRPCError.CODE_PARSE_ERROR), request, None) return server.NOT_DONE_YET id_ = None try: function_name = parsed.get('method') is_queued = function_name in self.queued_methods args = parsed.get('params', {}) id_ = parsed.get('id', None) token = parsed.pop('hmac', None) except AttributeError as err: log.warning(err) self._render_error( JSONRPCError(None, code=JSONRPCError.CODE_INVALID_REQUEST), request, id_) return server.NOT_DONE_YET reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( JSONRPCError.create_from_exception( err.message, code=JSONRPCError.CODE_AUTHENTICATION_ERROR, traceback=format_exc()), request, id_) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: function = self._get_jsonrpc_method(function_name) except UnknownAPIMethodError as err: log.warning('Failed to get function %s: %s', function_name, err) self._render_error( JSONRPCError(None, JSONRPCError.CODE_METHOD_NOT_FOUND), request, id_) return server.NOT_DONE_YET except NotAllowedDuringStartupError as err: log.warning('Function not allowed during startup %s: %s', function_name, err) self._render_error( JSONRPCError( "This method is unavailable until the daemon is fully started", code=JSONRPCError.CODE_INVALID_REQUEST), request, id_) return server.NOT_DONE_YET except DeprecatedAPIMethodError: log.warning('API function is deprecated %s', function_name) self._render_error( JSONRPCError(None, JSONRPCError.CODE_METHOD_NOT_FOUND), request, id_) return server.NOT_DONE_YET if args == EMPTY_PARAMS or args == []: args_dict = {} _args, _kwargs = (), {} elif isinstance(args, dict): args_dict = args elif len(args) == 1 and isinstance(args[0], dict): # TODO: this is for backwards compatibility. Remove this once API and UI are updated # TODO: also delete EMPTY_PARAMS then args_dict = args[0] _args, _kwargs = (), args elif isinstance(args, list): _args, _kwargs = args, {} else: # d = defer.maybeDeferred(function, *args) # if we want to support positional args too raise ValueError('Args must be a dict') params_error, erroneous_params = self._check_params( function, args_dict) if params_error is not None: params_error_message = '{} for {} command: {}'.format( params_error, function_name, ', '.join(erroneous_params)) log.warning(params_error_message) self._render_error( JSONRPCError(params_error_message, code=JSONRPCError.CODE_INVALID_PARAMS), request, id_) return server.NOT_DONE_YET if is_queued: d_lock = self._call_lock.get(function_name, False) if not d_lock: d = defer.maybeDeferred(function, self, **args_dict) self._call_lock[function_name] = finished_deferred def _del_lock(*args): if function_name in self._call_lock: del self._call_lock[function_name] if args: return args finished_deferred.addCallback(_del_lock) else: log.info("queued %s", function_name) d = d_lock d.addBoth( lambda _: log.info("running %s from queue", function_name)) d.addCallback( lambda _: defer.maybeDeferred(function, self, **args_dict)) else: d = defer.maybeDeferred(function, self, **args_dict) # finished_deferred will callback when the request is finished # and errback if something went wrong. If the errback is # called, cancel the deferred stack. This is to prevent # request.finish() from being called on a closed request. finished_deferred.addErrback(self._handle_dropped_request, d, function_name) d.addCallback(self._callback_render, request, id_, reply_with_next_secret) # TODO: don't trap RuntimeError, which is presently caught to # handle deferredLists that won't peacefully cancel, namely # get_lbry_files d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError) d.addErrback(log.fail(self._render_error, request, id_), 'Failed to process %s', function_name) d.addBoth(lambda _: log.debug("%s took %f", function_name, (utils.now() - time_in).total_seconds())) return server.NOT_DONE_YET
def render(self, request): time_in = utils.now() assert self._check_headers(request), InvalidHeaderError session = request.getSession() session_id = session.uid finished_deferred = request.notifyFinish() if self._use_authentication: # if this is a new session, send a new secret and set the expiration # otherwise, session.touch() if self._initialize_session(session_id): def expire_session(): self._unregister_user_session(session_id) session.startCheckingExpiration() session.notifyOnExpire(expire_session) message = "OK" request.setResponseCode(self.OK) self._set_headers(request, message, True) self._render_message(request, message) return server.NOT_DONE_YET else: session.touch() request.content.seek(0, 0) content = request.content.read() try: parsed = jsonrpclib.loads(content) except ValueError: log.warning("Unable to decode request json") self._render_error_string('Invalid JSON', request, None) return server.NOT_DONE_YET function_name = parsed.get('method') args = parsed.get('params', {}) id_ = parsed.get('id') token = parsed.pop('hmac', None) version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id_) reply_with_next_secret = False if self._use_authentication: if function_name in self.authorized_functions: try: self._verify_token(session_id, parsed, token) except InvalidAuthenticationToken as err: log.warning("API validation failed") self._render_error( err, request, id_, version=version, response_code=AuthJSONRPCServer.UNAUTHORIZED) return server.NOT_DONE_YET self._update_session_secret(session_id) reply_with_next_secret = True try: function = self._get_jsonrpc_method(function_name) except (UnknownAPIMethodError, NotAllowedDuringStartupError) as err: log.warning('Failed to get function %s: %s', function_name, err) self._render_error(err, request, version) return server.NOT_DONE_YET if args == EMPTY_PARAMS or args == []: d = defer.maybeDeferred(function) elif isinstance(args, dict): d = defer.maybeDeferred(function, **args) elif len(args) == 1 and isinstance(args[0], dict): # TODO: this is for backwards compatibility. Remove this once API and UI are updated # TODO: also delete EMPTY_PARAMS then d = defer.maybeDeferred(function, **args[0]) else: # d = defer.maybeDeferred(function, *args) # if we want to support positional args too raise ValueError('Args must be a dict') # finished_deferred will callback when the request is finished # and errback if something went wrong. If the errback is # called, cancel the deferred stack. This is to prevent # request.finish() from being called on a closed request. finished_deferred.addErrback(self._handle_dropped_request, d, function_name) d.addCallback(self._callback_render, request, id_, version, reply_with_next_secret) # TODO: don't trap RuntimeError, which is presently caught to # handle deferredLists that won't peacefully cancel, namely # get_lbry_files d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError) d.addErrback(log.fail(self._render_error, request, id_, version=version), 'Failed to process %s', function_name) d.addBoth(lambda _: log.debug("%s took %f", function_name, (utils.now() - time_in).total_seconds())) return server.NOT_DONE_YET
def render(self, request): if self.open_cors: request.setHeader("Access-Control-Allow-Origin", "*") from_ip = "" if request.getHeader("x-forwarded-for"): from_ip = " from %s" % request.getHeader("x-forwarded-for") # Unmarshal the JSON-RPC data. request.content.seek(0, 0) content = request.content.read() if not content and request.method == 'GET' and 'request' in request.args: content = request.args['request'][0] self.callback = request.args['callback'][ 0] if 'callback' in request.args else None self.is_jsonp = True if self.callback else False try: parsed = jsonrpclib.loads(content) except ValueError: parsed = {"content": content, "method": None, "params": {}} functionPath = parsed.get("method") if self.debug: parsedcopy = deepcopy(parsed) if functionPath in ["start_corpus", "create_corpus" ] and len(parsedcopy["params"]) > 1: parsedcopy["params"][1] = "********" self.safe_log(parsedcopy, "DEBUG - QUERY%s" % from_ip) params = parsed.get('params', {}) args, kwargs = [], {} if params.__class__ == list: args = params else: kwargs = params id = parsed.get('id') token = None #if request.requestHeaders.hasHeader(self.auth_token): # token = request.requestHeaders.getRawHeaders(self.auth_token)[0] version = parsed.get('jsonrpc') if version: version = int(float(version)) elif id and not version: version = jsonrpclib.VERSION_1 else: version = jsonrpclib.VERSION_PRE1 if not functionPath: self._cbRender({}, request, id, version) return server.NOT_DONE_YET try: function = self._getFunction(functionPath) d = None #if hasattr(function, 'requires_auth'): # d = maybeDeferred(self.auth, token, functionPath) except (jsonrpclib.Fault, AttributeError) as f: self._cbRender(f, request, id, version) else: if not self.is_jsonp: request.setHeader("content-type", "application/json") else: request.setHeader("content-type", "text/javascript") if hasattr(function, 'with_request'): args = [request] + args elif d: d.addCallback(context.call, function, *args, **kwargs) else: d = maybeDeferred(function, *args, **kwargs) d.addErrback(self._ebRender, id) d.addCallback(self._cbRender, request, id, version) def _responseFailed(err, call): call.cancel() request.notifyFinish().addErrback(_responseFailed, d) return server.NOT_DONE_YET