diff --git a/addons/base/static/openerp/js/base_chrome.js b/addons/base/static/openerp/js/base_chrome.js index 53256f7d260..dedab94eeab 100644 --- a/addons/base/static/openerp/js/base_chrome.js +++ b/addons/base/static/openerp/js/base_chrome.js @@ -143,27 +143,28 @@ openerp.base.Session = openerp.base.BasicController.extend({ // Construct a JSON-RPC2 request, method is currently unused params.session_id = this.session_id; params.context = typeof(params.context) != "undefined" ? params.context : this.context; - var request = { jsonrpc: "2.0", method: "call", params: params, "id":null }; - - // This is a violation of the JSON-RPC2 over HTTP protocol - // specification but i don't know how to parse the raw POST content from - // cherrypy so i use a POST form with one variable named request - var post = { request: JSON.stringify(request) }; // Use a default error handler unless defined error_callback = typeof(error_callback) != "undefined" ? error_callback : this.on_rpc_error; // Call using the rpc_mode - this.rpc_ajax(url, post, success_callback, error_callback); + this.rpc_ajax(url, { + jsonrpc: "2.0", + method: "call", + params: params, + id:null + }, success_callback, error_callback); }, - rpc_ajax: function(url, post, success_callback, error_callback) { + rpc_ajax: function(url, payload, success_callback, error_callback) { var self = this; this.on_rpc_request(); $.ajax({ type: "POST", url: url, dataType: 'json', - data: post, + contentType: 'application/json', + data: JSON.stringify(payload), + processData: false, success: function(response, textStatus, jqXHR) { self.on_rpc_response(); if (response.error) { @@ -182,7 +183,7 @@ openerp.base.Session = openerp.base.BasicController.extend({ error: function(jqXHR, textStatus, errorThrown) { self.on_rpc_response(); var error = { - code: 1, + code: -32098, message: "XmlHttpRequestError " + errorThrown, data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] } }; @@ -196,7 +197,7 @@ openerp.base.Session = openerp.base.BasicController.extend({ }, on_rpc_error: function(error) { // TODO this should use the $element with focus and button is displaying OPW etc... - this.on_log(error, error.message, error.data.type, error.data.debug); + this.on_log(error.message, error.data); }, on_session_invalid: function(contination) { }, diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py index 4a795cce903..3d0db1cea14 100644 --- a/openerpweb/openerpweb.py +++ b/openerpweb/openerpweb.py @@ -1,7 +1,9 @@ #!/usr/bin/python +import functools import optparse, os, re, sys, traceback, xmlrpclib +import cherrypy import cherrypy.lib.static import simplejson @@ -79,60 +81,81 @@ class JsonRequest(object): <-- {"jsonrpc": "2.0", "error": {"code": 1, "message": "End user error message.", "data": {"code": "codestring", "debug": "traceback" } }, "id": null} """ - def __init__(self): - # result may be filled, it's content will be updated by the return - # value of the dispatched function if it's a dict - self.result = {} - self.error_type = "" - self.error_message = "" - self.error_debug = "" def parse(self, request): - self.cherrypy_request = None - self.cherrypy_session = None - d = simplejson.loads(request) - self.params = d.get("params",{}) + self.params = request.get("params",{}) self.session_id = self.params.pop("session_id", None) or "random.random" self.session = session_store.setdefault(self.session_id, OpenERPSession()) - self.context = self.params.pop("context", {}) + self.context = self.params.pop('context', None) + return self.params - def dispatch(self, controller, f, request): - try: - print "--> %s.%s %s"%(controller.__class__.__name__,f.__name__,request) - self.parse(request) - r=f(controller, self, **self.params) - if isinstance(r, dict): - self.result.update(r) - except OpenERPUnboundException,e: - self.error_type = "session_invalid" - self.error_message = "OpenERP Session Invalid" - self.error_debug = traceback.format_exc() - except xmlrpclib.Fault, e: - tb = "".join(traceback.format_exception("", None, sys.exc_traceback)) - self.error_type = "server_exception" - self.error_message = "OpenERP Server Error: %s"%e.faultCode - self.error_debug = "Client %s\nServer %s"%(tb,e.faultString) - except Exception,e: - self.error_type = "client_exception" - self.error_message = "OpenERP WebClient Error: %r"%e - self.error_debug = "Client %s"%traceback.format_exc() - r = {"jsonrpc": "2.0", "id": None} - if self.error_type: - r["error"] = {"code": 1, "message": self.error_message, "data": { "type":self.error_type, "debug": self.error_debug } } + def dispatch(self, controller, method, requestf=None, request=None): + ''' Calls the method asked for by the JSON-RPC2 request + + :param controller: the instance of the controller which received the request + :type controller: type + :param method: the method which received the request + :type method: callable + :param requestf: a file-like object containing an encoded JSON-RPC2 request + :type requestf: bytes> + :param request: an encoded JSON-RPC2 request + :type request: bytes + + :returns: a string-encoded JSON-RPC2 reply + :rtype: bytes + ''' + if requestf: + request = simplejson.load(requestf) else: - r["result"] = self.result - print "<--",r + request = simplejson.loads(request) + try: + print "--> %s.%s %s"%(controller.__class__.__name__,method.__name__,request) + error = None + result = method(controller, self, **self.parse(request)) + except OpenERPUnboundException: + error = { + 'code': 100, + 'message': "OpenERP Session Invalid", + 'data': { + 'type': 'session_invalid', + 'debug': traceback.format_exc() + } + } + except xmlrpclib.Fault, e: + error = { + 'code': 200, + 'message': "OpenERP Server Error", + 'data': { + 'type': 'server_exception', + 'fault_code': e.faultCode, + 'debug': "Client %s\nServer %s" % ("".join(traceback.format_exception("", None, sys.exc_traceback)), e.faultString) + } + } + except Exception: + error = { + 'code': 300, + 'message': "OpenERP WebClient Error", + 'data': { + 'type': 'client_exception', + 'debug': "Client %s" % traceback.format_exc() + } + } + response = {"jsonrpc": "2.0", "id": request.get('id')} + if error: + response["error"] = error + else: + response["result"] = result + + print "<--", response print - #import pprint - #pprint.pprint(r) - return simplejson.dumps(r) + return simplejson.dumps(response) def jsonrequest(f): - # check cleaner wrapping: - # functools.wraps(f)(lambda x: JsonRequest().dispatch(x, f)) - l=lambda self, request: JsonRequest().dispatch(self, f, request) - l.exposed=1 - return l + @cherrypy.expose + @functools.wraps(f) + def json_handler(self): + return JsonRequest().dispatch(self, f, requestf=cherrypy.request.body) + return json_handler class HttpRequest(object): """ Regular GET/POST request @@ -234,8 +257,9 @@ def main(argv): #'server.thread_pool' = 10, 'tools.sessions.on': True, } - cherrypy.config.update(config) - cherrypy_root = Root() - cherrypy.quickstart(cherrypy_root,'',{'/':{}}) + cherrypy.tree.mount(Root()) -# vim: + cherrypy.config.update(config) + cherrypy.server.subscribe() + cherrypy.engine.start() + cherrypy.engine.block()