[MERGE] Forward-port of saas-3 up to 141e1b2
authorOlivier Dony <odo@openerp.com>
Wed, 25 Jun 2014 16:34:03 +0000 (18:34 +0200)
committerOlivier Dony <odo@openerp.com>
Wed, 25 Jun 2014 16:34:03 +0000 (18:34 +0200)
addons/website/models/ir_http.py
openerp/http.py

index a8f63a1..9250a2f 100644 (file)
@@ -61,7 +61,6 @@ class ir_http(orm.AbstractModel):
                     request.lang = request.context['lang'] = path.pop(1)
                     path = '/'.join(path) or '/'
                     return self.reroute(path)
-                return self._handle_exception(code=404)
         return super(ir_http, self)._dispatch()
 
     def reroute(self, path):
@@ -90,8 +89,8 @@ class ir_http(orm.AbstractModel):
         try:
             _, path = rule.build(arguments)
             assert path is not None
-        except Exception:
-            return self._handle_exception(werkzeug.exceptions.NotFound())
+        except Exception, e:
+            return self._handle_exception(e, code=404)
 
         if request.httprequest.method in ('GET', 'HEAD'):
             generated_path = werkzeug.url_unquote_plus(path)
@@ -125,51 +124,66 @@ class ir_http(orm.AbstractModel):
             response.data = datas.decode('base64')
             return response
 
-    def _handle_exception(self, exception=None, code=500):
-        try:
+    def _handle_exception(self, exception, code=500):
+        # This is done first as the attachment path may
+        # not match any HTTP controller, so the request
+        # may not be website-enabled.
+        attach = self._serve_attachment()
+        if attach:
+            return attach
+
+        is_website_request = bool(getattr(request, 'website_enabled', False) and request.website)
+        if not is_website_request:
+            # Don't touch non website requests exception handling
             return super(ir_http, self)._handle_exception(exception)
-        except Exception:
-
-            attach = self._serve_attachment()
-            if attach:
-                return attach
-
-            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')
-
-            raise
+        else:
+            try:
+                response = super(ir_http, self)._handle_exception(exception)
+                if isinstance(response, Exception):
+                    exception = response
+                else:
+                    # if parent excplicitely returns a plain response, then we don't touch it
+                    return response
+            except Exception, e:
+                exception = e
+
+            values = dict(
+                exception=exception,
+                traceback=traceback.format_exc(exception),
+            )
+            code = getattr(exception, 'code', code)
+
+            if isinstance(exception, openerp.exceptions.AccessError):
+                code = 403
+
+            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')
 
 class ModelConverter(ir.ir_http.ModelConverter):
     def __init__(self, url_map, model=False, domain='[]'):
index f67c08d..295a087 100644 (file)
@@ -1224,7 +1224,10 @@ class Root(object):
             request = self.get_request(httprequest)
 
             def _dispatch_nodb():
-                func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match()
+                try:
+                    func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match()
+                except werkzeug.exceptions.HTTPException, e:
+                    return request._handle_exception(e)
                 request.set_handler(func, arguments, "none")
                 result = request.dispatch()
                 return result