# HG changeset patch # User Sylvain Thénault # Date 1377786112 -7200 # Node ID 739ae5366bede3f6dadafd4c15752a4b4fad2f63 # Parent 90b8c7a7e205e041f9c564f6c2a8af723ee3fa96 [web] stop using deprecated StatusResponse. Closes #3098215 diff -r 90b8c7a7e205 -r 739ae5366bed web/controller.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() diff -r 90b8c7a7e205 -r 739ae5366bed web/request.py --- 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 ############# diff -r 90b8c7a7e205 -r 739ae5366bed web/test/unittest_http.py --- 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 . 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]) diff -r 90b8c7a7e205 -r 739ae5366bed web/views/ajaxcontroller.py --- 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)) diff -r 90b8c7a7e205 -r 739ae5366bed web/views/basecontrollers.py --- 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) diff -r 90b8c7a7e205 -r 739ae5366bed web/views/staticcontrollers.py --- 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: