[IMP] jsonp dispatch

bzr revid: al@openerp.com-20111214092933-77vn7s5jxvi5i72f
This commit is contained in:
Antony Lesuisse 2011-12-14 10:29:33 +01:00
parent e0ac8e3fa4
commit 26f690fc5e
1 changed files with 38 additions and 109 deletions

View File

@ -89,21 +89,11 @@ class WebRequest(object):
self.config = config
self.session = None
def init_session(self, session_id):
if self.session:
assert self.session.id == session_id
return
self.session_id = session_id or uuid.uuid4().hex
self.session = self.httpsession.setdefault(self.session_id, session.OpenERPSession(self.session_id))
self.session.config = self.config
def init(self, params):
self.params = dict(params)
# OpenERP session setup
session_id = self.params.pop("session_id", None)
self.init_session(session_id)
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
self.session = self.httpsession.setdefault(self.session_id, session.OpenERPSession(self.session_id))
self.session.config = self.config
self.context = self.params.pop('context', None)
self.debug = self.params.pop('debug', False) != False
@ -140,37 +130,6 @@ class JsonRequest(WebRequest):
"id": null}
"""
def _init_jsonrpc2(self):
assert self.jsonrequest.get('jsonrpc') == '2.0'
self.init(self.jsonrequest.get("params", {}))
response = {"jsonrpc": "2.0" }
def build_response(response):
content = simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder)
return werkzeug.wrappers.Response(
content, headers=[('Content-Type', 'application/json'),
('Content-Length', len(content))])
return response, build_response
def _init_jsonp(self, callback):
self.init(self.jsonrequest)
def build_response(response):
content = "%s(%s);" % (\
callback,
simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder),
)
return werkzeug.wrappers.Response(
content, headers=[('Content-Type', 'application/javascript'),
('Content-Length', len(content))])
return {}, build_response
def dispatch(self, controller, method):
""" Calls the method asked for by the JSON-RPC2 or JSONP request
@ -179,54 +138,36 @@ class JsonRequest(WebRequest):
:returns: an utf8 encoded JSON-RPC2 or JSONP reply
"""
method = self.httprequest.method
args = self.httprequest.args
jsonp = args.get('jsonp', False)
requestf = self.httprequest.stream
direct_json_request = None
jsonp_callback = None
rid = None
if requestf:
direct_json_request = requestf.read()
if not direct_json_request:
params = self.httprequest.args
direct_json_request = params.get('r')
jsonp_callback = params.get('callback')
if direct_json_request:
try:
self.jsonrequest = simplejson.loads(direct_json_request, object_hook=nonliterals.non_literal_decoder)
except Exception, e:
_logger.exception(e)
return werkzeug.exceptions.BadRequest(e)
if jsonp and args.get('r'):
# jsonp method GET
requestf = StringIO.StringIO(args.get('r'))
elif jsonp and method == 'POST':
# jsonp 2 steps step1 POST: save call
self.init(args)
req.session.jsonp_requests[args.get('id')] = self.httprequest.form['r']
headers=[('Content-Type', 'text/plain; charset=utf-8')]
r = werkzeug.wrappers.Response(request_id, headers=headers)
return r
elif args['jsonp'] and args.get('id'):
# jsonp 2 steps step2 GET: run and return result
self.init(args)
requestf = StringIO.StringIO(self.session.jsonp_requests.pop(args.get(id), ""))
else:
# no direct json request, try to get it from jsonp POST request
params = self.httprequest.args
rid = params.get('rid')
session_id = params.get('sid')
if session_id:
self.init_session(session_id)
stored_request = self.session.jsonp_requests.pop(rid, {})
else:
stored_request = {}
jsonp_callback = stored_request.get('jsonp')
self.jsonrequest = stored_request.get('params', {})
if self.jsonrequest.get('jsonrpc') == '2.0':
response, build_response = self._init_jsonrpc2()
elif jsonp_callback:
response, build_response = self._init_jsonp(jsonp_callback)
else:
return werkzeug.exceptions.BadRequest()
# regular jsonrpc2
requestf = self.httprequest.stream
self.init(self.jsonrequest.get("params", {}))
response = {"jsonrpc": "2.0" }
error = None
if not rid:
rid = self.jsonrequest.get('id')
try:
self.jsonrequest = simplejson.loads(direct_json_request, object_hook=nonliterals.non_literal_decoder)
self.init(self.jsonrequest.get("params", {}))
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("[%s] --> %s.%s\n%s", rid, controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
response['id'] = rid
response["result"] = method(controller, self, **self.params)
except openerplib.AuthenticationError:
error = {
@ -249,8 +190,6 @@ class JsonRequest(WebRequest):
}
}
except Exception:
logging.getLogger(__name__ + '.JSONRequest.dispatch').exception\
("An error occured while handling a json request")
error = {
'code': 300,
'message': "OpenERP WebClient Error",
@ -262,11 +201,18 @@ class JsonRequest(WebRequest):
if error:
response["error"] = error
_logger.error("[%s] <--\n%s", rid, pprint.pformat(response))
elif _logger.isEnabledFor(logging.DEBUG):
_logger.debug("[%s] <--\n%s", rid, pprint.pformat(response))
return build_response(response)
if jsonp:
mime = 'application/javascript'
body = "%s(%s);" % (jsonp, simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder),)
else:
mime = 'application/json'
body = simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder)
r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
return r
def jsonrequest(f):
""" Decorator marking the decorated method as being a handler for a
@ -430,29 +376,12 @@ class ControllerType(type):
class Controller(object):
__metaclass__ = ControllerType
class JSONP(Controller):
_cp_path = '/web/jsonp'
@httprequest
def post(self, req, request_id, params, callback):
params = simplejson.loads(params, object_hook=nonliterals.non_literal_decoder)
params['session_id'] = req.session.id
req.session.jsonp_requests[request_id] = {
'jsonp': callback,
'params': params,
'id': request_id,
}
headers=[('Content-Type', 'text/plain; charset=utf-8')]
response = werkzeug.wrappers.Response(request_id, headers=headers)
return response
class Proxy(Controller):
_cp_path = '/web/proxy'
@jsonrequest
def static_proxy(self, req, path):
def load(self, req, path):
#req.config.socket_port
#if not re.match('^/[^/]+/static/.*', path):
# return werkzeug.exceptions.BadRequest()