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()