2015-03-16 07:21:55 +08:00
|
|
|
var step = require('step');
|
2015-04-23 17:29:55 +08:00
|
|
|
var assert = require('assert');
|
2015-01-20 23:56:06 +08:00
|
|
|
var _ = require('underscore');
|
2015-06-29 22:38:13 +08:00
|
|
|
var templateName = require('../backends/template_maps').templateName;
|
2015-04-27 20:52:36 +08:00
|
|
|
var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
|
2015-07-08 19:27:56 +08:00
|
|
|
var cors = require('../middleware/cors');
|
2015-01-20 23:56:06 +08:00
|
|
|
|
2015-07-08 21:50:59 +08:00
|
|
|
function NamedMapsController(app, templateMaps, metadataBackend, mapBackend, staticMapBackend, templateBaseUrl,
|
|
|
|
surrogateKeysCache, layergroupRequestDecorator, tablesExtentApi) {
|
2015-01-20 23:56:06 +08:00
|
|
|
this.app = app;
|
|
|
|
this.templateMaps = templateMaps;
|
|
|
|
this.metadataBackend = metadataBackend;
|
2015-06-30 00:58:58 +08:00
|
|
|
this.mapBackend = mapBackend;
|
2015-07-08 21:50:59 +08:00
|
|
|
this.staticMapBackend = staticMapBackend;
|
2015-01-20 23:56:06 +08:00
|
|
|
this.templateBaseUrl = templateBaseUrl;
|
2015-01-23 23:37:38 +08:00
|
|
|
this.surrogateKeysCache = surrogateKeysCache;
|
2015-07-06 08:08:56 +08:00
|
|
|
this.layergroupRequestDecorator = layergroupRequestDecorator;
|
2015-07-08 21:50:59 +08:00
|
|
|
this.tablesExtentApi = tablesExtentApi;
|
2015-01-20 23:56:06 +08:00
|
|
|
}
|
|
|
|
|
2015-04-27 21:01:49 +08:00
|
|
|
module.exports = NamedMapsController;
|
2015-01-20 23:56:06 +08:00
|
|
|
|
2015-04-27 21:01:49 +08:00
|
|
|
NamedMapsController.prototype.register = function(app) {
|
2015-07-08 19:27:56 +08:00
|
|
|
app.get(this.templateBaseUrl + '/:template_id/:layer/:z/:x/:y.:format', cors(), this.tile.bind(this));
|
|
|
|
app.get(this.templateBaseUrl + '/:template_id/jsonp', cors(), this.jsonp.bind(this));
|
2015-07-08 21:50:59 +08:00
|
|
|
app.get(
|
|
|
|
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format', cors(), this.staticMap.bind(this)
|
|
|
|
);
|
2015-07-08 19:27:56 +08:00
|
|
|
app.post(this.templateBaseUrl + '/:template_id', cors(), this.instantiate.bind(this));
|
2015-01-20 23:58:12 +08:00
|
|
|
};
|
|
|
|
|
2015-06-29 22:39:35 +08:00
|
|
|
NamedMapsController.prototype.tile = function(req, res) {
|
2015-06-30 21:41:57 +08:00
|
|
|
var self = this;
|
|
|
|
|
2015-07-08 21:34:46 +08:00
|
|
|
var cdbUser = req.context.user;
|
2015-06-30 21:41:57 +08:00
|
|
|
var template;
|
|
|
|
var layergroupConfig;
|
|
|
|
var layergroupId;
|
2015-07-02 08:02:22 +08:00
|
|
|
var params;
|
2015-06-30 21:41:57 +08:00
|
|
|
var cacheChannel;
|
|
|
|
|
2015-07-02 08:02:22 +08:00
|
|
|
var layergroupDecorator = {
|
|
|
|
beforeLayergroupCreate: function(requestMapConfig, callback) {
|
2015-07-05 02:41:22 +08:00
|
|
|
self.layergroupRequestDecorator.beforeLayergroupCreate(req, requestMapConfig, callback);
|
2015-07-02 08:02:22 +08:00
|
|
|
},
|
|
|
|
afterLayergroupCreate: function(layergroup, response, callback) {
|
2015-07-05 02:41:22 +08:00
|
|
|
self.layergroupRequestDecorator.afterLayergroupCreate(req, layergroup, response, callback);
|
2015-07-02 08:02:22 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-30 21:41:57 +08:00
|
|
|
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;
|
2015-07-02 08:02:22 +08:00
|
|
|
params = _.extend({}, req.params, {
|
|
|
|
user: req.params.user
|
|
|
|
});
|
2015-07-05 02:41:22 +08:00
|
|
|
self.app.setDBParams(cdbUser, params, this);
|
2015-06-30 21:41:57 +08:00
|
|
|
},
|
|
|
|
function setApiKey(err){
|
|
|
|
assert.ifError(err);
|
2015-07-02 08:02:22 +08:00
|
|
|
self.mapBackend.createLayergroup(layergroupConfig, params, layergroupDecorator, this);
|
2015-06-30 21:41:57 +08:00
|
|
|
},
|
|
|
|
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;
|
2015-07-02 08:02:22 +08:00
|
|
|
self.mapBackend.getTileOrGrid(req.params, this);
|
2015-06-30 21:41:57 +08:00
|
|
|
},
|
2015-07-02 08:02:22 +08:00
|
|
|
function handleImage(err, tile, headers, stats) {
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.add(stats);
|
|
|
|
}
|
2015-06-30 21:41:57 +08:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2015-06-29 22:39:35 +08:00
|
|
|
};
|
|
|
|
|
2015-04-27 21:01:49 +08:00
|
|
|
NamedMapsController.prototype.instantiate = function(req, res) {
|
2015-01-21 00:57:53 +08:00
|
|
|
var self = this;
|
|
|
|
|
2015-04-14 22:40:15 +08:00
|
|
|
if (req.profiler) {
|
2015-01-21 00:57:53 +08:00
|
|
|
req.profiler.start('windshaft-cartodb.instance_template_post');
|
|
|
|
}
|
2015-03-16 07:21:55 +08:00
|
|
|
step(
|
2015-06-30 01:18:52 +08:00
|
|
|
function instantiateTemplate() {
|
2015-04-23 18:05:52 +08:00
|
|
|
ifInvalidContentType(req, 'template POST data must be of type application/json');
|
|
|
|
|
2015-01-21 00:57:53 +08:00
|
|
|
self.instantiateTemplate(req, res, req.body, this);
|
2015-06-30 01:18:52 +08:00
|
|
|
}, function finishInstantiation(err, response) {
|
2015-04-14 22:41:04 +08:00
|
|
|
self.finish_instantiation(err, response, res);
|
2015-01-21 00:57:53 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2015-01-20 23:56:06 +08:00
|
|
|
/**
|
|
|
|
* jsonp endpoint, allows to instantiate a template with a json call.
|
|
|
|
* callback query argument is mandatory
|
|
|
|
*/
|
2015-04-27 21:01:49 +08:00
|
|
|
NamedMapsController.prototype.jsonp = function(req, res) {
|
2015-01-20 23:56:06 +08:00
|
|
|
var self = this;
|
|
|
|
|
2015-04-14 22:40:15 +08:00
|
|
|
if (req.profiler) {
|
2015-01-20 23:56:06 +08:00
|
|
|
req.profiler.start('windshaft-cartodb.instance_template_get');
|
|
|
|
}
|
2015-03-16 07:21:55 +08:00
|
|
|
step(
|
2015-07-02 08:02:22 +08:00
|
|
|
function jsonp$instantiateTemplate() {
|
2015-01-20 23:56:06 +08:00
|
|
|
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) {
|
2015-07-08 21:34:46 +08:00
|
|
|
throw new Error('Invalid config parameter, should be a valid JSON');
|
2015-01-20 23:56:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
self.instantiateTemplate(req, res, config, this);
|
2015-06-30 01:18:52 +08:00
|
|
|
}, function finishInstantiation(err, response) {
|
2015-04-14 22:41:04 +08:00
|
|
|
self.finish_instantiation(err, response, res);
|
2015-01-20 23:56:06 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Instantiate a template
|
2015-04-27 21:01:49 +08:00
|
|
|
NamedMapsController.prototype.instantiateTemplate = function(req, res, template_params, callback) {
|
2015-01-20 23:56:06 +08:00
|
|
|
var self = this;
|
|
|
|
|
2015-07-02 08:02:22 +08:00
|
|
|
var layergroupDecorator = {
|
|
|
|
beforeLayergroupCreate: function(requestMapConfig, callback) {
|
2015-07-05 02:41:22 +08:00
|
|
|
self.layergroupRequestDecorator.beforeLayergroupCreate(req, requestMapConfig, callback);
|
2015-07-02 08:02:22 +08:00
|
|
|
},
|
|
|
|
afterLayergroupCreate: function(layergroup, response, callback) {
|
2015-07-05 02:41:22 +08:00
|
|
|
self.layergroupRequestDecorator.afterLayergroupCreate(req, layergroup, response, callback);
|
2015-07-02 08:02:22 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-01-20 23:56:06 +08:00
|
|
|
var template;
|
|
|
|
var layergroup;
|
2015-07-08 21:34:46 +08:00
|
|
|
var cdbuser = req.context.user;
|
2015-07-02 08:02:22 +08:00
|
|
|
var params = {
|
|
|
|
user: req.params.user
|
|
|
|
};
|
2015-01-20 23:56:06 +08:00
|
|
|
// Format of template_id: [<template_owner>]@<template_id>
|
2015-04-23 17:29:55 +08:00
|
|
|
var tpl_id = templateName(req.params.template_id);
|
2015-01-20 23:56:06 +08:00
|
|
|
var auth_token = req.query.auth_token;
|
2015-03-16 07:21:55 +08:00
|
|
|
step(
|
2015-01-20 23:56:06 +08:00
|
|
|
function getTemplate(){
|
|
|
|
self.templateMaps.getTemplate(cdbuser, tpl_id, this);
|
|
|
|
},
|
2015-01-22 22:40:40 +08:00
|
|
|
function checkAuthorized(err, templateValue) {
|
2015-01-20 23:56:06 +08:00
|
|
|
if ( req.profiler ) req.profiler.done('getTemplate');
|
|
|
|
if ( err ) throw err;
|
2015-01-22 22:40:40 +08:00
|
|
|
if ( ! templateValue ) {
|
2015-01-20 23:56:06 +08:00
|
|
|
err = new Error("Template '" + tpl_id + "' of user '" + cdbuser + "' not found");
|
|
|
|
err.http_status = 404;
|
|
|
|
throw err;
|
|
|
|
}
|
2015-01-22 22:40:40 +08:00
|
|
|
|
|
|
|
template = templateValue;
|
|
|
|
|
2015-01-20 23:56:06 +08:00
|
|
|
var authorized = false;
|
|
|
|
try {
|
2015-01-22 22:40:40 +08:00
|
|
|
authorized = self.templateMaps.isAuthorized(template, auth_token);
|
2015-01-20 23:56:06 +08:00
|
|
|
} catch (err) {
|
|
|
|
// we catch to add http_status
|
|
|
|
err.http_status = 403;
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
if ( ! authorized ) {
|
2015-07-08 21:34:46 +08:00
|
|
|
err = new Error('Unauthorized template instantiation');
|
2015-01-20 23:56:06 +08:00
|
|
|
err.http_status = 403;
|
|
|
|
throw err;
|
|
|
|
}
|
2015-01-22 22:40:40 +08:00
|
|
|
|
|
|
|
if (req.profiler) {
|
|
|
|
req.profiler.done('authorizedByCert');
|
|
|
|
}
|
|
|
|
|
2015-01-20 23:56:06 +08:00
|
|
|
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;
|
2015-07-05 02:41:22 +08:00
|
|
|
self.app.setDBParams(cdbuser, params, this);
|
2015-01-20 23:56:06 +08:00
|
|
|
},
|
|
|
|
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;
|
2015-07-02 08:02:22 +08:00
|
|
|
params.api_key = val;
|
|
|
|
self.mapBackend.createLayergroup(layergroup, params, layergroupDecorator, this);
|
2015-01-20 23:56:06 +08:00
|
|
|
},
|
2015-01-22 22:40:40 +08:00
|
|
|
function prepareResponse(err, layergroup) {
|
|
|
|
if ( err ) {
|
2015-06-06 01:38:38 +08:00
|
|
|
return callback(err, { errors: [''+err] });
|
2015-01-20 23:56:06 +08:00
|
|
|
}
|
|
|
|
var tplhash = self.templateMaps.fingerPrint(template).substring(0,8);
|
2015-01-22 22:40:40 +08:00
|
|
|
layergroup.layergroupid = cdbuser + '@' + tplhash + '@' + layergroup.layergroupid;
|
2015-06-18 07:13:33 +08:00
|
|
|
res.header('X-Layergroup-Id', layergroup.layergroupid);
|
2015-01-23 23:37:38 +08:00
|
|
|
|
2015-04-27 20:52:36 +08:00
|
|
|
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, template.name));
|
2015-01-23 23:37:38 +08:00
|
|
|
|
2015-06-06 01:38:38 +08:00
|
|
|
callback(null, layergroup);
|
|
|
|
}
|
2015-01-20 23:56:06 +08:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2015-04-27 21:01:49 +08:00
|
|
|
NamedMapsController.prototype.finish_instantiation = function(err, response, res) {
|
2015-01-20 23:56:06 +08:00
|
|
|
if (err) {
|
|
|
|
var statusCode = 400;
|
2015-06-06 01:38:38 +08:00
|
|
|
response = { errors: [''+err] };
|
2015-01-20 23:56:06 +08:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
};
|
2015-01-21 01:14:10 +08:00
|
|
|
|
2015-04-23 18:05:52 +08:00
|
|
|
function ifInvalidContentType(req, description) {
|
|
|
|
if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) {
|
|
|
|
throw new Error(description);
|
|
|
|
}
|
|
|
|
}
|
2015-07-08 21:50:59 +08:00
|
|
|
|
|
|
|
NamedMapsController.prototype.staticMap = function(req, res) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var cdbUser = req.context.user;
|
|
|
|
|
|
|
|
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
|
|
|
|
|
|
|
|
var template;
|
|
|
|
var layergroupConfig;
|
|
|
|
var layergroupId;
|
|
|
|
var params;
|
|
|
|
var cacheChannel;
|
|
|
|
|
|
|
|
var layergroupDecorator = {
|
|
|
|
beforeLayergroupCreate: function(requestMapConfig, callback) {
|
|
|
|
self.layergroupRequestDecorator.beforeLayergroupCreate(req, requestMapConfig, callback);
|
|
|
|
},
|
|
|
|
afterLayergroupCreate: function(layergroup, response, callback) {
|
|
|
|
self.layergroupRequestDecorator.afterLayergroupCreate(req, layergroup, response, callback);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
params = {
|
|
|
|
user: req.params.user
|
|
|
|
};
|
|
|
|
self.app.setDBParams(cdbUser, params, this);
|
|
|
|
},
|
|
|
|
function setApiKey(err){
|
|
|
|
assert.ifError(err);
|
|
|
|
self.mapBackend.createLayergroup(layergroupConfig, params, layergroupDecorator, 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 staticImageOptions(err) {
|
|
|
|
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 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 imageParams = _.extend({}, params, {
|
|
|
|
token: layergroupId,
|
|
|
|
format: req.params.format
|
|
|
|
});
|
|
|
|
|
|
|
|
var width = +req.params.width;
|
|
|
|
var height = +req.params.height;
|
|
|
|
|
|
|
|
if (!_.isUndefined(imageOpts.zoom) && imageOpts.center) {
|
|
|
|
self.staticMapBackend.getImage(imageParams, width, height, imageOpts.zoom, imageOpts.center, this);
|
|
|
|
} else {
|
|
|
|
self.staticMapBackend.getImage(imageParams, 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) {
|
|
|
|
if (!err.error) {
|
|
|
|
err.error = err.message;
|
|
|
|
}
|
|
|
|
self.app.sendError(res, err, self.app.findStatusCode(err), 'STATIC_VIZ_MAP', err);
|
|
|
|
} else {
|
|
|
|
res.setHeader('Content-Type', headers['Content-Type'] || 'image/' + format);
|
|
|
|
res.setHeader('Cache-Control', 'public,max-age=7200,must-revalidate');
|
|
|
|
self.app.sendResponse(res, [image, 200]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|