From 13a1c3bd5c69711dbd415b273b63c9bab24ae042 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 19 Jul 2023 14:17:40 +0200 Subject: [PATCH] Use gzip mtime for Last-Modified comparison when in gzip mode Prior to 1.3.0, uMap was not setting the gzip mtime, so it was whatever the time it get requested at first. Since 1.3.0: - when creating the geojson.gzip, we also force its mtime to be the geojson one - we replaced If-Match by If-Unmodified, which relies on Last-Modified When uMap is served by a proxy like Nginx (and X-Accel-Redirect), and if user accepts gzip, then the Last-Modified would be the gzip one, not the flat geojson one. So when comparing that value in a subsequent update, we need to compare with the correct value. fix #1212 --- umap/views.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/umap/views.py b/umap/views.py index 3459e49e..b79240c5 100644 --- a/umap/views.py +++ b/umap/views.py @@ -784,11 +784,28 @@ class GZipMixin(object): def path(self): return self.object.geojson.path + @property + def gzip_path(self): + return Path(f"{self.path}{self.EXT}") + @property def last_modified(self): - stat = os.stat(self.path) + # Prior to 1.3.0 we did not set gzip mtime as geojson mtime, + # but we switched from If-Match header to IF-Unmodified-Since + # and when users accepts gzip their last modified value is the gzip + # (when umap is served by nginx and X-Accel-Redirect) + # one, so we need to compare with that value in that case. + # cf https://github.com/umap-project/umap/issues/1212 + path = self.gzip_path if self.accepts_gzip else self.path + stat = os.stat(path) return http_date(stat.st_mtime) + @property + def accepts_gzip(self): + return settings.UMAP_GZIP and re_accepts_gzip.search( + self.request.META.get("HTTP_ACCEPT_ENCODING", "") + ) + class DataLayerView(GZipMixin, BaseDetailView): model = DataLayer @@ -797,13 +814,9 @@ class DataLayerView(GZipMixin, BaseDetailView): response = None path = self.path # Generate gzip if needed - accepts_gzip = re_accepts_gzip.search( - self.request.META.get("HTTP_ACCEPT_ENCODING", "") - ) - if accepts_gzip and settings.UMAP_GZIP: - gzip_path = Path(f"{path}{self.EXT}") - if not gzip_path.exists(): - gzip_file(path, gzip_path) + if self.accepts_gzip: + if not self.gzip_path.exists(): + gzip_file(path, self.gzip_path) if getattr(settings, "UMAP_XSENDFILE_HEADER", None): response = HttpResponse()