NamedMaps controller using NamedMapMapConfigProvider

PreviewBackend with format param
This commit is contained in:
Raul Ochoa
2015-07-09 18:47:21 +02:00
parent 23d1109910
commit 5aad624346
3 changed files with 119 additions and 256 deletions
+4 -2
View File
@@ -233,6 +233,8 @@ MapController.prototype.center = function(req, res) {
MapController.prototype.staticMap = function(req, res, width, height, zoom /* bounds */, center) {
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
req.params.layer = 'all';
req.params.format = 'png';
var self = this;
@@ -245,10 +247,10 @@ MapController.prototype.staticMap = function(req, res, width, height, zoom /* bo
assert.ifError(err);
if (center) {
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
req.params, width, height, zoom, center, this);
format, width, height, zoom, center, this);
} else {
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
req.params, width, height, zoom /* bounds */, this);
format, width, height, zoom /* bounds */, this);
}
},
function handleImage(err, image, headers, stats) {
+34 -202
View File
@@ -1,11 +1,9 @@
var step = require('step');
var assert = require('assert');
var _ = require('underscore');
var templateName = require('../backends/template_maps').templateName;
var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
var cors = require('../middleware/cors');
var MapStoreMapConfigProvider = require('windshaft').model.provider.MapStoreMapConfig;
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
function NamedMapsController(app, pgConnection, mapStore, templateMaps, metadataBackend, mapBackend, tileBackend,
@@ -28,7 +26,7 @@ function NamedMapsController(app, pgConnection, mapStore, templateMaps, metadata
module.exports = NamedMapsController;
NamedMapsController.prototype.register = function(app) {
app.get(this.templateBaseUrl + '/:template_id/:layer/:z/:x/:y.:format', cors(), this.tile.bind(this));
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));
app.get(
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format', cors(), this.staticMap.bind(this)
@@ -87,109 +85,23 @@ NamedMapsController.prototype.tile = function(req, res) {
var self = this;
var cdbUser = req.context.user;
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);
}
};
var namedMapProvider;
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 = _.extend({}, req.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 getImage(err) {
assert.ifError(err);
req.params.token = layergroupId;
self.tileBackend.getTile(new MapStoreMapConfigProvider(self.mapStore, req.params), params, this);
function getTile() {
namedMapProvider = new NamedMapMapConfigProvider(
self.templateMaps,
self.pgConnection,
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) {
@@ -201,6 +113,7 @@ NamedMapsController.prototype.tile = function(req, res) {
}
self.app.sendError(res, err, self.app.findStatusCode(err), 'NAMED_MAP_TILE', err);
} else {
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbUser, namedMapProvider.getTemplateName()));
res.setHeader('Content-Type', headers['Content-Type']);
res.setHeader('Cache-Control', 'public,max-age=7200,must-revalidate');
self.app.sendResponse(res, [tile, 200]);
@@ -215,106 +128,28 @@ NamedMapsController.prototype.staticMap = function(req, res) {
var cdbUser = req.context.user;
var format = req.params.format === 'jpg' ? 'jpeg' : 'png';
req.params.format = 'png';
req.params.layer = 'all';
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);
}
};
var namedMapProvider;
step(
function reqParams() {
self.app.req2params(req, this);
},
function getTemplate(err) {
assert.ifError(err);
self.templateMaps.getTemplate(cdbUser, templateName(req.params.template_id), this);
namedMapProvider = new NamedMapMapConfigProvider(
self.templateMaps,
self.pgConnection,
cdbUser,
req.params.template_id,
req.query.config,
req.query.auth_token,
req.params
);
namedMapProvider.getTemplate(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) {
function prepareStaticImageOptions(err, template) {
assert.ifError(err);
getStaticImageOptions(template, this);
},
@@ -332,6 +167,8 @@ NamedMapsController.prototype.staticMap = function(req, res) {
}
};
var cacheChannel = '';
var dbTables = cacheChannel.split(':');
if (dbTables.length <= 1 || dbTables[1].length === 0) {
return defaultZoomCenter;
@@ -350,21 +187,15 @@ NamedMapsController.prototype.staticMap = function(req, res) {
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;
var provider = new MapStoreMapConfigProvider(self.mapStore, imageParams);
if (!_.isUndefined(imageOpts.zoom) && imageOpts.center) {
self.previewBackend.getImage(
provider, imageParams, width, height, imageOpts.zoom, imageOpts.center, this);
namedMapProvider, format, width, height, imageOpts.zoom, imageOpts.center, this);
} else {
self.previewBackend.getImage(
provider, imageParams, width, height, imageOpts.bounds, this);
namedMapProvider, format, width, height, imageOpts.bounds, this);
}
},
function handleImage(err, image, headers, stats) {
@@ -379,6 +210,7 @@ NamedMapsController.prototype.staticMap = function(req, res) {
}
self.app.sendError(res, err, self.app.findStatusCode(err), 'STATIC_VIZ_MAP', err);
} else {
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbUser, namedMapProvider.getTemplateName()));
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]);
@@ -418,7 +250,7 @@ NamedMapsController.prototype.instantiateTemplate = function(req, res, template_
},
function createLayergroup(err, mapConfig, rendererParams/*, context*/) {
assert.ifError(err);
self.mapBackend.createLayergroup(mapConfig, rendererParams, layergroupDecorator, this);
self.mapBackend.createLayergroup(mapConfig.obj(), rendererParams, layergroupDecorator, this);
},
function prepareResponse(err, layergroup) {
if (err) {
@@ -1,13 +1,15 @@
var _ = require('underscore');
var assert = require('assert');
var dot = require('dot');
var step = require('step');
var MapConfig = require('windshaft').model.MapConfig;
var templateName = require('../../backends/template_maps').templateName;
function NamedMapMapConfigProvider(templateMaps, pgConnection, owner, templateId, config, authToken, params) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.owner = owner;
this.templateId = templateId;
this.templateName = templateName(templateId);
this.config = config;
this.authToken = authToken;
this.params = params;
@@ -25,51 +27,19 @@ function NamedMapMapConfigProvider(templateMaps, pgConnection, owner, templateId
module.exports = NamedMapMapConfigProvider;
NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
if (this.err !== null || this.mapConfig !== null) {
if (!!this.err || this.mapConfig !== null) {
return callback(this.err, this.mapConfig, this.rendererParams, this.context);
}
var self = this;
var mapConfig;
var mapConfig = null;
var rendererParams;
var context = {};
step(
function getTemplate(err) {
assert.ifError(err);
self.templateMaps.getTemplate(self.owner, templateName(self.templateId), this);
},
function checkExists(err, tpl) {
assert.ifError(err);
if (!tpl) {
var notFoundErr = new Error(
"Template '" + templateName(self.templateId) + "' of user '" + self.owner + "' 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, self.authToken);
} 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 getTemplate() {
self.getTemplate(this);
},
function prepareParams(err, tpl) {
assert.ifError(err);
@@ -101,7 +71,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
},
function cacheAndReturnMapConfig(err) {
self.err = err;
self.mapConfig = mapConfig;
self.mapConfig = (mapConfig === null) ? null : MapConfig.create(mapConfig);
self.rendererParams = rendererParams;
self.context = context;
return callback(self.err, self.mapConfig, self.rendererParams, self.context);
@@ -109,8 +79,58 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
);
};
NamedMapMapConfigProvider.prototype.getTemplate = function(callback) {
var self = this;
if (!!this.err || this.template !== null) {
return callback(this.err, this.template);
}
step(
function getTemplate() {
self.templateMaps.getTemplate(self.owner, self.templateName, this);
},
function checkExists(err, tpl) {
assert.ifError(err);
if (!tpl) {
var notFoundErr = new Error(
"Template '" + self.templateName + "' of user '" + self.owner + "' 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, self.authToken);
} 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 cacheAndReturnTemplate(err, template) {
self.err = err;
self.template = template;
return callback(self.err, self.template);
}
);
};
NamedMapMapConfigProvider.prototype.getKey = function() {
return createKey(this.params);
return this.createKey();
};
NamedMapMapConfigProvider.prototype.getCacheBuster = function() {
@@ -118,24 +138,29 @@ NamedMapMapConfigProvider.prototype.getCacheBuster = function() {
};
NamedMapMapConfigProvider.prototype.filter = function(key) {
var regex = new RegExp('^' + createKey(this.params, true) + '.*');
var regex = new RegExp('^' + this.createKey(true) + '.*');
return key && key.match(regex);
};
// Configure bases for cache keys suitable for string interpolation
var baseKey = '<%= dbname %>:<%= owner %>:<%= templateName %>';
var renderKey = baseKey + ':<%= authToken %>:<%= configHash %>:<%= layer %>:<%= scale_factor %>';
// Create a string ID/key from a set of params
function createKey(params, base) {
return _.template(base ? baseKey : renderKey, _.defaults({}, params, {
var baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}';
var rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}';
var baseKeyTpl = dot.template(baseKey);
var rendererKeyTpl = dot.template(rendererKey);
NamedMapMapConfigProvider.prototype.createKey = function(base) {
var tplValues = _.defaults({}, this.params, {
dbname: '',
owner: '',
templateName: '',
authToken: '',
configHash: '',
owner: this.owner,
templateName: this.templateName,
authToken: this.authToken || '',
configHash: this.config && this.config.toString() || '',
layer: '',
scale_factor: 1
}));
}
});
return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues);
};
NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, callback) {
var self = this;
@@ -151,4 +176,8 @@ NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, call
callback(err);
}
);
};
};
NamedMapMapConfigProvider.prototype.getTemplateName = function() {
return this.templateName;
};