Windshaft-cartodb/lib/cartodb/controllers/named_maps.js

243 lines
7.7 KiB
JavaScript
Raw Normal View History

2015-03-16 07:21:55 +08:00
var step = require('step');
var assert = require('assert');
var _ = require('underscore');
var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
var util = require('util');
var BaseController = require('./base');
2015-07-08 19:27:56 +08:00
var cors = require('../middleware/cors');
var TablesCacheEntry = require('../cache/model/database_tables_entry');
function NamedMapsController(app, authApi, pgConnection, namedMapProviderCache, tileBackend, previewBackend,
surrogateKeysCache, tablesExtentApi) {
BaseController.call(this, authApi, pgConnection);
this.app = app;
this.namedMapProviderCache = namedMapProviderCache;
this.tileBackend = tileBackend;
this.previewBackend = previewBackend;
2015-01-23 23:37:38 +08:00
this.surrogateKeysCache = surrogateKeysCache;
this.tablesExtentApi = tablesExtentApi;
}
util.inherits(NamedMapsController, BaseController);
module.exports = NamedMapsController;
NamedMapsController.prototype.register = function(app) {
app.get(app.base_url_templated + '/:template_id/:layer/:z/:x/:y.(:format)', cors(), this.tile.bind(this));
app.get(
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format', cors(), this.staticMap.bind(this)
);
};
NamedMapsController.prototype.sendResponse = function(req, res, resource, headers, namedMapProvider) {
this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(req.context.user, namedMapProvider.getTemplateName()));
2015-09-17 08:03:09 +08:00
res.set('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png');
res.set('Cache-Control', 'public,max-age=7200,must-revalidate');
var self = this;
var dbName = req.params.dbname;
step(
function getAffectedTablesAndLastUpdatedTime() {
namedMapProvider.getAffectedTablesAndLastUpdatedTime(this);
},
function sendResponse(err, result) {
req.profiler.done('affectedTables');
if (err) {
console.log('ERROR generating cache channel: ' + err);
}
if (!result || !!result.affectedTables) {
// we increase cache control as we can invalidate it
2015-09-17 08:03:09 +08:00
res.set('Cache-Control', 'public,max-age=31536000');
var lastModifiedDate;
if (Number.isFinite(result.lastUpdatedTime)) {
lastModifiedDate = new Date(result.lastUpdatedTime);
} else {
lastModifiedDate = new Date();
}
2015-09-17 08:03:09 +08:00
res.set('Last-Modified', lastModifiedDate.toUTCString());
var tablesCacheEntry = new TablesCacheEntry(dbName, result.affectedTables);
2015-09-17 08:03:09 +08:00
res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel());
if (result.affectedTables.length > 0) {
self.surrogateKeysCache.tag(res, tablesCacheEntry);
}
}
self.send(req, res, [resource, 200]);
}
);
};
2015-06-29 22:39:35 +08:00
NamedMapsController.prototype.tile = function(req, res) {
var self = this;
2015-07-08 21:34:46 +08:00
var cdbUser = req.context.user;
var namedMapProvider;
step(
function reqParams() {
self.req2params(req, this);
},
function getTile() {
namedMapProvider = self.namedMapProviderCache.get(
cdbUser,
req.params.template_id,
req.query.config,
req.query.auth_token,
req.params
);
self.tileBackend.getTile(namedMapProvider, req.params, this);
},
function handleImage(err, tile, headers, stats) {
if (req.profiler) {
req.profiler.add(stats);
}
if (err) {
self.sendError(req, res, err, 'NAMED_MAP_TILE');
} else {
self.sendResponse(req, res, tile, headers, namedMapProvider);
}
}
);
2015-06-29 22:39:35 +08:00
};
NamedMapsController.prototype.staticMap = function(req, res) {
var self = this;
var cdbUser = req.context.user;
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
req.params.format = 'png';
req.params.layer = 'all';
var namedMapProvider;
step(
function reqParams() {
self.req2params(req, this);
},
function getTemplate(err) {
assert.ifError(err);
namedMapProvider = self.namedMapProviderCache.get(
cdbUser,
req.params.template_id,
req.query.config,
req.query.auth_token,
req.params
);
namedMapProvider.getTemplate(this);
},
function prepareStaticImageOptions(err, template) {
assert.ifError(err);
getStaticImageOptions(template, this);
},
function estimateBounds(err, imageOpts) {
assert.ifError(err);
if (imageOpts) {
return imageOpts;
}
var defaultZoomCenter = {
zoom: 1,
center: {
lng: 0,
lat: 0
}
};
var cacheChannel = '';
var dbTables = cacheChannel.split(':');
if (dbTables.length <= 1 || dbTables[1].length === 0) {
return defaultZoomCenter;
}
var tableNames = dbTables[1].split(',');
if (tableNames.length === 0) {
return defaultZoomCenter;
}
var next = this;
self.tablesExtentApi.getBounds(cdbUser, tableNames, function(err, result) {
next(null, result || defaultZoomCenter);
});
},
function getImage(err, imageOpts) {
assert.ifError(err);
var width = +req.params.width;
var height = +req.params.height;
if (!_.isUndefined(imageOpts.zoom) && imageOpts.center) {
self.previewBackend.getImage(
namedMapProvider, format, width, height, imageOpts.zoom, imageOpts.center, this);
} else {
self.previewBackend.getImage(
namedMapProvider, format, width, height, imageOpts.bounds, this);
}
},
function handleImage(err, image, headers, stats) {
if (req.profiler) {
req.profiler.done('render-' + format);
req.profiler.add(stats || {});
}
if (err) {
self.sendError(req, res, err, 'STATIC_VIZ_MAP');
} else {
self.sendResponse(req, res, image, headers, namedMapProvider);
}
}
);
};
function getStaticImageOptions(template, callback) {
if (template.view) {
var zoomCenter = templateZoomCenter(template.view);
if (zoomCenter) {
return callback(null, zoomCenter);
}
var bounds = templateBounds(template.view);
if (bounds) {
return callback(null, bounds);
}
}
return callback(null, null);
}
function templateZoomCenter(view) {
if (!_.isUndefined(view.zoom) && view.center) {
return {
zoom: view.zoom,
center: view.center
};
}
return false;
}
function templateBounds(view) {
if (view.bounds) {
var hasAllBounds = _.every(['west', 'south', 'east', 'north'], function(prop) {
return !!view.bounds[prop];
});
if (hasAllBounds) {
return {
bounds: {
west: view.bounds.west,
south: view.bounds.south,
east: view.bounds.east,
north: view.bounds.north
}
};
} else {
return false;
}
}
return false;
}