diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index 96da8a7b..686be507 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -5,13 +5,17 @@ var templateName = require('../backends/template_maps').templateName; var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); var cors = require('../middleware/cors'); -function NamedMapsController(app, templateMaps, metadataBackend, mapBackend, staticMapBackend, templateBaseUrl, - surrogateKeysCache, layergroupRequestDecorator, tablesExtentApi) { +var MapStoreMapConfigProvider = require('windshaft').model.provider.MapStoreMapConfig; + +function NamedMapsController(app, mapStore, templateMaps, metadataBackend, mapBackend, tileBackend, previewBackend, + templateBaseUrl, surrogateKeysCache, layergroupRequestDecorator, tablesExtentApi) { this.app = app; + this.mapStore = mapStore; this.templateMaps = templateMaps; this.metadataBackend = metadataBackend; this.mapBackend = mapBackend; - this.staticMapBackend = staticMapBackend; + this.tileBackend = tileBackend; + this.previewBackend = previewBackend; this.templateBaseUrl = templateBaseUrl; this.surrogateKeysCache = surrogateKeysCache; this.layergroupRequestDecorator = layergroupRequestDecorator; @@ -29,6 +33,53 @@ NamedMapsController.prototype.register = function(app) { app.post(this.templateBaseUrl + '/:template_id', cors(), this.instantiate.bind(this)); }; +NamedMapsController.prototype.instantiate = function(req, res) { + var self = this; + + if (req.profiler) { + req.profiler.start('windshaft-cartodb.instance_template_post'); + } + step( + function instantiateTemplate() { + ifInvalidContentType(req, 'template POST data must be of type application/json'); + + self.instantiateTemplate(req, res, req.body, this); + }, function finishInstantiation(err, response) { + self.finish_instantiation(err, response, res); + } + ); +}; + +/** + * jsonp endpoint, allows to instantiate a template with a json call. + * callback query argument is mandatory + */ +NamedMapsController.prototype.jsonp = function(req, res) { + var self = this; + + if (req.profiler) { + req.profiler.start('windshaft-cartodb.instance_template_get'); + } + step( + function jsonp$instantiateTemplate() { + if ( req.query.callback === undefined || req.query.callback.length === 0) { + throw new Error('callback parameter should be present and be a function name'); + } + var config = {}; + if(req.query.config) { + try { + config = JSON.parse(req.query.config); + } catch(e) { + throw new Error('Invalid config parameter, should be a valid JSON'); + } + } + self.instantiateTemplate(req, res, config, this); + }, function finishInstantiation(err, response) { + self.finish_instantiation(err, response, res); + } + ); +}; + NamedMapsController.prototype.tile = function(req, res) { var self = this; @@ -135,7 +186,7 @@ NamedMapsController.prototype.tile = function(req, res) { assert.ifError(err); req.params.token = layergroupId; - self.mapBackend.getTileOrGrid(req.params, this); + self.tileBackend.getTile(new MapStoreMapConfigProvider(self.mapStore, req.params), params, this); }, function handleImage(err, tile, headers, stats) { if (req.profiler) { @@ -155,162 +206,6 @@ NamedMapsController.prototype.tile = function(req, res) { ); }; -NamedMapsController.prototype.instantiate = function(req, res) { - var self = this; - - if (req.profiler) { - req.profiler.start('windshaft-cartodb.instance_template_post'); - } - step( - function instantiateTemplate() { - ifInvalidContentType(req, 'template POST data must be of type application/json'); - - self.instantiateTemplate(req, res, req.body, this); - }, function finishInstantiation(err, response) { - self.finish_instantiation(err, response, res); - } - ); -}; - -/** - * jsonp endpoint, allows to instantiate a template with a json call. - * callback query argument is mandatory - */ -NamedMapsController.prototype.jsonp = function(req, res) { - var self = this; - - if (req.profiler) { - req.profiler.start('windshaft-cartodb.instance_template_get'); - } - step( - function jsonp$instantiateTemplate() { - if ( req.query.callback === undefined || req.query.callback.length === 0) { - throw new Error('callback parameter should be present and be a function name'); - } - var config = {}; - if(req.query.config) { - try { - config = JSON.parse(req.query.config); - } catch(e) { - throw new Error('Invalid config parameter, should be a valid JSON'); - } - } - self.instantiateTemplate(req, res, config, this); - }, function finishInstantiation(err, response) { - self.finish_instantiation(err, response, res); - } - ); -}; - - -// Instantiate a template -NamedMapsController.prototype.instantiateTemplate = function(req, res, template_params, callback) { - var self = this; - - var layergroupDecorator = { - beforeLayergroupCreate: function(requestMapConfig, callback) { - self.layergroupRequestDecorator.beforeLayergroupCreate(req, requestMapConfig, callback); - }, - afterLayergroupCreate: function(layergroup, response, callback) { - self.layergroupRequestDecorator.afterLayergroupCreate(req, layergroup, response, callback); - } - }; - - var template; - var layergroup; - var cdbuser = req.context.user; - var params = { - user: req.params.user - }; - // Format of template_id: []@ - var tpl_id = templateName(req.params.template_id); - var auth_token = req.query.auth_token; - step( - function getTemplate(){ - self.templateMaps.getTemplate(cdbuser, tpl_id, this); - }, - function checkAuthorized(err, templateValue) { - if ( req.profiler ) req.profiler.done('getTemplate'); - if ( err ) throw err; - if ( ! templateValue ) { - err = new Error("Template '" + tpl_id + "' of user '" + cdbuser + "' not found"); - err.http_status = 404; - throw err; - } - - template = templateValue; - - var authorized = false; - try { - authorized = self.templateMaps.isAuthorized(template, auth_token); - } catch (err) { - // we catch to add http_status - err.http_status = 403; - throw err; - } - if ( ! authorized ) { - err = new Error('Unauthorized template instantiation'); - err.http_status = 403; - throw err; - } - - if (req.profiler) { - req.profiler.done('authorizedByCert'); - } - - return self.templateMaps.instance(template, template_params); - }, - function prepareParams(err, instance){ - if ( req.profiler ) req.profiler.done('TemplateMaps_instance'); - if ( err ) throw err; - layergroup = instance; - self.app.setDBParams(cdbuser, params, this); - }, - function setApiKey(err){ - if ( req.profiler ) req.profiler.done('setDBParams'); - if ( err ) throw err; - self.metadataBackend.getUserMapKey(cdbuser, this); - }, - function createLayergroup(err, val) { - if ( req.profiler ) req.profiler.done('getUserMapKey'); - if ( err ) throw err; - params.api_key = val; - self.mapBackend.createLayergroup(layergroup, params, layergroupDecorator, this); - }, - function prepareResponse(err, layergroup) { - if ( err ) { - return callback(err, { errors: [''+err] }); - } - var tplhash = self.templateMaps.fingerPrint(template).substring(0,8); - layergroup.layergroupid = cdbuser + '@' + tplhash + '@' + layergroup.layergroupid; - res.header('X-Layergroup-Id', layergroup.layergroupid); - - self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, template.name)); - - callback(null, layergroup); - } - ); -}; - -NamedMapsController.prototype.finish_instantiation = function(err, response, res) { - if (err) { - var statusCode = 400; - response = { errors: [''+err] }; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - this.app.sendError(res, response, statusCode, 'POST INSTANCE TEMPLATE', err); - } else { - this.app.sendResponse(res, [response, 200]); - } -}; - -function ifInvalidContentType(req, description) { - if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) { - throw new Error(description); - } -} - NamedMapsController.prototype.staticMap = function(req, res) { var self = this; @@ -460,10 +355,13 @@ NamedMapsController.prototype.staticMap = function(req, res) { var width = +req.params.width; var height = +req.params.height; + var provider = new MapStoreMapConfigProvider(self.mapStore, imageParams); if (!_.isUndefined(imageOpts.zoom) && imageOpts.center) { - self.staticMapBackend.getImage(imageParams, width, height, imageOpts.zoom, imageOpts.center, this); + self.previewBackend.getImage( + provider, imageParams, width, height, imageOpts.zoom, imageOpts.center, this); } else { - self.staticMapBackend.getImage(imageParams, width, height, imageOpts.bounds, this); + self.previewBackend.getImage( + provider, imageParams, width, height, imageOpts.bounds, this); } }, function handleImage(err, image, headers, stats) { @@ -486,6 +384,115 @@ NamedMapsController.prototype.staticMap = function(req, res) { ); }; + +// Instantiate a template +NamedMapsController.prototype.instantiateTemplate = function(req, res, template_params, callback) { + var self = this; + + var layergroupDecorator = { + beforeLayergroupCreate: function(requestMapConfig, callback) { + self.layergroupRequestDecorator.beforeLayergroupCreate(req, requestMapConfig, callback); + }, + afterLayergroupCreate: function(layergroup, response, callback) { + self.layergroupRequestDecorator.afterLayergroupCreate(req, layergroup, response, callback); + } + }; + + var template; + var layergroup; + var cdbuser = req.context.user; + var params = { + user: req.params.user + }; + // Format of template_id: []@ + var tpl_id = templateName(req.params.template_id); + var auth_token = req.query.auth_token; + step( + function getTemplate(){ + self.templateMaps.getTemplate(cdbuser, tpl_id, this); + }, + function checkAuthorized(err, templateValue) { + if ( req.profiler ) req.profiler.done('getTemplate'); + if ( err ) throw err; + if ( ! templateValue ) { + err = new Error("Template '" + tpl_id + "' of user '" + cdbuser + "' not found"); + err.http_status = 404; + throw err; + } + + template = templateValue; + + var authorized = false; + try { + authorized = self.templateMaps.isAuthorized(template, auth_token); + } catch (err) { + // we catch to add http_status + err.http_status = 403; + throw err; + } + if ( ! authorized ) { + err = new Error('Unauthorized template instantiation'); + err.http_status = 403; + throw err; + } + + if (req.profiler) { + req.profiler.done('authorizedByCert'); + } + + return self.templateMaps.instance(template, template_params); + }, + function prepareParams(err, instance){ + if ( req.profiler ) req.profiler.done('TemplateMaps_instance'); + if ( err ) throw err; + layergroup = instance; + self.app.setDBParams(cdbuser, params, this); + }, + function setApiKey(err){ + if ( req.profiler ) req.profiler.done('setDBParams'); + if ( err ) throw err; + self.metadataBackend.getUserMapKey(cdbuser, this); + }, + function createLayergroup(err, val) { + if ( req.profiler ) req.profiler.done('getUserMapKey'); + if ( err ) throw err; + params.api_key = val; + self.mapBackend.createLayergroup(layergroup, params, layergroupDecorator, this); + }, + function prepareResponse(err, layergroup) { + if ( err ) { + return callback(err, { errors: [''+err] }); + } + var tplhash = self.templateMaps.fingerPrint(template).substring(0,8); + layergroup.layergroupid = cdbuser + '@' + tplhash + '@' + layergroup.layergroupid; + res.header('X-Layergroup-Id', layergroup.layergroupid); + + self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, template.name)); + + callback(null, layergroup); + } + ); +}; + +NamedMapsController.prototype.finish_instantiation = function(err, response, res) { + if (err) { + var statusCode = 400; + response = { errors: [''+err] }; + if ( ! _.isUndefined(err.http_status) ) { + statusCode = err.http_status; + } + this.app.sendError(res, response, statusCode, 'POST INSTANCE TEMPLATE', err); + } else { + this.app.sendResponse(res, [response, 200]); + } +}; + +function ifInvalidContentType(req, description) { + if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) { + throw new Error(description); + } +} + function getStaticImageOptions(template, callback) { if (template.view) { var zoomCenter = templateZoomCenter(template.view); diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 110c8c4b..bba292af 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -321,9 +321,11 @@ module.exports = function(serverOptions) { new controller.NamedMaps( app, + mapStore, templateMaps, metadataBackend, mapBackend, + tileBackend, previewBackend, template_baseurl, surrogateKeysCache, diff --git a/test/acceptance/named_static_maps.js b/test/acceptance/named_static_maps.js index 30f126d4..3df35b22 100644 --- a/test/acceptance/named_static_maps.js +++ b/test/acceptance/named_static_maps.js @@ -9,7 +9,7 @@ var server = new CartodbWindshaft(serverOptions); var TemplateMaps = require('../../lib/cartodb/backends/template_maps.js'); var NamedMapsCacheEntry = require('../../lib/cartodb/cache/model/named_maps_entry'); -describe.skip('named static maps', function() { +describe('named static maps', function() { // configure redis pool instance to use in tests var redisPool = new RedisPool(global.environment.redis);