diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index d6ba0d1b..ebdabb8f 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -25,8 +25,13 @@ NamedMapsController.prototype.register = function(app) { userMiddleware, this.prepareContext, this.getNamedMapProvider(), + this.getAffectedTables(), this.getTile(), - this.getAffectedTablesAndLastUpdatedTime(), + this.setSurrogateKey(), + this.setCacheChannelHeader(), + this.setLastModifiedHeader(), + this.setCacheControlHeader(), + this.setContentTypeHeader(), this.respond(), vectorError() ); @@ -38,11 +43,16 @@ NamedMapsController.prototype.register = function(app) { allowQueryParams(['layer', 'zoom', 'lon', 'lat', 'bbox']), this.prepareContext, this.getNamedMapProvider('STATIC_VIZ_MAP'), + this.getAffectedTables(), this.prepareLayerFilterFromPreviewLayers('STATIC_VIZ_MAP'), this.getStaticImageOptions(), this.getImage('STATIC_VIZ_MAP'), this.incrementMapViews(), - this.getAffectedTablesAndLastUpdatedTime(), + this.setSurrogateKey(), + this.setCacheChannelHeader(), + this.setLastModifiedHeader(), + this.setCacheControlHeader(), + this.setContentTypeHeader(), this.respond() ); }; @@ -66,6 +76,24 @@ NamedMapsController.prototype.getNamedMapProvider = function (label) { }.bind(this); }; +NamedMapsController.prototype.getAffectedTables = function () { + return function getAffectedTables (req, res, next) { + const { namedMapProvider } = res.locals; + + namedMapProvider.getAffectedTablesAndLastUpdatedTime((err, affectedTablesAndLastUpdate) => { + req.profiler.done('affectedTables'); + + if (err) { + return next(err); + } + + res.locals.affectedTablesAndLastUpdate = affectedTablesAndLastUpdate; + + next(); + }); + }.bind(this); +}; + NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function (label) { return function prepareLayerFilterFromPreviewLayersMiddleware (req, res, next) { const { user, namedMapProvider } = res.locals; @@ -330,41 +358,75 @@ function templateBounds(view) { return false; } -NamedMapsController.prototype.getAffectedTablesAndLastUpdatedTime = function () { - return function getAffectedTablesAndLastUpdatedTimeMiddleware (req, res, next) { - const { namedMapProvider, headers, user } = res.locals; +NamedMapsController.prototype.setCacheChannelHeader = function () { + return function setCacheChannelHeaderMiddleware (req, res, next) { + const { affectedTablesAndLastUpdate } = res.locals; + + if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) { + res.set('X-Cache-Channel', affectedTablesAndLastUpdate.getCacheChannel()); + } + + next(); + }; +}; + +NamedMapsController.prototype.setSurrogateKey = function () { + return function setSurrogateKeyMiddleware(req, res, next) { + const { user, namedMapProvider, affectedTablesAndLastUpdate } = res.locals; this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(user, namedMapProvider.getTemplateName())); - res.set('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png'); + if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) { + if (affectedTablesAndLastUpdate.tables.length > 0) { + this.surrogateKeysCache.tag(res, affectedTablesAndLastUpdate); + } + } + + next(); + }.bind(this); +}; + +NamedMapsController.prototype.setLastModifiedHeader = function () { + return function setLastModifiedHeaderMiddleware(req, res, next) { + const { affectedTablesAndLastUpdate } = res.locals; + + if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) { + var lastModifiedDate; + if (Number.isFinite(affectedTablesAndLastUpdate.lastUpdatedTime)) { + lastModifiedDate = new Date(affectedTablesAndLastUpdate.getLastUpdatedAt()); + } else { + lastModifiedDate = new Date(); + } + + res.set('Last-Modified', lastModifiedDate.toUTCString()); + } + + next(); + }; + }; + +NamedMapsController.prototype.setCacheControlHeader = function () { + return function setCacheControlHeaderMiddleware(req, res, next) { + const { affectedTablesAndLastUpdate } = res.locals; + res.set('Cache-Control', 'public,max-age=7200,must-revalidate'); - namedMapProvider.getAffectedTablesAndLastUpdatedTime((err, result) => { - req.profiler.done('affectedTables'); - if (err) { - global.logger.log('ERROR generating cache channel: ' + err); - } + if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) { + // we increase cache control as we can invalidate it + res.set('Cache-Control', 'public,max-age=31536000'); + } - if (!result || !!result.tables) { - // we increase cache control as we can invalidate it - res.set('Cache-Control', 'public,max-age=31536000'); + next(); + }; + }; - var lastModifiedDate; - if (Number.isFinite(result.lastUpdatedTime)) { - lastModifiedDate = new Date(result.getLastUpdatedAt()); - } else { - lastModifiedDate = new Date(); - } - res.set('Last-Modified', lastModifiedDate.toUTCString()); +NamedMapsController.prototype.setContentTypeHeader = function () { + return function setContentTypeHeaderMiddleware(req, res, next) { + const { headers = {} } = res.locals; - res.set('X-Cache-Channel', result.getCacheChannel()); - if (result.tables.length > 0) { - this.surrogateKeysCache.tag(res, result); - } - } + res.set('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png'); - next(); - }); - }.bind(this); + next(); + }; }; NamedMapsController.prototype.respond = function () {