[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.
--- 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)