From 2bc09a61cf7dd45c440c0b0a5725e9a8b0881730 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 24 Oct 2012 09:40:05 +0200 Subject: [PATCH] Add support for cache_policy=persistent When cache_policy=persistent is given the response will contain a Cache-Control header requesting for 1 year lifetime caching --- README.md | 12 ++++++++++-- lib/cartodb/server_options.js | 11 ++++++++--- test/acceptance/server.js | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 47a48866..e1f66eeb 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,16 @@ Args: * sql - plain SQL arguments * interactivity - specify the column to use in UTFGrid -* cache_buster - if needed you can add a cachebuster to make sure you're - rendering new +* cache_buster - Specify an identifier for the internal tile cache. + Requesting tiles with the same cache_buster value may + result in being served a cached version of the tile + (even when requesting a tile for the first time, as tiles + can be prepared in advance) +* cache_policy - Set to "persist" to have the server send an Cache-Control + header requesting caching devices to keep the response + cached as much as possible. This is best used with a + timestamp value in cache_buster for manual control of + updates. * geom_type - override the cartodb default * style - override the default map style with Carto diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index b0ce3ba8..e1ab444b 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -45,8 +45,13 @@ module.exports = function(){ var ttl = global.environment.varnish.ttl || 86400; Cache.generateCacheChannel(req, function(channel){ res.header('X-Cache-Channel', channel); - res.header('Last-Modified', new Date().toUTCString()); - res.header('Cache-Control', 'no-cache,max-age='+ttl+',must-revalidate, public'); + var cache_policy = req.query.cache_policy; + if ( cache_policy == 'persist' ) { + res.header('Cache-Control', 'public,max-age=31536000'); // 1 year + } else { + res.header('Last-Modified', new Date().toUTCString()); + res.header('Cache-Control', 'no-cache,max-age='+ttl+',must-revalidate, public'); + } cb(null, channel); // add last-modified too ? }); } @@ -60,7 +65,7 @@ module.exports = function(){ me.req2params = function(req, callback){ // Whitelist query parameters and attach format - var good_query = ['sql', 'geom_type', 'cache_buster','callback', 'interactivity', 'map_key', 'api_key', 'style']; + var good_query = ['sql', 'geom_type', 'cache_buster', 'cache_policy', 'callback', 'interactivity', 'map_key', 'api_key', 'style']; var bad_query = _.difference(_.keys(req.query), good_query); _.each(bad_query, function(key){ delete req.query[key]; }); diff --git a/test/acceptance/server.js b/test/acceptance/server.js index eb5dd025..fb564ff7 100644 --- a/test/acceptance/server.js +++ b/test/acceptance/server.js @@ -535,7 +535,40 @@ suite('server', function() { // GET TILE // ///////////////////////////////////////////////////////////////////////////////// - + + test("should send Cache-Control header with short expiration by default", function(done){ + assert.response(server, { + headers: {host: 'localhost'}, + url: '/tiles/gadm4/6/31/24.png', + method: 'GET' + },{ + status: 200, + }, function(res) { + var cc = res.headers['cache-control']; + assert.ok(cc); + //assert.equal(cc, 'public,max-age=31536000'); // 1 year + assert.ok(cc.match('no-cache'), cc); + assert.ok(cc.match('must-revalidate'), cc); + assert.ok(cc.match('public'), cc); + done(); + }); + }); + + test("should send Cache-Control header with long expiration when requested", function(done){ + assert.response(server, { + headers: {host: 'localhost'}, + url: '/tiles/gadm4/6/31/24.png?cache_policy=persist', + method: 'GET' + },{ + status: 200, + }, function(res) { + var cc = res.headers['cache-control']; + assert.ok(cc); + assert.equal(cc, 'public,max-age=31536000'); // 1 year + done(); + }); + }); + test("get'ing a tile with default style should return an image", function(done){ assert.response(server, { headers: {host: 'localhost'},