diff --git a/netforce_clinic/controllers/__init__.py b/netforce_clinic/controllers/__init__.py index e69de29..c24bd68 100644 --- a/netforce_clinic/controllers/__init__.py +++ b/netforce_clinic/controllers/__init__.py @@ -0,0 +1 @@ +from . import json_rpc diff --git a/netforce_clinic/controllers/json_rpc.py b/netforce_clinic/controllers/json_rpc.py new file mode 100644 index 0000000..a465fb8 --- /dev/null +++ b/netforce_clinic/controllers/json_rpc.py @@ -0,0 +1,99 @@ +from netforce.controller import Controller +from netforce.model import get_model, clear_cache +from netforce import database +from netforce import access +import json +import traceback +import sys +import time +import random +from netforce.locale import translate +from netforce.utils import timeout +from netforce.log import rpc_log + + +class JsonRpc(Controller): + _path = "/json_rpc" + + def get(self): + self.render("base/json_rpc.xml") + + def post(self): + req = json.loads(self.request.body.decode()) + # open("/tmp/json_rpc.log","a").write(self.request.body.decode()+"\n###############################################################\n") + db = database.get_connection() + if db: + db.begin() + try: + clear_cache() + method = req["method"] + params = req["params"] + if method == "execute": + model = params[0] + method = params[1] + if method.startswith("_"): + raise Exception("Invalid method") + args = params[2] + if len(params) >= 4: + opts = params[3] or {} + else: + opts = {} + user_id = access.get_active_user() + rpc_log.info("EXECUTE db=%s model=%s method=%s user=%s" % + (database.get_active_db(), model, method, user_id)) + m = get_model(model) + f = getattr(m, method) + ctx = { + "request_handler": self, + "request": self.request, + } + ctx.update(self.get_cookies()) + opts.setdefault("context", {}).update(ctx) + with timeout(seconds=900): # XXX: can make this faster? (less signal sys handler overhead) + t0 = time.time() + res = f(*args, **opts) + t1 = time.time() + dt = (t1 - t0) * 1000 + rpc_log.info("<<< %d ms" % dt) + resp = { + "result": res, + "error": None, + "id": req["id"], + } + else: + raise Exception("Invalid method: %s" % method) + db = database.get_connection() + if db: + db.commit() + except Exception as e: + try: + msg = translate(str(e)) + except: + print("WARNING: Failed to translate error message") + msg = str(e) + rpc_log.error(msg) + db = database.get_connection() + if db: + db.rollback() + rpc_log.error(traceback.format_exc()) + err = { + "message": msg, + } + error_fields = getattr(e, "error_fields", None) + if error_fields: + err["error_fields"] = error_fields + resp = { + "result": None, + "error": err, + "id": req["id"], + } + access.clear_active_user() + try: + data = json.dumps(resp) + except: + print("JSONRPC ERROR: invalid response") + from pprint import pprint + pprint(resp) + self.write(data) + +JsonRpc.register()