[FIX] request.handle_exception: cleanup override logic, fixed chain broken by commit...
authorDenis Ledoux <dle@openerp.com>
Fri, 23 May 2014 11:15:52 +0000 (13:15 +0200)
committerDenis Ledoux <dle@openerp.com>
Fri, 23 May 2014 11:15:52 +0000 (13:15 +0200)
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.

addons/website/models/ir_http.py
openerp/http.py

index f724eb2..6577383 100644 (file)
@@ -99,45 +99,45 @@ class ir_http(orm.AbstractModel):
             werkzeug.exceptions.abort(werkzeug.utils.redirect(url))
 
     def _handle_exception(self, exception=None, code=500):
-        res = super(ir_http, self)._handle_exception(exception)
-        if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response:
-            return exception.response
-        if getattr(request, 'website_enabled', False) and request.website:
-            values = dict(
-                exception=exception,
-                traceback=traceback.format_exc(exception),
-            )
-            if exception:
-                code = getattr(exception, 'code', code)
-                if isinstance(exception, ir_qweb.QWebException):
-                    values.update(qweb_exception=exception)
-                    if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
-                        code = 403
-            if code == 500:
-                logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
-                if 'qweb_exception' in values:
-                    view = request.registry.get("ir.ui.view")
-                    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]
-                    values['views'] = to_reset
-            elif code == 403:
-                logger.warn("403 Forbidden:\n\n%s", values['traceback'])
-
-            values.update(
-                status_message=werkzeug.http.HTTP_STATUS_CODES[code],
-                status_code=code,
-            )
-
-            if not request.uid:
-                self._auth_method_public()
+        try:
+            return super(ir_http, self)._handle_exception(exception)
+        except Exception:
+            if getattr(request, 'website_enabled', False) and request.website:
+                values = dict(
+                    exception=exception,
+                    traceback=traceback.format_exc(exception),
+                )
+                if exception:
+                    code = getattr(exception, 'code', code)
+                    if isinstance(exception, ir_qweb.QWebException):
+                        values.update(qweb_exception=exception)
+                        if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
+                            code = 403
+                if code == 500:
+                    logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
+                    if 'qweb_exception' in values:
+                        view = request.registry.get("ir.ui.view")
+                        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]
+                        values['views'] = to_reset
+                elif code == 403:
+                    logger.warn("403 Forbidden:\n\n%s", values['traceback'])
+
+                values.update(
+                    status_message=werkzeug.http.HTTP_STATUS_CODES[code],
+                    status_code=code,
+                )
+
+                if not request.uid:
+                    self._auth_method_public()
 
-            try:
-                html = request.website._render('website.%s' % code, values)
-            except Exception:
-                html = request.website._render('website.http_error', values)
-            return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
+                try:
+                    html = request.website._render('website.%s' % code, values)
+                except Exception:
+                    html = request.website._render('website.http_error', values)
+                return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
 
-        return res
+            raise
 
 class ModelConverter(ir.ir_http.ModelConverter):
     def __init__(self, url_map, model=False):
index 68c2067..ec979fd 100644 (file)
@@ -208,6 +208,9 @@ class WebRequest(object):
            to abitrary responses. Anything returned (except None) will
            be used as response.""" 
         self._failed = exception # prevent tx commit
+        if isinstance(exception, werkzeug.exceptions.HTTPException):
+            return exception
+        raise
 
     def _call_function(self, *args, **kwargs):
         request = self
@@ -373,18 +376,20 @@ class JsonRequest(WebRequest):
     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.""" 
-        super(JsonRequest, self)._handle_exception(exception)
-        _logger.exception("Exception during JSON request handling.")
-        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)
+           be used as response."""
+        try:
+            return super(JsonRequest, self)._handle_exception(exception)
+        except Exception:
+            _logger.exception("Exception during JSON request handling.")
+            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