diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index 3c3a2114..437a37cc 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -21,7 +21,7 @@ module.exports = NamedMapsController; var cdbRequest = new CdbRequest(); NamedMapsController.prototype.register = function(app) { - app.get(this.templateBaseUrl + '/:template_id/:layerFilter/:z/:x/:y.:format', this.tile.bind(this)); + app.get(this.templateBaseUrl + '/:template_id/:layer/:z/:x/:y.:format', this.tile.bind(this)); app.get(this.templateBaseUrl + '/:template_id/jsonp', this.jsonp.bind(this)); app.post(this.templateBaseUrl, this.create.bind(this)); app.put(this.templateBaseUrl + '/:template_id', this.update.bind(this)); @@ -33,8 +33,127 @@ NamedMapsController.prototype.register = function(app) { }; NamedMapsController.prototype.tile = function(req, res) { + var self = this; + this.app.doCORS(res); - this.app.sendResponse(res, [{}, 200]); + + var cdbUser = cdbRequest.userByReq(req); + var template; + var layergroupConfig; + var layergroupId; + var fakeReq; + var cacheChannel; + + step( + function reqParams() { + self.app.req2params(req, this); + }, + function getTemplate(err) { + assert.ifError(err); + self.templateMaps.getTemplate(cdbUser, templateName(req.params.template_id), this); + }, + function checkExists(err, tpl) { + assert.ifError(err); + if (!tpl) { + var notFoundErr = new Error( + "Template '" + templateName(req.params.template_id) + "' of user '" + cdbUser + "' not found" + ); + notFoundErr.http_status = 404; + throw notFoundErr; + } + return tpl; + }, + function checkAuthorized(err, tpl) { + assert.ifError(err); + + var authorized = false; + try { + authorized = self.templateMaps.isAuthorized(tpl, req.query.auth_token); + } catch (err) { + // we catch to add http_status + var authorizationFailedErr = new Error('Failed to authorize template'); + authorizationFailedErr.http_status = 403; + throw authorizationFailedErr; + } + if ( ! authorized ) { + var unauthorizedErr = new Error('Unauthorized template instantiation'); + unauthorizedErr.http_status = 403; + throw unauthorizedErr; + } + + return tpl; + }, + function prepareParams(err, tpl) { + assert.ifError(err); + + template = tpl; + + var templateParams = {}; + if (req.query.config) { + try { + templateParams = JSON.parse(req.query.config); + } catch (e) { + throw new Error('malformed config parameter, should be a valid JSON'); + } + } + + return templateParams; + }, + function instantiateTemplate(err, templateParams) { + assert.ifError(err); + return self.templateMaps.instance(template, templateParams); + }, + function prepareLayergroup(err, layergroup) { + assert.ifError(err); + layergroupConfig = layergroup; + fakeReq = { + query: {}, + params: _.extend({}, req.params, { + user: req.params.user + }), + headers: _.clone(req.headers), + context: _.clone(req.context), + method: req.method, + res: res, + profiler: req.profiler + }; + self.serverOptions.setDBParams(cdbUser, fakeReq.params, this); + }, + function setApiKey(err){ + assert.ifError(err); + self.mapBackend.createLayergroup(layergroupConfig, fakeReq, this); + }, + function prepareResponse(err, layergroup) { + assert.ifError(err); + + // added by createLayergroup + cacheChannel = res.header('X-Cache-Channel'); + res.removeHeader('X-Cache-Channel'); + self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbUser, template.name)); + + layergroupId = layergroup.layergroupid.split(":")[0]; + + return null; + }, + function getImage(err) { + assert.ifError(err); + + req.params.token = layergroupId; + self.mapBackend.getTileOrGrid(req, res, this); + }, + function handleImage(err, req, res, tile, headers) { + if (err) { + if (!err.error) { + err.error = err.message; + } + self.app.sendError(res, err, self.app.findStatusCode(err), 'NAMED_MAP_TILE', err); + } else { + res.setHeader('Content-Type', headers['Content-Type']); + res.setHeader('Cache-Control', 'public,max-age=7200,must-revalidate'); + self.app.sendResponse(res, [tile, 200]); + } + } + ); }; // Add a template