[FIX] request.handle_exception: cleanup override logic, fixed chain broken by commit a096ae0

handle_exception() is supposed to try handling an exception and if it cannot,
re-raise it. Overridden methods must therefore call super() within a try/except
block, and only attempt to handle the exception if super() raised.
This commit is contained in:
Denis Ledoux 2014-05-23 13:15:52 +02:00
parent 7a3b7f7fe2
commit 51c7b55da0
2 changed files with 52 additions and 47 deletions

View File

@ -99,45 +99,45 @@ class ir_http(orm.AbstractModel):
werkzeug.exceptions.abort(werkzeug.utils.redirect(url)) werkzeug.exceptions.abort(werkzeug.utils.redirect(url))
def _handle_exception(self, exception=None, code=500): def _handle_exception(self, exception=None, code=500):
res = super(ir_http, self)._handle_exception(exception) try:
if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response: return super(ir_http, self)._handle_exception(exception)
return exception.response except Exception:
if getattr(request, 'website_enabled', False) and request.website: if getattr(request, 'website_enabled', False) and request.website:
values = dict( values = dict(
exception=exception, exception=exception,
traceback=traceback.format_exc(exception), traceback=traceback.format_exc(exception),
) )
if exception: if exception:
code = getattr(exception, 'code', code) code = getattr(exception, 'code', code)
if isinstance(exception, ir_qweb.QWebException): if isinstance(exception, ir_qweb.QWebException):
values.update(qweb_exception=exception) values.update(qweb_exception=exception)
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError): if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
code = 403 code = 403
if code == 500: if code == 500:
logger.error("500 Internal Server Error:\n\n%s", values['traceback']) logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
if 'qweb_exception' in values: if 'qweb_exception' in values:
view = request.registry.get("ir.ui.view") view = request.registry.get("ir.ui.view")
views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context) views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
to_reset = [v for v in views if v.model_data_id.noupdate is True] to_reset = [v for v in views if v.model_data_id.noupdate is True]
values['views'] = to_reset values['views'] = to_reset
elif code == 403: elif code == 403:
logger.warn("403 Forbidden:\n\n%s", values['traceback']) logger.warn("403 Forbidden:\n\n%s", values['traceback'])
values.update( values.update(
status_message=werkzeug.http.HTTP_STATUS_CODES[code], status_message=werkzeug.http.HTTP_STATUS_CODES[code],
status_code=code, status_code=code,
) )
if not request.uid: if not request.uid:
self._auth_method_public() self._auth_method_public()
try: try:
html = request.website._render('website.%s' % code, values) html = request.website._render('website.%s' % code, values)
except Exception: except Exception:
html = request.website._render('website.http_error', values) html = request.website._render('website.http_error', values)
return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8') return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
return res raise
class ModelConverter(ir.ir_http.ModelConverter): class ModelConverter(ir.ir_http.ModelConverter):
def __init__(self, url_map, model=False): def __init__(self, url_map, model=False):

View File

@ -208,6 +208,9 @@ class WebRequest(object):
to abitrary responses. Anything returned (except None) will to abitrary responses. Anything returned (except None) will
be used as response.""" be used as response."""
self._failed = exception # prevent tx commit self._failed = exception # prevent tx commit
if isinstance(exception, werkzeug.exceptions.HTTPException):
return exception
raise
def _call_function(self, *args, **kwargs): def _call_function(self, *args, **kwargs):
request = self request = self
@ -373,18 +376,20 @@ class JsonRequest(WebRequest):
def _handle_exception(self, exception): def _handle_exception(self, exception):
"""Called within an except block to allow converting exceptions """Called within an except block to allow converting exceptions
to abitrary responses. Anything returned (except None) will to abitrary responses. Anything returned (except None) will
be used as response.""" be used as response."""
super(JsonRequest, self)._handle_exception(exception) try:
_logger.exception("Exception during JSON request handling.") return super(JsonRequest, self)._handle_exception(exception)
error = { except Exception:
'code': 200, _logger.exception("Exception during JSON request handling.")
'message': "OpenERP Server Error", error = {
'data': serialize_exception(exception) 'code': 200,
} 'message': "OpenERP Server Error",
if isinstance(exception, AuthenticationError): 'data': serialize_exception(exception)
error['code'] = 100 }
error['message'] = "OpenERP Session Invalid" if isinstance(exception, AuthenticationError):
return self._json_response(error=error) error['code'] = 100
error['message'] = "OpenERP Session Invalid"
return self._json_response(error=error)
def dispatch(self): def dispatch(self):
""" Calls the method asked for by the JSON-RPC2 or JSONP request """ Calls the method asked for by the JSON-RPC2 or JSONP request