[web publish] in case of error, ensure proper http status is set and Content-disposition header is reseted. Closes #2553066 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 22 Feb 2013 12:20:59 +0100
branchstable
changeset 8753 b61a7c6352f2
parent 8745 00c5ea2a064a
child 8754 9d5cfbde9856
[web publish] in case of error, ensure proper http status is set and Content-disposition header is reseted. Closes #2553066
web/application.py
web/test/unittest_idownloadable.py
--- a/web/application.py	Mon Sep 17 14:39:29 2012 +0200
+++ b/web/application.py	Fri Feb 22 12:20:59 2013 +0100
@@ -485,6 +485,7 @@
             raise
         ### Last defense line
         except BaseException as ex:
+            req.status_out = httplib.INTERNAL_SERVER_ERROR
             result = self.error_handler(req, ex, tb=True)
         finally:
             if req.cnx and not commited:
@@ -538,6 +539,7 @@
             self.exception(repr(ex))
         req.set_header('Cache-Control', 'no-cache')
         req.remove_header('Etag')
+        req.remove_header('Content-disposition')
         req.reset_message()
         req.reset_headers()
         if req.ajax_request:
--- a/web/test/unittest_idownloadable.py	Mon Sep 17 14:39:29 2012 +0200
+++ b/web/test/unittest_idownloadable.py	Fri Feb 22 12:20:59 2013 +0100
@@ -25,29 +25,40 @@
 from cubicweb import view
 from cubicweb.predicates import is_instance
 
+class IDownloadableUser(view.EntityAdapter):
+    __regid__ = 'IDownloadable'
+    __select__ = is_instance('CWUser')
+
+    def download_content_type(self):
+        """return MIME type of the downloadable content"""
+        return 'text/plain'
+
+    def download_encoding(self):
+        """return encoding of the downloadable content"""
+        return 'ascii'
+
+    def download_file_name(self):
+        """return file name of the downloadable content"""
+        return  self.entity.name() + '.txt'
+
+    def download_data(self):
+        return 'Babar is not dead!'
+
+
+class BrokenIDownloadableGroup(IDownloadableUser):
+    __regid__ = 'IDownloadable'
+    __select__ = is_instance('CWGroup')
+
+    def download_file_name(self):
+        return  self.entity.name + '.txt'
+
+    def download_data(self):
+        raise IOError()
 
 class IDownloadableTC(CubicWebTC):
 
     def setUp(self):
         super(IDownloadableTC, self).setUp()
-        class IDownloadableUser(view.EntityAdapter):
-            __regid__ = 'IDownloadable'
-            __select__ = is_instance('CWUser')
-
-            def download_content_type(self):
-                """return MIME type of the downloadable content"""
-                return 'text/plain'
-
-            def download_encoding(self):
-                """return encoding of the downloadable content"""
-                return 'ascii'
-
-            def download_file_name(self):
-                """return file name of the downloadable content"""
-                return  self.entity.name() + '.txt'
-
-            def download_data(self):
-                return 'Babar is not dead!'
         self.vreg.register(IDownloadableUser)
         self.addCleanup(partial(self.vreg.unregister, IDownloadableUser))
 
@@ -55,7 +66,7 @@
         req = self.request()
         req.form['vid'] = 'download'
         req.form['eid'] = str(req.user.eid)
-        data = self.ctrl_publish(req,'view')
+        data = self.ctrl_publish(req, 'view')
         get = req.headers_out.getRawHeaders
         self.assertEqual(['attachment;filename="admin.txt"'],
                          get('content-disposition'))
@@ -122,5 +133,24 @@
             self.assertEqual(["""attachment;filename="Brte_h_grand_nm_a_va_totallement_dborder_de_la_limite_l.txt";filename*=utf-8''B%C3%A8rte_h%C3%B4_grand_n%C3%B4m_%C3%A7a_va_totallement_d%C3%A9border_de_la_limite_l%C3%A0.txt"""],
                              get('content-disposition'))
 
+
+    def test_download_data_error(self):
+        self.vreg.register(BrokenIDownloadableGroup)
+        self.addCleanup(partial(self.vreg.unregister, BrokenIDownloadableGroup))
+        req = self.request()
+        req.form['vid'] = 'download'
+        req.form['eid'] = str(req.execute('CWGroup X WHERE X name "managers"')[0][0])
+        errhdlr = self.app.__dict__.pop('error_handler') # temporarily restore error handler
+        try:
+            data = self.app_handle_request(req)
+        finally:
+            self.app.error_handler = errhdlr
+        get = req.headers_out.getRawHeaders
+        self.assertEqual(['application/xhtml+xml'],
+                         get('content-type'))
+        self.assertEqual(None,
+                         get('content-disposition'))
+        self.assertEqual(req.status_out, 500)
+
 if __name__ == '__main__':
     unittest_main()