[FIX] http,ir.http: refactor exception handling to allow request-specific handling

Typically an exception during a JSON-RPC request must be
handled specifically and return a JSON-RPC error in all
cases. Previously the _authenticate() step could fail
during ir_http.dispatch() and bubble up to werkzeug,
yielding a dumb "Internal Server Error 500" even for
a JSON-RPC request.

bzr revid: odo@openerp.com-20140328142748-00haplmkc3fv6f9y
This commit is contained in:
Olivier Dony 2014-03-28 15:27:48 +01:00
parent 9379dc0312
commit 8809c77f60
2 changed files with 48 additions and 35 deletions

View File

@ -85,8 +85,8 @@ class ir_http(osv.AbstractModel):
return auth_method
def _handle_exception(self, exception):
# If handle exception return something different than None, it will be used as a response
raise
# If handle_exception returns something different than None, it will be used as a response
return request._handle_exception(exception)
def _dispatch(self):
# locate the controller method

View File

@ -202,6 +202,13 @@ class WebRequest(object):
self.func_arguments = arguments
self.auth_method = auth
def _handle_exception(self, exception):
"""Called within an except block to allow converting exceptions
to abitrary responses. Anything returned (except None) will
be used as response."""
raise
def _call_function(self, *args, **kwargs):
request = self
if self.func_request_type != self._request_type:
@ -338,37 +345,15 @@ class JsonRequest(WebRequest):
self.params = dict(self.jsonrequest.get("params", {}))
self.context = self.params.pop('context', dict(self.session.context))
def dispatch(self):
""" Calls the method asked for by the JSON-RPC2 or JSONP request
"""
if self.jsonp_handler:
return self.jsonp_handler()
response = {"jsonrpc": "2.0" }
error = None
try:
response['id'] = self.jsonrequest.get('id')
response["result"] = self._call_function(**self.params)
except AuthenticationError, e:
_logger.exception("Exception during JSON request handling.")
se = serialize_exception(e)
error = {
'code': 100,
'message': "OpenERP Session Invalid",
'data': se
}
self._failed = e # prevent tx commit
except Exception, e:
_logger.exception("Exception during JSON request handling.")
se = serialize_exception(e)
error = {
'code': 200,
'message': "OpenERP Server Error",
'data': se
}
self._failed = e # prevent tx commit
if error:
response["error"] = error
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
if self.jsonp:
# If we use jsonp, that's mean we are called from another host
@ -381,8 +366,36 @@ class JsonRequest(WebRequest):
mime = 'application/json'
body = simplejson.dumps(response)
r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
return r
return werkzeug.wrappers.Response(
body, headers=[('Content-Type', mime),
('Content-Length', len(body))])
def _handle_exception(self, exception):
"""Called within an except block to allow converting exceptions
to abitrary responses. Anything returned (except None) will
be used as response."""
_logger.exception("Exception during JSON request handling.")
self._failed = exception # prevent tx commit
error = {
'code': 200,
'message': "OpenERP Server Error",
'data': serialize_exception(exception)
}
if isinstance(exception, AuthenticationError):
error['code'] = 100
error['message'] = "OpenERP Session Invalid"
return self._json_response(error=error)
def dispatch(self):
""" Calls the method asked for by the JSON-RPC2 or JSONP request
"""
if self.jsonp_handler:
return self.jsonp_handler()
try:
result = self._call_function(**self.params)
return self._json_response(result)
except Exception, e:
return self._handle_exception(e)
def serialize_exception(e):
tmp = {