[web] stop using deprecated StatusResponse. Closes #3098215 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 29 Aug 2013 16:21:52 +0200
branchstable
changeset 9229 739ae5366bed
parent 9228 90b8c7a7e205
child 9230 a68b2fe8a800
[web] stop using deprecated StatusResponse. Closes #3098215
web/controller.py
web/request.py
web/test/unittest_http.py
web/views/ajaxcontroller.py
web/views/basecontrollers.py
web/views/staticcontrollers.py
--- a/web/controller.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/controller.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -21,6 +21,7 @@
 
 from logilab.mtconverter import xml_escape
 from logilab.common.registry import yes
+from logilab.common.deprecation import deprecated
 
 from cubicweb.appobject import AppObject
 from cubicweb.mail import format_mail
@@ -103,6 +104,8 @@
         if not self._edited_entity:
             self._edited_entity = entity
 
+    @deprecated('[3.18] call view.set_http_cache_headers then '
+                '.is_client_cache_valid() method and return instead')
     def validate_cache(self, view):
         view.set_http_cache_headers()
         self._cw.validate_cache()
--- a/web/request.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/request.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -765,11 +765,13 @@
             return controller
         return 'view'
 
-    def validate_cache(self):
-        """raise a `StatusResponse` exception if a cached page along the way
-        exists and is still usable.
+    def is_client_cache_valid(self):
+        """check if a client cached page exists (as specified in request
+        headers) and is still usable.
 
-        calls the client-dependant implementation of `_validate_cache`
+        Return False if the page has to be calculated, else True.
+
+        Some response cache headers may be set by this method.
         """
         modified = True
         if self.get_header('Cache-Control') not in ('max-age=0', 'no-cache'):
@@ -784,15 +786,30 @@
                 # Expires header seems to be required by IE7 -- Are you sure ?
                 self.add_header('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
             if self.http_method() == 'HEAD':
-                raise StatusResponse(200, '')
-            # /!\ no raise, the function returns and we keep processing the request)
+                self.status_out = 200
+                # XXX replace by True once validate_cache bw compat method is dropped
+                return 200
+            # /!\ no raise, the function returns and we keep processing the request
         else:
             # overwrite headers_out to forge a brand new not-modified response
             self.headers_out = self._forge_cached_headers()
             if self.http_method() in ('HEAD', 'GET'):
-                raise StatusResponse(httplib.NOT_MODIFIED)
+                self.status_out = httplib.NOT_MODIFIED
             else:
-                raise StatusResponse(httplib.PRECONDITION_FAILED)
+                self.status_out = httplib.PRECONDITION_FAILED
+            # XXX replace by True once validate_cache bw compat method is dropped
+            return self.status_out
+        # XXX replace by False once validate_cache bw compat method is dropped
+        return None
+
+    @deprecated('[3.18] use .is_client_cache_valid() method instead')
+    def validate_cache(self):
+        """raise a `StatusResponse` exception if a cached page along the way
+        exists and is still usable.
+        """
+        status_code = self.is_client_cache_valid()
+        if status_code is not None:
+            raise StatusResponse(status_code)
 
     # abstract methods to override according to the web front-end #############
 
--- a/web/test/unittest_http.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/test/unittest_http.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,15 +1,30 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 from logilab.common.testlib import TestCase, unittest_main, tag, Tags
 
-from cubicweb.web import StatusResponse
 from cubicweb.devtools.fake import FakeRequest
 
 
 def _test_cache(hin, hout, method='GET'):
-    """forge and process a request
+    """forge and process an HTTP request using given headers in/out and method,
+    then return it once its .is_client_cache_valid() method has been called.
 
-    return status code and the request object
-
-    status is None is no cache is involved
+    req.status_out is None if the page should have been calculated.
     """
     # forge request
     req = FakeRequest(method=method)
@@ -18,12 +33,9 @@
     for key, value in hout:
         req.headers_out.addRawHeader(key, str(value))
     # process
