100 lines
3.3 KiB
Python
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()
|