From 542180912072c807a46d8773e90b203db7b86135 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Thu, 18 Aug 2011 20:36:56 +0200 Subject: [PATCH] [IMP] factorize http request handling bzr revid: al@openerp.com-20110818183656-qp9zy271jl6wccq9 --- addons/base/controllers/main.py | 27 ++++----- openerpweb/openerpweb.py | 98 +++++++++++++-------------------- 2 files changed, 51 insertions(+), 74 deletions(-) diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 65e061211f8..8663a22d885 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -87,9 +87,9 @@ def concat_files(file_list): ftime = os.path.getmtime(fname) if ftime > files_timestamp: files_timestamp = ftime - files_content = open(fname).read() + files_content.append(open(fname).read()) files_concat = "".join(files_content) - return files_concat + return (files_concat,files_timestamp) home_template = textwrap.dedent(""" @@ -127,17 +127,17 @@ class WebClient(openerpweb.Controller): def css(self, req, mods='base'): cherrypy.response.headers['Content-Type'] = 'text/css' files = manifest_glob(mods.split(','), 'css') - concat = concat_files(files)[0] + content,timestamp = concat_files(files) # TODO request set the Date of last modif and Etag - return concat + return content @openerpweb.httprequest def js(self, req, mods='base'): cherrypy.response.headers['Content-Type'] = 'application/javascript' files = manifest_glob(mods.split(','), 'js') - concat = concat_files(files)[0] + content,timestamp = concat_files(files) # TODO request set the Date of last modif and Etag - return concat + return content @openerpweb.httprequest def home(self, req, s_action=None): @@ -157,7 +157,7 @@ class WebClient(openerpweb.Controller): 'css': css } return r - + @openerpweb.jsonrequest def translations(self, req, mods, lang): lang_model = req.session.model('res.lang') @@ -193,7 +193,6 @@ class WebClient(openerpweb.Controller): transl["messages"].append({'id': x.id, 'string': x.string}) return {"modules": transs, "lang_parameters": lang_obj} - class Database(openerpweb.Controller): _cp_path = "/base/database" @@ -439,18 +438,16 @@ def clean_action(action, session, context=None): return action # values come from the server, we can just eval them if isinstance(action.get('context'), basestring): - action['context'] = eval( - action['context'], - session.evaluation_context(context=context)) or {} + localvars = session.evaluation_context(context=context) + action['context'] = eval( action['context'], localvars ) or {} if isinstance(action.get('domain'), basestring): - action['domain'] = eval( - action['domain'], - session.evaluation_context( - action.get('context', {}))) or [] + localvars = session.evaluation_context( action.get('context', {})) + action['domain'] = eval( action['domain'], localvars ) or [] return fix_view_modes(action) +# I think generate_views,fix_view_modes should go into js ActionManager def generate_views(action): """ While the server generates a sequence called "views" computing dependencies diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py index 0f6b7f8031e..4bf490eba90 100644 --- a/openerpweb/openerpweb.py +++ b/openerpweb/openerpweb.py @@ -233,7 +233,25 @@ class OpenERPSession(object): #---------------------------------------------------------- # OpenERP Web RequestHandler #---------------------------------------------------------- -class JsonRequest(object): +class CherryPyRequest(object): + """ CherryPy request handling + """ + def init(self,params): + self.params = params + # Move cherrypy thread local objects to attributes + self.applicationsession = applicationsession + self.httprequest = cherrypy.request + self.httpresponse = cherrypy.response + self.httpsession = cherrypy.session + self.httpsession_id = "cookieid" + # OpenERP session setup + self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex + host = cherrypy.config['openerp.server.host'] + port = cherrypy.config['openerp.server.port'] + self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port)) + self.context = self.params.pop('context', None) + +class JsonRequest(CherryPyRequest): """ JSON-RPC2 over HTTP. Sucessful request:: @@ -267,48 +285,27 @@ class JsonRequest(object): """ - def parse(self, request): - self.request = request - self.params = request.get("params", {}) - self.applicationsession = applicationsession - self.httprequest = cherrypy.request - self.httpresponse = cherrypy.response - self.httpsession = cherrypy.session - self.httpsession_id = "cookieid" - self.httpsession = cherrypy.session - self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex - host = cherrypy.config['openerp.server.host'] - port = cherrypy.config['openerp.server.port'] - self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port)) - self.context = self.params.pop('context', None) - return self.params - 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 + :param request: a JSON-RPC2 request - :returns: a string-encoded JSON-RPC2 reply - :rtype: bytes + :returns: an utf8 encoded JSON-RPC2 reply """ - # Read POST content or POST Form Data named "request" - if requestf: - request = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder) - else: - request = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder) - - response = {"jsonrpc": "2.0", "id": request.get('id')} + response = {"jsonrpc": "2.0" } + error = None try: - print "--> %s.%s %s" % (controller.__class__.__name__, method.__name__, request) - error = None - self.parse(request) + # Read POST content or POST Form Data named "request" + if requestf: + self.jsonrequest = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder) + else: + self.jsonrequest = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder) + print "--> %s.%s %s" % (controller.__class__.__name__, method.__name__, self.jsonrequest) + self.init(self.jsonrequest.get("params", {})) + response['id'] = self.jsonrequest.get('id') response["result"] = method(controller, self, **self.params) except OpenERPUnboundException: error = { @@ -357,41 +354,24 @@ def jsonrequest(f): @functools.wraps(f) def json_handler(controller): return JsonRequest().dispatch(controller, f, requestf=cherrypy.request.body) - return json_handler -class HttpRequest(object): +class HttpRequest(CherryPyRequest): """ Regular GET/POST request """ - def dispatch(self, controller, f, request, **kw): - self.request = request - self.applicationsession = applicationsession - self.httpsession_id = "cookieid" - self.httpsession = cherrypy.session - self.context = kw.get('context', {}) - host = cherrypy.config['openerp.server.host'] - port = cherrypy.config['openerp.server.port'] - self.session_id = kw.pop('session_id', None) - self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port)) - self.result = "" - if request.method == 'GET': - print "GET --> %s.%s %s %r" % (controller.__class__.__name__, f.__name__, request, kw) - else: - akw = dict([(key, kw[key] if isinstance(kw[key], basestring) else type(kw[key])) for key in kw.keys()]) - print "POST --> %s.%s %s %r" % (controller.__class__.__name__, f.__name__, request, akw) - r = f(controller, self, **kw) - if isinstance(r, str): - print "<--", len(r), 'bytes' - else: - print "<--", len(r), 'characters' + def dispatch(self, controller, method, **kw): + self.init(kw) + print "%s --> %s %s.%s %r" % (self.httprequest.method, controller.__class__.__name__, method.__name__, self.httprequest, kw) + r = method(controller, self, **kw) + print "<--", 'size:', len(r) print return r def httprequest(f): # check cleaner wrapping: # functools.wraps(f)(lambda x: JsonRequest().dispatch(x, f)) - def http_handler(self,*l, **kw): - return HttpRequest().dispatch(self, f, cherrypy.request, **kw) + def http_handler(controller,*l, **kw): + return HttpRequest().dispatch(controller, f, **kw) http_handler.exposed = 1 return http_handler