pngtile: include ?t= in tile urls and generate large cache-control max-age's for those that match
authorTero Marttila <terom@qmsk.net>
Sat, 04 Oct 2014 02:19:43 +0300
changeset 172 73380dd6a816
parent 171 0ff809f855f7
child 173 e7822b0be417
pngtile: include ?t= in tile urls and generate large cache-control max-age's for those that match
pngtile/image.py
pngtile/tile.py
static/pngtile/map.js
--- a/pngtile/image.py	Sat Oct 04 01:40:54 2014 +0300
+++ b/pngtile/image.py	Sat Oct 04 02:19:43 2014 +0300
@@ -117,11 +117,13 @@
 
         map_config = dict(
             tiles_url       = self.tiles_url(name),
+            tiles_mtime     = image_info['cache_mtime'],
 
-            tile_url        = '{tiles_url}?x={x}&y={y}&zoom={z}',
+            tile_url        = '{tiles_url}?t={tiles_mtime}&x={x}&y={y}&zoom={z}',
             tile_size       = pngtile.tile.TILE_SIZE,
             tile_zoom       = pngtile.tile.MAX_ZOOM,
             
+            # do NOT include a mtime in these urls.. we should always revalidate them
             image_url       = '{tiles_url}?w={w}&h={h}&x={x}&y={y}&zoom={z}',
             image_width     = image_info['img_width'],
             image_height    = image_info['img_height'],
--- a/pngtile/tile.py	Sat Oct 04 01:40:54 2014 +0300
+++ b/pngtile/tile.py	Sat Oct 04 02:19:43 2014 +0300
@@ -9,6 +9,8 @@
 import pngtile.application
 import pypngtile
 
+import datetime
+
 ## Coordinates
 # width of a tile
 TILE_SIZE = 256
@@ -44,6 +46,9 @@
     return scale(val, zoom) - dim / 2
 
 class TileApplication (pngtile.application.PNGTileApplication):
+    # age in seconds for caching a known-mtime image
+    MAX_AGE = 7 * 24 * 60 * 60 # 1 week
+
     def __init__ (self, image_server, **opts):
         """
             image_server:       http://.../ url to image-server frontend
@@ -153,6 +158,14 @@
         # http caching
         mtime = image.cache_mtime()
 
+        if 't' in request.args:
+            try:
+                ttime = datetime.datetime.utcfromtimestamp(int(request.args['t']))
+            except ValueError:
+                ttime = None
+        else:
+            ttime = None
+
         if request.if_modified_since and mtime == request.if_modified_since:
             return Response(status=304)
             
@@ -163,6 +176,18 @@
         response = Response(png, content_type='image/png')
         response.last_modified = mtime
 
+        if not ttime:
+            # cached item may change while url stays the same
+            response.headers['Cache-Control'] = 'must-revalidate'
+
+        elif ttime == mtime:
+            # url will change if content changes
+            response.headers['Cache-Control'] = 'max-age={max_age:d}'.format(max_age=self.MAX_AGE)
+
+        else:
+            # XXX: mismatch wtf
+            response.headers['Cache-Control'] = 'must-revalidate'
+
         return response
 
 
--- a/static/pngtile/map.js	Sat Oct 04 01:40:54 2014 +0300
+++ b/static/pngtile/map.js	Sat Oct 04 02:19:43 2014 +0300
@@ -74,6 +74,7 @@
 
     L.tileLayer(map_config.tile_url, {
         tiles_url:          map_config.tiles_url,
+        tiles_mtime:        map_config.tiles_mtime,
         minZoom:            0,
         maxZoom:            map_config.tile_zoom,
         tileSize:           map_config.tile_size,
@@ -87,6 +88,7 @@
     L.control.link({
         url:        map_config.image_url,
         tiles_url:  map_config.tiles_url,
+        tiles_mtime:        map_config.tiles_mtime,
     }).addTo(map);
 
     // set position