[web] use a redirect for /data/foo requests that don't use the instance md5 hash
authorJulien Cristau <julien.cristau@logilab.fr>
Fri, 20 Nov 2015 18:23:17 +0100
changeset 10851 70b21cf8b45c
parent 10850 928c7ec525e0
child 10852 e35d23686d1f
[web] use a redirect for /data/foo requests that don't use the instance md5 hash The actual file contents can be cached for a long time. If the request doesn't use the hash, that's wrong. Using a redirect lets keep the caching for the actual file contents while not breaking requests missing the hash.
web/test/unittest_views_staticcontrollers.py
web/views/staticcontrollers.py
--- a/web/test/unittest_views_staticcontrollers.py	Fri Nov 20 12:37:15 2015 +0100
+++ b/web/test/unittest_views_staticcontrollers.py	Fri Nov 20 18:23:17 2015 +0100
@@ -76,6 +76,12 @@
         with self._publish_static_files(fname, next_headers) as req:
             self.assertEqual(304, req.status_out)
 
+    def _check_datafile_redirect(self, fname, expected):
+        with self._publish_static_files(fname) as req:
+            self.assertEqual(302, req.status_out)
+            self.assertEqual(req.get_response_header('location'),
+                             req.base_url() + expected)
+
     def _check_no_datafile(self, fname):
         with self._publish_static_files(fname) as req:
             self.assertEqual(404, req.status_out)
@@ -90,10 +96,12 @@
             self._check_no_datafile('data/%s/cubicweb.css' % ('0'*len(hash)))
 
         with tempattr(self.vreg.config, 'mode', 'notest'):
-            self._check_datafile_ok('data/cubicweb.css')
+            self.config._init_base_url()  # reset config.datadir_url
+            self._check_datafile_redirect('data/cubicweb.css', 'data/%s/cubicweb.css' % hash)
             self._check_datafile_ok('data/%s/cubicweb.css' % hash)
-            self._check_no_datafile('data/does/not/exist')
-            self._check_no_datafile('data/%s/cubicweb.css' % ('0'*len(hash)))
+            self._check_no_datafile('data/%s/does/not/exist' % hash)
+            self._check_datafile_redirect('data/%s/does/not/exist' % ('0'*len(hash)),
+                                          'data/%s/%s/does/not/exist' % (hash, '0'*len(hash)))
 
 
 class ConcatFilesTC(CubicWebTC):
--- a/web/views/staticcontrollers.py	Fri Nov 20 12:37:15 2015 +0100
+++ b/web/views/staticcontrollers.py	Fri Nov 20 18:23:17 2015 +0100
@@ -33,7 +33,7 @@
 from logging import getLogger
 
 from cubicweb import Forbidden
-from cubicweb.web import NotFound
+from cubicweb.web import NotFound, Redirect
 from cubicweb.web.http_headers import generateDateTime
 from cubicweb.web.controller import Controller
 from cubicweb.web.views.urlrewrite import URLRewriter
@@ -200,11 +200,13 @@
             paths = relpath[len(self.data_modconcat_basepath):].split(',')
             filepath = self.concat_files_registry.concat_cached_filepath(paths)
         else:
-            # skip leading '/data/' and url params
-            if relpath.startswith(self.base_datapath):
-                prefix = self.base_datapath
-            else:
+            if not relpath.startswith(self.base_datapath):
+                # /data/foo, redirect to /data/{hash}/foo
                 prefix = 'data/'
+                relpath = relpath[len(prefix):]
+                raise Redirect(self._cw.data_url(relpath), 302)
+            # skip leading '/data/{hash}/' and url params
+            prefix = self.base_datapath
             relpath = relpath[len(prefix):]
             relpath = relpath.split('?', 1)[0]
             dirpath, rid = config.locate_resource(relpath)