clinic/netforce_clinic/controllers/json_rpc.py

100 lines
3.3 KiB
Python

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