-    status = None
-    try:
-        req.validate_cache()
-    except StatusResponse as ex:
-        status = ex.status
-    return status, req
+    req.status_out = None
+    req.is_client_cache_valid()
+    return req
 
 class HTTPCache(TestCase):
     """Check that the http cache logiac work as expected
@@ -48,42 +60,42 @@
     def test_IN_none_OUT_none(self):
         #: test that no caching is requested when not data is available
         #: on any side
-        status, req =_test_cache((),())
-        self.assertIsNone(status)
+        req =_test_cache((), ())
+        self.assertIsNone(req.status_out)
 
     def test_IN_Some_OUT_none(self):
         #: test that no caching is requested when no data is available
         #: server (origin) side
         hin = [('if-modified-since','Sat, 14 Apr 2012 14:39:32 GM'),
               ]
-        status, req = _test_cache(hin, ())
-        self.assertIsNone(status)
+        req = _test_cache(hin, ())
+        self.assertIsNone(req.status_out)
         hin = [('if-none-match','babar/huitre'),
               ]
-        status, req = _test_cache(hin, ())
-        self.assertIsNone(status)
+        req = _test_cache(hin, ())
+        self.assertIsNone(req.status_out)
         hin = [('if-modified-since','Sat, 14 Apr 2012 14:39:32 GM'),
                ('if-none-match','babar/huitre'),
               ]
-        status, req = _test_cache(hin, ())
-        self.assertIsNone(status)
+        req = _test_cache(hin, ())
+        self.assertIsNone(req.status_out)
 
     def test_IN_none_OUT_Some(self):
         #: test that no caching is requested when no data is provided
         #: by the client
         hout = [('last-modified','Sat, 14 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache((), hout)
-        self.assertIsNone(status)
+        req = _test_cache((), hout)
+        self.assertIsNone(req.status_out)
         hout = [('etag','babar/huitre'),
                ]
-        status, req = _test_cache((), hout)
-        self.assertIsNone(status)
+        req = _test_cache((), hout)
+        self.assertIsNone(req.status_out)
         hout = [('last-modified', 'Sat, 14 Apr 2012 14:39:32 GM'),
                 ('etag','babar/huitre'),
                ]
-        status, req = _test_cache((), hout)
-        self.assertIsNone(status)
+        req = _test_cache((), hout)
+        self.assertIsNone(req.status_out)
 
     @tag('last_modified')
     def test_last_modified_newer(self):
@@ -93,8 +105,8 @@
                ]
         hout = [('last-modified', 'Sat, 14 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'origin is newer than client')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'origin is newer than client')
 
     @tag('last_modified')
     def test_last_modified_older(self):
@@ -103,8 +115,8 @@
                ]
         hout = [('last-modified', 'Sat, 14 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'origin is older than client')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'origin is older than client')
 
     @tag('last_modified')
     def test_last_modified_same(self):
@@ -113,8 +125,8 @@
                ]
         hout = [('last-modified', 'Sat, 14 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'origin is equal to client')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'origin is equal to client')
 
     @tag('etag')
     def test_etag_mismatch(self):
@@ -124,8 +136,8 @@
                ]
         hout = [('etag', 'celestine'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'etag mismatch')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'etag mismatch')
 
     @tag('etag')
     def test_etag_match(self):
@@ -134,23 +146,23 @@
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'etag match')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'etag match')
         # etag match in multiple
         hin  = [('if-none-match', 'loutre'),
                 ('if-none-match', 'babar'),
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'etag match in multiple')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'etag match in multiple')
         # client use "*" as etag
         hin  = [('if-none-match', '*'),
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'client use "*" as etag')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'client use "*" as etag')
 
     @tag('etag', 'last_modified')
     def test_both(self):
@@ -162,8 +174,8 @@
         hout = [('etag', 'loutre'),
                 ('last-modified', 'Sat, 15 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'both wrong')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'both wrong')
 
     @tag('etag', 'last_modified')
     def test_both_etag_mismatch(self):
@@ -174,8 +186,8 @@
         hout = [('etag', 'loutre'),
                 ('last-modified', 'Sat, 13 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'both  but etag mismatch')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'both  but etag mismatch')
 
     @tag('etag', 'last_modified')
     def test_both_but_modified(self):
@@ -186,8 +198,8 @@
         hout = [('etag', 'babar'),
                 ('last-modified', 'Sat, 15 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'both  but modified')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'both  but modified')
 
     @tag('etag', 'last_modified')
     def test_both_ok(self):
@@ -198,8 +210,8 @@
         hout = [('etag', 'babar'),
                 ('last-modified', 'Sat, 13 Apr 2012 14:39:32 GM'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'both ok')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'both ok')
 
     @tag('etag', 'HEAD')
     def test_head_verb(self):
@@ -210,15 +222,15 @@
                ]
         hout = [('etag', 'rhino/really-not-babar'),
                ]
-        status, req = _test_cache(hin, hout, method='HEAD')
-        self.assertCache(200, status, 'modifier HEAD verb')
+        req = _test_cache(hin, hout, method='HEAD')
+        self.assertCache(200, req.status_out, 'modifier HEAD verb')
         # not modified
         hin  = [('if-none-match', 'babar'),
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout, method='HEAD')
-        self.assertCache(304, status, 'not modifier HEAD verb')
+        req = _test_cache(hin, hout, method='HEAD')
+        self.assertCache(304, req.status_out, 'not modifier HEAD verb')
 
     @tag('etag', 'POST')
     def test_post_verb(self):
@@ -227,15 +239,15 @@
                ]
         hout = [('etag', 'rhino/really-not-babar'),
                ]
-        status, req = _test_cache(hin, hout, method='POST')
-        self.assertCache(None, status, 'modifier HEAD verb')
+        req = _test_cache(hin, hout, method='POST')
+        self.assertCache(None, req.status_out, 'modifier HEAD verb')
         # not modified
         hin  = [('if-none-match', 'babar'),
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout, method='POST')
-        self.assertCache(412, status, 'not modifier HEAD verb')
+        req = _test_cache(hin, hout, method='POST')
+        self.assertCache(412, req.status_out, 'not modifier HEAD verb')
 
     @tag('expires')
     def test_expires_added(self):
@@ -246,8 +258,8 @@
                ]
         hout = [('etag', 'rhino/really-not-babar'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'modifier HEAD verb')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'modifier HEAD verb')
         value = req.headers_out.getHeader('expires')
         self.assertIsNotNone(value)
 
@@ -258,8 +270,8 @@
                ]
         hout = [('etag', 'babar'),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(304, status, 'not modifier HEAD verb')
+        req = _test_cache(hin, hout)
+        self.assertCache(304, req.status_out, 'not modifier HEAD verb')
         value = req.headers_out.getHeader('expires')
         self.assertIsNone(value)
 
@@ -272,8 +284,8 @@
         hout = [('etag', 'rhino/really-not-babar'),
                 ('expires', DATE),
                ]
-        status, req = _test_cache(hin, hout)
-        self.assertCache(None, status, 'not modifier HEAD verb')
+        req = _test_cache(hin, hout)
+        self.assertCache(None, req.status_out, 'not modifier HEAD verb')
         value = req.headers_out.getRawHeaders('expires')
         self.assertEqual(value, [DATE])
 
--- a/web/views/ajaxcontroller.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/views/ajaxcontroller.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -371,7 +371,8 @@
         vid = req.form.get('fallbackvid', 'noresult')
         viewobj = self._cw.vreg['views'].select(vid, req, rset=rset)
     viewobj.set_http_cache_headers()
-    req.validate_cache()
+    if req.is_client_cache_valid():
+        return ''
     return self._call_view(viewobj, paginate=req.form.pop('paginate', False))
 
 
--- a/web/views/basecontrollers.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/views/basecontrollers.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -128,7 +128,9 @@
         """publish a request, returning an encoded string"""
         view, rset = self._select_view_and_rset(rset)
         self.add_to_breadcrumbs(view)
-        self.validate_cache(view)
+        view.set_http_cache_headers()
+        if self._cw.is_client_cache_valid():
+            return ''
         template = self.appli.main_template_id(self._cw)
         return self._cw.vreg['views'].main_template(self._cw, template,
                                                     rset=rset, view=view)
--- a/web/views/staticcontrollers.py	Thu Aug 29 16:20:33 2013 +0200
+++ b/web/views/staticcontrollers.py	Thu Aug 29 16:21:52 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -20,7 +20,6 @@
 - /data/...
 - /static/...
 - /fckeditor/...
-
 """
 
 import os
@@ -78,7 +77,8 @@
         #
         # Real production environment should use dedicated static file serving.
         self._cw.set_header('last-modified', generateDateTime(os.stat(path).st_mtime))
-        self._cw.validate_cache()
+        if self._cw.is_client_cache_valid():
+            return ''
         # XXX elif uri.startswith('/https/'): uri = uri[6:]
         mimetype, encoding = mimetypes.guess_type(path)
         if mimetype is None: