Splits controllers and supports after layergroup creation actions
This commit is contained in:
parent
6e0678e084
commit
9bece712a9
@ -1,4 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
Layergroup: require('./layergroup'),
|
||||||
Map: require('./map'),
|
Map: require('./map'),
|
||||||
NamedMaps: require('./named_maps'),
|
NamedMaps: require('./named_maps'),
|
||||||
NamedMapsAdmin: require('./named_maps_admin'),
|
NamedMapsAdmin: require('./named_maps_admin'),
|
||||||
|
205
lib/cartodb/controllers/layergroup.js
Normal file
205
lib/cartodb/controllers/layergroup.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
var assert = require('assert');
|
||||||
|
var step = require('step');
|
||||||
|
|
||||||
|
var cors = require('../middleware/cors');
|
||||||
|
|
||||||
|
var windshaft = require('windshaft');
|
||||||
|
var MapStoreMapConfigProvider = windshaft.model.provider.MapStoreMapConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param app
|
||||||
|
* @param {MapStore} mapStore
|
||||||
|
* @param {TileBackend} tileBackend
|
||||||
|
* @param {PreviewBackend} previewBackend
|
||||||
|
* @param {AttributesBackend} attributesBackend
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function LayergroupController(app, mapStore, tileBackend, previewBackend, attributesBackend) {
|
||||||
|
this.app = app;
|
||||||
|
this.mapStore = mapStore;
|
||||||
|
this.tileBackend = tileBackend;
|
||||||
|
this.previewBackend = previewBackend;
|
||||||
|
this.attributesBackend = attributesBackend;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = LayergroupController;
|
||||||
|
|
||||||
|
|
||||||
|
LayergroupController.prototype.register = function(app) {
|
||||||
|
app.get(app.base_url_mapconfig + '/:token/:z/:x/:y@:scale_factor?x.:format', cors(), this.tile.bind(this));
|
||||||
|
app.get(app.base_url_mapconfig + '/:token/:z/:x/:y.:format', cors(), this.tile.bind(this));
|
||||||
|
app.get(app.base_url_mapconfig + '/:token/:layer/:z/:x/:y.(:format)', cors(), this.layer.bind(this));
|
||||||
|
app.get(app.base_url_mapconfig + '/:token/:layer/attributes/:fid', cors(), this.attributes.bind(this));
|
||||||
|
app.get(app.base_url_mapconfig + '/static/center/:token/:z/:lat/:lng/:width/:height.:format', cors(),
|
||||||
|
this.center.bind(this));
|
||||||
|
app.get(app.base_url_mapconfig + '/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format', cors(),
|
||||||
|
this.bbox.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
LayergroupController.prototype.attributes = function(req, res) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
req.profiler.start('windshaft.maplayer_attribute');
|
||||||
|
|
||||||
|
step(
|
||||||
|
function setupParams() {
|
||||||
|
self.app.req2params(req, this);
|
||||||
|
},
|
||||||
|
function retrieveFeatureAttributes(err) {
|
||||||
|
req.profiler.done('req2params');
|
||||||
|
|
||||||
|
assert.ifError(err);
|
||||||
|
|
||||||
|
self.attributesBackend.getFeatureAttributes(req.params, false, this);
|
||||||
|
},
|
||||||
|
function finish(err, tile, stats) {
|
||||||
|
req.profiler.add(stats || {});
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
// See https://github.com/Vizzuality/Windshaft-cartodb/issues/68
|
||||||
|
var errMsg = err.message ? ( '' + err.message ) : ( '' + err );
|
||||||
|
var statusCode = self.app.findStatusCode(err);
|
||||||
|
self.app.sendError(res, { errors: [errMsg] }, statusCode, 'GET ATTRIBUTES', err);
|
||||||
|
} else {
|
||||||
|
self.app.sendResponse(res, [tile, 200]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets a tile for a given token and set of tile ZXY coords. (OSM style)
|
||||||
|
LayergroupController.prototype.tile = function(req, res) {
|
||||||
|
req.profiler.start('windshaft.map_tile');
|
||||||
|
this.tileOrLayer(req, res);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets a tile for a given token, layer set of tile ZXY coords. (OSM style)
|
||||||
|
LayergroupController.prototype.layer = function(req, res, next) {
|
||||||
|
if (req.params.token === 'static') {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
req.profiler.start('windshaft.maplayer_tile');
|
||||||
|
this.tileOrLayer(req, res);
|
||||||
|
};
|
||||||
|
|
||||||
|
LayergroupController.prototype.tileOrLayer = function (req, res) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
step(
|
||||||
|
function mapController$prepareParams() {
|
||||||
|
self.app.req2params(req, this);
|
||||||
|
},
|
||||||
|
function mapController$getTileOrGrid(err) {
|
||||||
|
req.profiler.done('req2params');
|
||||||
|
if ( err ) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
self.tileBackend.getTile(new MapStoreMapConfigProvider(self.mapStore, req.params), req.params, this);
|
||||||
|
},
|
||||||
|
function mapController$finalize(err, tile, headers, stats) {
|
||||||
|
req.profiler.add(stats);
|
||||||
|
self.finalizeGetTileOrGrid(err, req, res, tile, headers);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
function finish(err) {
|
||||||
|
if ( err ) {
|
||||||
|
console.error("windshaft.tiles: " + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This function is meant for being called as the very last
|
||||||
|
// step by all endpoints serving tiles or grids
|
||||||
|
LayergroupController.prototype.finalizeGetTileOrGrid = function(err, req, res, tile, headers) {
|
||||||
|
var supportedFormats = {
|
||||||
|
grid_json: true,
|
||||||
|
json_torque: true,
|
||||||
|
torque_json: true,
|
||||||
|
png: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var formatStat = 'invalid';
|
||||||
|
if (req.params.format) {
|
||||||
|
var format = req.params.format.replace('.', '_');
|
||||||
|
if (supportedFormats[format]) {
|
||||||
|
formatStat = format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err){
|
||||||
|
// See https://github.com/Vizzuality/Windshaft-cartodb/issues/68
|
||||||
|
var errMsg = err.message ? ( '' + err.message ) : ( '' + err );
|
||||||
|
var statusCode = this.app.findStatusCode(err);
|
||||||
|
|
||||||
|
// Rewrite mapnik parsing errors to start with layer number
|
||||||
|
var matches = errMsg.match("(.*) in style 'layer([0-9]+)'");
|
||||||
|
if (matches) {
|
||||||
|
errMsg = 'style'+matches[2]+': ' + matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.app.sendError(res, { errors: ['' + errMsg] }, statusCode, 'TILE RENDER', err);
|
||||||
|
global.statsClient.increment('windshaft.tiles.error');
|
||||||
|
global.statsClient.increment('windshaft.tiles.' + formatStat + '.error');
|
||||||
|
} else {
|
||||||
|
this.app.sendWithHeaders(res, tile, 200, headers);
|
||||||
|
global.statsClient.increment('windshaft.tiles.success');
|
||||||
|
global.statsClient.increment('windshaft.tiles.' + formatStat + '.success');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LayergroupController.prototype.bbox = function(req, res) {
|
||||||
|
this.staticMap(req, res, +req.params.width, +req.params.height, {
|
||||||
|
west: +req.params.west,
|
||||||
|
north: +req.params.north,
|
||||||
|
east: +req.params.east,
|
||||||
|
south: +req.params.south
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LayergroupController.prototype.center = function(req, res) {
|
||||||
|
this.staticMap(req, res, +req.params.width, +req.params.height, +req.params.z, {
|
||||||
|
lng: +req.params.lng,
|
||||||
|
lat: +req.params.lat
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LayergroupController.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;
|
||||||
|
|
||||||
|
step(
|
||||||
|
function() {
|
||||||
|
self.app.req2params(req, this);
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
req.profiler.done('req2params');
|
||||||
|
assert.ifError(err);
|
||||||
|
if (center) {
|
||||||
|
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
|
||||||
|
format, width, height, zoom, center, this);
|
||||||
|
} else {
|
||||||
|
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
|
||||||
|
format, width, height, zoom /* bounds */, this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function handleImage(err, image, headers, stats) {
|
||||||
|
req.profiler.done('render-' + format);
|
||||||
|
req.profiler.add(stats || {});
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
if (!err.error) {
|
||||||
|
err.error = err.message;
|
||||||
|
}
|
||||||
|
self.app.sendError(res, {errors: ['' + err] }, self.app.findStatusCode(err), 'STATIC_MAP', err);
|
||||||
|
} else {
|
||||||
|
res.setHeader('Content-Type', headers['Content-Type'] || 'image/' + format);
|
||||||
|
self.app.sendResponse(res, [image, 200]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
@ -1,37 +1,37 @@
|
|||||||
|
var _ = require('underscore');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
var step = require('step');
|
var step = require('step');
|
||||||
|
var windshaft = require('windshaft');
|
||||||
|
|
||||||
var cors = require('../middleware/cors');
|
var cors = require('../middleware/cors');
|
||||||
|
|
||||||
var windshaft = require('windshaft');
|
|
||||||
var MapStoreMapConfigProvider = windshaft.model.provider.MapStoreMapConfig;
|
|
||||||
var MapConfig = windshaft.model.MapConfig;
|
var MapConfig = windshaft.model.MapConfig;
|
||||||
var Datasource = windshaft.model.Datasource;
|
var Datasource = windshaft.model.Datasource;
|
||||||
|
|
||||||
|
var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
|
||||||
|
|
||||||
var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter');
|
var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter');
|
||||||
|
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param app
|
* @param app
|
||||||
* @param {PgConnection} pgConnection
|
* @param {PgConnection} pgConnection
|
||||||
* @param {MapStore} mapStore
|
|
||||||
* @param {TemplateMaps} templateMaps
|
* @param {TemplateMaps} templateMaps
|
||||||
* @param {MapBackend} mapBackend
|
* @param {MapBackend} mapBackend
|
||||||
* @param {TileBackend} tileBackend
|
* @param metadataBackend
|
||||||
* @param {PreviewBackend} previewBackend
|
* @param {QueryTablesApi} queryTablesApi
|
||||||
* @param {AttributesBackend} attributesBackend
|
* @param {SurrogateKeysCache} surrogateKeysCache
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function MapController(app, pgConnection, mapStore, templateMaps, mapBackend, tileBackend, previewBackend,
|
function MapController(app, pgConnection, templateMaps, mapBackend, metadataBackend, queryTablesApi,
|
||||||
attributesBackend) {
|
surrogateKeysCache) {
|
||||||
this._app = app;
|
this.app = app;
|
||||||
this.pgConnection = pgConnection;
|
this.pgConnection = pgConnection;
|
||||||
this.mapStore = mapStore;
|
|
||||||
this.templateMaps = templateMaps;
|
this.templateMaps = templateMaps;
|
||||||
this.mapBackend = mapBackend;
|
this.mapBackend = mapBackend;
|
||||||
this.tileBackend = tileBackend;
|
this.metadataBackend = metadataBackend;
|
||||||
this.previewBackend = previewBackend;
|
this.queryTablesApi = queryTablesApi;
|
||||||
this.attributesBackend = attributesBackend;
|
this.surrogateKeysCache = surrogateKeysCache;
|
||||||
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
|
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,57 +39,82 @@ module.exports = MapController;
|
|||||||
|
|
||||||
|
|
||||||
MapController.prototype.register = function(app) {
|
MapController.prototype.register = function(app) {
|
||||||
app.get(app.base_url_mapconfig + '/:token/:z/:x/:y@:scale_factor?x.:format', cors(), this.tile.bind(this));
|
|
||||||
app.get(app.base_url_mapconfig + '/:token/:z/:x/:y.:format', cors(), this.tile.bind(this));
|
|
||||||
app.get(app.base_url_mapconfig + '/:token/:layer/:z/:x/:y.(:format)', cors(), this.layer.bind(this));
|
|
||||||
app.options(app.base_url_mapconfig, cors('Content-Type'));
|
|
||||||
app.get(app.base_url_mapconfig, cors(), this.createGet.bind(this));
|
app.get(app.base_url_mapconfig, cors(), this.createGet.bind(this));
|
||||||
app.post(app.base_url_mapconfig, cors(), this.createPost.bind(this));
|
app.post(app.base_url_mapconfig, cors(), this.createPost.bind(this));
|
||||||
app.get(app.base_url_mapconfig + '/:token/:layer/attributes/:fid', cors(), this.attributes.bind(this));
|
app.get(app.base_url_templated + '/:template_id/jsonp', cors(), this.jsonp.bind(this));
|
||||||
app.get(app.base_url_mapconfig + '/static/center/:token/:z/:lat/:lng/:width/:height.:format', cors(),
|
app.post(app.base_url_templated + '/:template_id', cors(), this.instantiate.bind(this));
|
||||||
this.center.bind(this));
|
app.options(app.base_url_mapconfig, cors('Content-Type'));
|
||||||
app.get(app.base_url_mapconfig + '/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format', cors(),
|
|
||||||
this.bbox.bind(this));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MapController.prototype.attributes = function(req, res) {
|
MapController.prototype.createGet = function(req, res){
|
||||||
var self = this;
|
req.profiler.start('windshaft.createmap_get');
|
||||||
|
|
||||||
req.profiler.start('windshaft.maplayer_attribute');
|
|
||||||
|
|
||||||
step(
|
|
||||||
function setupParams() {
|
|
||||||
self._app.req2params(req, this);
|
|
||||||
},
|
|
||||||
function retrieveFeatureAttributes(err) {
|
|
||||||
req.profiler.done('req2params');
|
|
||||||
|
|
||||||
|
this.create(req, res, function createGet$prepareConfig(err, req) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
if ( ! req.params.config ) {
|
||||||
|
throw new Error('layergroup GET needs a "config" parameter');
|
||||||
|
}
|
||||||
|
return JSON.parse(req.params.config);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
self.attributesBackend.getFeatureAttributes(req.params, false, this);
|
MapController.prototype.createPost = function(req, res) {
|
||||||
},
|
req.profiler.start('windshaft.createmap_post');
|
||||||
function finish(err, tile, stats) {
|
|
||||||
req.profiler.add(stats || {});
|
|
||||||
|
|
||||||
if (err) {
|
this.create(req, res, function createPost$prepareConfig(err, req) {
|
||||||
// See https://github.com/Vizzuality/Windshaft-cartodb/issues/68
|
assert.ifError(err);
|
||||||
var errMsg = err.message ? ( '' + err.message ) : ( '' + err );
|
if (!req.is('application/json')) {
|
||||||
var statusCode = self._app.findStatusCode(err);
|
throw new Error('layergroup POST data must be of type application/json');
|
||||||
self._app.sendError(res, { errors: [errMsg] }, statusCode, 'GET ATTRIBUTES', err);
|
}
|
||||||
} else {
|
return req.body;
|
||||||
self._app.sendResponse(res, [tile, 200]);
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MapController.prototype.instantiate = function(req, res) {
|
||||||
|
if (req.profiler) {
|
||||||
|
req.profiler.start('windshaft-cartodb.instance_template_post');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instantiateTemplate(req, res, function prepareTemplateParams(callback) {
|
||||||
|
if (!req.is('application/json')) {
|
||||||
|
return callback(new Error('Template POST data must be of type application/json'));
|
||||||
|
}
|
||||||
|
return callback(null, req.body);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MapController.prototype.jsonp = function(req, res) {
|
||||||
|
if (req.profiler) {
|
||||||
|
req.profiler.start('windshaft-cartodb.instance_template_get');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instantiateTemplate(req, res, function prepareJsonTemplateParams(callback) {
|
||||||
|
var err = null;
|
||||||
|
if ( req.query.callback === undefined || req.query.callback.length === 0) {
|
||||||
|
err = new Error('callback parameter should be present and be a function name');
|
||||||
|
}
|
||||||
|
|
||||||
|
var templateParams = {};
|
||||||
|
if (req.query.config) {
|
||||||
|
try {
|
||||||
|
templateParams = JSON.parse(req.query.config);
|
||||||
|
} catch(e) {
|
||||||
|
err = new Error('Invalid config parameter, should be a valid JSON');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
return callback(err, templateParams);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
MapController.prototype.create = function(req, res, prepareConfigFn) {
|
MapController.prototype.create = function(req, res, prepareConfigFn) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
var mapConfig;
|
||||||
|
|
||||||
step(
|
step(
|
||||||
function setupParams(){
|
function setupParams(){
|
||||||
self._app.req2params(req, this);
|
self.app.req2params(req, this);
|
||||||
},
|
},
|
||||||
prepareConfigFn,
|
prepareConfigFn,
|
||||||
function beforeLayergroupCreate(err, requestMapConfig) {
|
function beforeLayergroupCreate(err, requestMapConfig) {
|
||||||
@ -110,178 +135,151 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
|
|||||||
},
|
},
|
||||||
function createLayergroup(err, requestMapConfig, datasource) {
|
function createLayergroup(err, requestMapConfig, datasource) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
self.mapBackend.createLayergroup(
|
mapConfig = new MapConfig(requestMapConfig, datasource || Datasource.EmptyDatasource());
|
||||||
new MapConfig(requestMapConfig, datasource || Datasource.EmptyDatasource()), req.params, this
|
self.mapBackend.createLayergroup(mapConfig, req.params, this);
|
||||||
);
|
},
|
||||||
|
function afterLayergroupCreate(err, layergroup) {
|
||||||
|
assert.ifError(err);
|
||||||
|
self.afterLayergroupCreate(req, mapConfig, layergroup, this);
|
||||||
},
|
},
|
||||||
function finish(err, layergroup) {
|
function finish(err, layergroup) {
|
||||||
if (err) {
|
if (err) {
|
||||||
var statusCode = self._app.findStatusCode(err);
|
var statusCode = self.app.findStatusCode(err);
|
||||||
self._app.sendError(res, { errors: [ err.message ] }, statusCode, 'ANONYMOUS LAYERGROUP', err);
|
self.app.sendError(res, { errors: [ err.message ] }, statusCode, 'ANONYMOUS LAYERGROUP', err);
|
||||||
} else {
|
} else {
|
||||||
self._app.sendResponse(res, [layergroup, 200]);
|
self.app.sendResponse(res, [layergroup, 200]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
MapController.prototype.createGet = function(req, res){
|
MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn) {
|
||||||
req.profiler.start('windshaft.createmap_get');
|
|
||||||
|
|
||||||
this.create(req, res, function createGet$prepareConfig(err, req) {
|
|
||||||
assert.ifError(err);
|
|
||||||
if ( ! req.params.config ) {
|
|
||||||
throw new Error('layergroup GET needs a "config" parameter');
|
|
||||||
}
|
|
||||||
return JSON.parse(req.params.config);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO rewrite this so it is possible to share code with `MapController::create` method
|
|
||||||
MapController.prototype.createPost = function(req, res) {
|
|
||||||
req.profiler.start('windshaft.createmap_post');
|
|
||||||
|
|
||||||
this.create(req, res, function createPost$prepareConfig(err, req) {
|
|
||||||
assert.ifError(err);
|
|
||||||
if (!req.is('application/json')) {
|
|
||||||
throw new Error('layergroup POST data must be of type application/json');
|
|
||||||
}
|
|
||||||
return req.body;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets a tile for a given token and set of tile ZXY coords. (OSM style)
|
|
||||||
MapController.prototype.tile = function(req, res) {
|
|
||||||
req.profiler.start('windshaft.map_tile');
|
|
||||||
this.tileOrLayer(req, res);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets a tile for a given token, layer set of tile ZXY coords. (OSM style)
|
|
||||||
MapController.prototype.layer = function(req, res, next) {
|
|
||||||
if (req.params.token === 'static') {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
req.profiler.start('windshaft.maplayer_tile');
|
|
||||||
this.tileOrLayer(req, res);
|
|
||||||
};
|
|
||||||
|
|
||||||
MapController.prototype.tileOrLayer = function (req, res) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
var cdbuser = req.context.user;
|
||||||
|
|
||||||
|
var mapConfigProvider;
|
||||||
|
var mapConfig;
|
||||||
|
|
||||||
step(
|
step(
|
||||||
function mapController$prepareParams() {
|
function getTemplateParams() {
|
||||||
self._app.req2params(req, this);
|
prepareParamsFn(this);
|
||||||
},
|
},
|
||||||
function mapController$getTileOrGrid(err) {
|
function getTemplate(err, templateParams) {
|
||||||
req.profiler.done('req2params');
|
assert.ifError(err);
|
||||||
if ( err ) {
|
mapConfigProvider = new NamedMapMapConfigProvider(
|
||||||
throw err;
|
self.templateMaps,
|
||||||
|
self.pgConnection,
|
||||||
|
cdbuser,
|
||||||
|
req.params.template_id,
|
||||||
|
templateParams,
|
||||||
|
req.query.auth_token,
|
||||||
|
req.params
|
||||||
|
);
|
||||||
|
mapConfigProvider.getMapConfig(this);
|
||||||
|
},
|
||||||
|
function createLayergroup(err, mapConfig_, rendererParams/*, context*/) {
|
||||||
|
assert.ifError(err);
|
||||||
|
mapConfig = mapConfig_;
|
||||||
|
self.mapBackend.createLayergroup(mapConfig, rendererParams, this);
|
||||||
|
},
|
||||||
|
function afterLayergroupCreate(err, layergroup) {
|
||||||
|
assert.ifError(err);
|
||||||
|
self.afterLayergroupCreate(req, mapConfig, layergroup, this);
|
||||||
|
},
|
||||||
|
function finishTemplateInstantiation(err, layergroup) {
|
||||||
|
if (err) {
|
||||||
|
var statusCode = self.app.findStatusCode(err);
|
||||||
|
self.app.sendError(res, { errors: [ err.message ] }, statusCode, 'NAMED MAP LAYERGROUP', err);
|
||||||
|
} else {
|
||||||
|
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
||||||
|
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
||||||
|
|
||||||
|
res.header('X-Layergroup-Id', layergroup.layergroupid);
|
||||||
|
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
|
||||||
|
|
||||||
|
self.app.sendResponse(res, [layergroup, 200]);
|
||||||
}
|
}
|
||||||
self.tileBackend.getTile(new MapStoreMapConfigProvider(self.mapStore, req.params), req.params, this);
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MapController.prototype.afterLayergroupCreate = function(req, mapconfig, layergroup, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var username = req.context.user;
|
||||||
|
|
||||||
|
var tasksleft = 2; // redis key and affectedTables
|
||||||
|
var errors = [];
|
||||||
|
|
||||||
|
var done = function(err) {
|
||||||
|
if ( err ) {
|
||||||
|
errors.push('' + err);
|
||||||
|
}
|
||||||
|
if ( ! --tasksleft ) {
|
||||||
|
err = errors.length ? new Error(errors.join('\n')) : null;
|
||||||
|
callback(err, layergroup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// include in layergroup response the variables in serverMedata
|
||||||
|
// those variables are useful to send to the client information
|
||||||
|
// about how to reach this server or information about it
|
||||||
|
_.extend(layergroup, global.environment.serverMetadata);
|
||||||
|
|
||||||
|
// Don't wait for the mapview count increment to
|
||||||
|
// take place before proceeding. Error will be logged
|
||||||
|
// asynchronously
|
||||||
|
this.metadataBackend.incMapviewCount(username, mapconfig.obj().stat_tag, function(err) {
|
||||||
|
if (req.profiler) {
|
||||||
|
req.profiler.done('incMapviewCount');
|
||||||
|
}
|
||||||
|
if ( err ) {
|
||||||
|
console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
var sql = mapconfig.getLayers().map(function(layer) {
|
||||||
|
return layer.options.sql;
|
||||||
|
}).join(';');
|
||||||
|
|
||||||
|
var dbName = req.params.dbname;
|
||||||
|
var cacheKey = dbName + ':' + layergroup.layergroupid;
|
||||||
|
|
||||||
|
step(
|
||||||
|
function getAffectedTablesAndLastUpdatedTime() {
|
||||||
|
self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this);
|
||||||
},
|
},
|
||||||
function mapController$finalize(err, tile, headers, stats) {
|
function handleAffectedTablesAndLastUpdatedTime(err, result) {
|
||||||
req.profiler.add(stats);
|
if (req.profiler) {
|
||||||
self.finalizeGetTileOrGrid(err, req, res, tile, headers);
|
req.profiler.done('queryTablesAndLastUpdated');
|
||||||
|
}
|
||||||
|
assert.ifError(err);
|
||||||
|
var cacheChannel = self.app.buildCacheChannel(dbName, result.affectedTables);
|
||||||
|
self.app.channelCache[cacheKey] = cacheChannel;
|
||||||
|
|
||||||
|
// last update for layergroup cache buster
|
||||||
|
layergroup.layergroupid = layergroup.layergroupid + ':' + result.lastUpdatedTime;
|
||||||
|
layergroup.last_updated = new Date(result.lastUpdatedTime).toISOString();
|
||||||
|
|
||||||
|
var res = req.res;
|
||||||
|
if (res) {
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||||
|
res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
||||||
|
res.header('Last-Modified', (new Date()).toUTCString());
|
||||||
|
res.header('X-Cache-Channel', cacheChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.header('X-Layergroup-Id', layergroup.layergroupid);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
function finish(err) {
|
function finish(err) {
|
||||||
if ( err ) {
|
done(err);
|
||||||
console.error("windshaft.tiles: " + err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// This function is meant for being called as the very last
|
|
||||||
// step by all endpoints serving tiles or grids
|
|
||||||
MapController.prototype.finalizeGetTileOrGrid = function(err, req, res, tile, headers) {
|
|
||||||
var supportedFormats = {
|
|
||||||
grid_json: true,
|
|
||||||
json_torque: true,
|
|
||||||
torque_json: true,
|
|
||||||
png: true
|
|
||||||
};
|
|
||||||
|
|
||||||
var formatStat = 'invalid';
|
|
||||||
if (req.params.format) {
|
|
||||||
var format = req.params.format.replace('.', '_');
|
|
||||||
if (supportedFormats[format]) {
|
|
||||||
formatStat = format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err){
|
|
||||||
// See https://github.com/Vizzuality/Windshaft-cartodb/issues/68
|
|
||||||
var errMsg = err.message ? ( '' + err.message ) : ( '' + err );
|
|
||||||
var statusCode = this._app.findStatusCode(err);
|
|
||||||
|
|
||||||
// Rewrite mapnik parsing errors to start with layer number
|
|
||||||
var matches = errMsg.match("(.*) in style 'layer([0-9]+)'");
|
|
||||||
if (matches) {
|
|
||||||
errMsg = 'style'+matches[2]+': ' + matches[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._app.sendError(res, { errors: ['' + errMsg] }, statusCode, 'TILE RENDER', err);
|
|
||||||
global.statsClient.increment('windshaft.tiles.error');
|
|
||||||
global.statsClient.increment('windshaft.tiles.' + formatStat + '.error');
|
|
||||||
} else {
|
|
||||||
this._app.sendWithHeaders(res, tile, 200, headers);
|
|
||||||
global.statsClient.increment('windshaft.tiles.success');
|
|
||||||
global.statsClient.increment('windshaft.tiles.' + formatStat + '.success');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MapController.prototype.bbox = function(req, res) {
|
|
||||||
this.staticMap(req, res, +req.params.width, +req.params.height, {
|
|
||||||
west: +req.params.west,
|
|
||||||
north: +req.params.north,
|
|
||||||
east: +req.params.east,
|
|
||||||
south: +req.params.south
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
MapController.prototype.center = function(req, res) {
|
|
||||||
this.staticMap(req, res, +req.params.width, +req.params.height, +req.params.z, {
|
|
||||||
lng: +req.params.lng,
|
|
||||||
lat: +req.params.lat
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
step(
|
|
||||||
function() {
|
|
||||||
self._app.req2params(req, this);
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
req.profiler.done('req2params');
|
|
||||||
assert.ifError(err);
|
|
||||||
if (center) {
|
|
||||||
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
|
|
||||||
format, width, height, zoom, center, this);
|
|
||||||
} else {
|
|
||||||
self.previewBackend.getImage(new MapStoreMapConfigProvider(self.mapStore, req.params),
|
|
||||||
format, width, height, zoom /* bounds */, this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function handleImage(err, image, headers, stats) {
|
|
||||||
req.profiler.done('render-' + format);
|
|
||||||
req.profiler.add(stats || {});
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
if (!err.error) {
|
|
||||||
err.error = err.message;
|
|
||||||
}
|
|
||||||
self._app.sendError(res, {errors: ['' + err] }, self._app.findStatusCode(err), 'STATIC_MAP', err);
|
|
||||||
} else {
|
|
||||||
res.setHeader('Content-Type', headers['Content-Type'] || 'image/' + format);
|
|
||||||
self._app.sendResponse(res, [image, 200]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,17 +6,13 @@ var cors = require('../middleware/cors');
|
|||||||
|
|
||||||
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
|
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
|
||||||
|
|
||||||
function NamedMapsController(app, pgConnection, mapStore, templateMaps, metadataBackend, mapBackend, tileBackend,
|
function NamedMapsController(app, pgConnection, templateMaps, tileBackend, previewBackend, surrogateKeysCache,
|
||||||
previewBackend, templateBaseUrl, surrogateKeysCache, tablesExtentApi) {
|
tablesExtentApi) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.mapStore = mapStore;
|
|
||||||
this.pgConnection = pgConnection;
|
this.pgConnection = pgConnection;
|
||||||
this.templateMaps = templateMaps;
|
this.templateMaps = templateMaps;
|
||||||
this.metadataBackend = metadataBackend;
|
|
||||||
this.mapBackend = mapBackend;
|
|
||||||
this.tileBackend = tileBackend;
|
this.tileBackend = tileBackend;
|
||||||
this.previewBackend = previewBackend;
|
this.previewBackend = previewBackend;
|
||||||
this.templateBaseUrl = templateBaseUrl;
|
|
||||||
this.surrogateKeysCache = surrogateKeysCache;
|
this.surrogateKeysCache = surrogateKeysCache;
|
||||||
this.tablesExtentApi = tablesExtentApi;
|
this.tablesExtentApi = tablesExtentApi;
|
||||||
}
|
}
|
||||||
@ -24,49 +20,10 @@ function NamedMapsController(app, pgConnection, mapStore, templateMaps, metadata
|
|||||||
module.exports = NamedMapsController;
|
module.exports = NamedMapsController;
|
||||||
|
|
||||||
NamedMapsController.prototype.register = function(app) {
|
NamedMapsController.prototype.register = function(app) {
|
||||||
app.get(this.templateBaseUrl + '/:template_id/:layer/:z/:x/:y.(:format)', cors(), this.tile.bind(this));
|
app.get(app.base_url_templated + '/: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.get(
|
||||||
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format', cors(), this.staticMap.bind(this)
|
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format', cors(), this.staticMap.bind(this)
|
||||||
);
|
);
|
||||||
app.post(this.templateBaseUrl + '/:template_id', cors(), this.instantiate.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
NamedMapsController.prototype.instantiate = function(req, res) {
|
|
||||||
if (req.profiler) {
|
|
||||||
req.profiler.start('windshaft-cartodb.instance_template_post');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.instantiateTemplate(req, res, function prepareTemplateParams(callback) {
|
|
||||||
if (!req.is('application/json')) {
|
|
||||||
return callback(new Error('Template POST data must be of type application/json'));
|
|
||||||
}
|
|
||||||
return callback(null, req.body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
NamedMapsController.prototype.jsonp = function(req, res) {
|
|
||||||
if (req.profiler) {
|
|
||||||
req.profiler.start('windshaft-cartodb.instance_template_get');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.instantiateTemplate(req, res, function prepareJsonTemplateParams(callback) {
|
|
||||||
var err = null;
|
|
||||||
if ( req.query.callback === undefined || req.query.callback.length === 0) {
|
|
||||||
err = new Error('callback parameter should be present and be a function name');
|
|
||||||
}
|
|
||||||
|
|
||||||
var templateParams = {};
|
|
||||||
if (req.query.config) {
|
|
||||||
try {
|
|
||||||
templateParams = JSON.parse(req.query.config);
|
|
||||||
} catch(e) {
|
|
||||||
err = new Error('Invalid config parameter, should be a valid JSON');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(err, templateParams);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NamedMapsController.prototype.tile = function(req, res) {
|
NamedMapsController.prototype.tile = function(req, res) {
|
||||||
@ -207,53 +164,6 @@ NamedMapsController.prototype.staticMap = function(req, res) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Instantiate a template
|
|
||||||
NamedMapsController.prototype.instantiateTemplate = function(req, res, prepareParamsFn) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var cdbuser = req.context.user;
|
|
||||||
|
|
||||||
var mapConfigProvider;
|
|
||||||
|
|
||||||
step(
|
|
||||||
function getTemplateParams() {
|
|
||||||
prepareParamsFn(this);
|
|
||||||
},
|
|
||||||
function getTemplate(err, templateParams) {
|
|
||||||
assert.ifError(err);
|
|
||||||
mapConfigProvider = new NamedMapMapConfigProvider(
|
|
||||||
this.templateMaps,
|
|
||||||
this.pgConnection,
|
|
||||||
cdbuser,
|
|
||||||
req.params.template_id,
|
|
||||||
templateParams,
|
|
||||||
req.query.auth_token,
|
|
||||||
req.params
|
|
||||||
);
|
|
||||||
mapConfigProvider.getMapConfig(this);
|
|
||||||
},
|
|
||||||
function createLayergroup(err, mapConfig, rendererParams/*, context*/) {
|
|
||||||
assert.ifError(err);
|
|
||||||
self.mapBackend.createLayergroup(mapConfig, rendererParams, this);
|
|
||||||
},
|
|
||||||
function finishTemplateInstantiation(err, layergroup) {
|
|
||||||
if (err) {
|
|
||||||
var statusCode = this._app.findStatusCode(err);
|
|
||||||
this.app.sendError(res, { errors: [ err.message ] }, statusCode, 'NAMED MAP LAYERGROUP', err);
|
|
||||||
} else {
|
|
||||||
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
|
||||||
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
|
||||||
|
|
||||||
res.header('X-Layergroup-Id', layergroup.layergroupid);
|
|
||||||
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
|
|
||||||
|
|
||||||
this.app.sendResponse(res, [layergroup, 200]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
function getStaticImageOptions(template, callback) {
|
function getStaticImageOptions(template, callback) {
|
||||||
if (template.view) {
|
if (template.view) {
|
||||||
var zoomCenter = templateZoomCenter(template.view);
|
var zoomCenter = templateZoomCenter(template.view);
|
||||||
|
@ -5,21 +5,20 @@ var templateName = require('../backends/template_maps').templateName;
|
|||||||
var cors = require('../middleware/cors');
|
var cors = require('../middleware/cors');
|
||||||
|
|
||||||
|
|
||||||
function NamedMapsAdminController(app, templateMaps, templateBaseUrl) {
|
function NamedMapsAdminController(app, templateMaps) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.templateMaps = templateMaps;
|
this.templateMaps = templateMaps;
|
||||||
this.templateBaseUrl = templateBaseUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = NamedMapsAdminController;
|
module.exports = NamedMapsAdminController;
|
||||||
|
|
||||||
NamedMapsAdminController.prototype.register = function(app) {
|
NamedMapsAdminController.prototype.register = function(app) {
|
||||||
app.post(this.templateBaseUrl, cors(), this.create.bind(this));
|
app.post(app.base_url_templated, cors(), this.create.bind(this));
|
||||||
app.put(this.templateBaseUrl + '/:template_id', cors(), this.update.bind(this));
|
app.put(app.base_url_templated + '/:template_id', cors(), this.update.bind(this));
|
||||||
app.get(this.templateBaseUrl + '/:template_id', cors(), this.retrieve.bind(this));
|
app.get(app.base_url_templated + '/:template_id', cors(), this.retrieve.bind(this));
|
||||||
app.del(this.templateBaseUrl + '/:template_id', cors(), this.destroy.bind(this));
|
app.del(app.base_url_templated + '/:template_id', cors(), this.destroy.bind(this));
|
||||||
app.get(this.templateBaseUrl, cors(), this.list.bind(this));
|
app.get(app.base_url_templated, cors(), this.list.bind(this));
|
||||||
app.options(this.templateBaseUrl + '/:template_id', cors('Content-Type'));
|
app.options(app.base_url_templated + '/:template_id', cors('Content-Type'));
|
||||||
};
|
};
|
||||||
|
|
||||||
NamedMapsAdminController.prototype.create = function(req, res) {
|
NamedMapsAdminController.prototype.create = function(req, res) {
|
||||||
|
@ -195,90 +195,6 @@ module.exports = function(serverOptions) {
|
|||||||
return statusCode;
|
return statusCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
// var layergroupRequestDecorator = {
|
|
||||||
// afterLayergroupCreate: function(req, mapconfig, layergroup, callback) {
|
|
||||||
// var token = layergroup.layergroupid;
|
|
||||||
//
|
|
||||||
// var username = req.context.user;
|
|
||||||
//
|
|
||||||
// var tasksleft = 2; // redis key and affectedTables
|
|
||||||
// var errors = [];
|
|
||||||
//
|
|
||||||
// var done = function(err) {
|
|
||||||
// if ( err ) {
|
|
||||||
// errors.push('' + err);
|
|
||||||
// }
|
|
||||||
// if ( ! --tasksleft ) {
|
|
||||||
// err = errors.length ? new Error(errors.join('\n')) : null;
|
|
||||||
// callback(err);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // include in layergroup response the variables in serverMedata
|
|
||||||
// // those variables are useful to send to the client information
|
|
||||||
// // about how to reach this server or information about it
|
|
||||||
// var serverMetadata = global.environment.serverMetadata;
|
|
||||||
// if (serverMetadata) {
|
|
||||||
// _.extend(layergroup, serverMetadata);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Don't wait for the mapview count increment to
|
|
||||||
// // take place before proceeding. Error will be logged
|
|
||||||
// // asyncronously
|
|
||||||
// metadataBackend.incMapviewCount(username, mapconfig.stat_tag, function(err) {
|
|
||||||
// if (req.profiler) {
|
|
||||||
// req.profiler.done('incMapviewCount');
|
|
||||||
// }
|
|
||||||
// if ( err ) {
|
|
||||||
// console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
|
||||||
// }
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// var sql = mapconfig.layers.map(function(layer) {
|
|
||||||
// return layer.options.sql;
|
|
||||||
// }).join(';');
|
|
||||||
//
|
|
||||||
// var dbName = req.params.dbname;
|
|
||||||
// var cacheKey = dbName + ':' + token;
|
|
||||||
//
|
|
||||||
// step(
|
|
||||||
// function getAffectedTablesAndLastUpdatedTime() {
|
|
||||||
// queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this);
|
|
||||||
// },
|
|
||||||
// function handleAffectedTablesAndLastUpdatedTime(err, result) {
|
|
||||||
// if (req.profiler) {
|
|
||||||
// req.profiler.done('queryTablesAndLastUpdated');
|
|
||||||
// }
|
|
||||||
// assert.ifError(err);
|
|
||||||
// var cacheChannel = app.buildCacheChannel(dbName, result.affectedTables);
|
|
||||||
// app.channelCache[cacheKey] = cacheChannel;
|
|
||||||
//
|
|
||||||
// // last update for layergroup cache buster
|
|
||||||
// layergroup.layergroupid = layergroup.layergroupid + ':' + result.lastUpdatedTime;
|
|
||||||
// layergroup.last_updated = new Date(result.lastUpdatedTime).toISOString();
|
|
||||||
//
|
|
||||||
// var res = req.res;
|
|
||||||
// if (res) {
|
|
||||||
// if (req.method === 'GET') {
|
|
||||||
// var ttl = global.environment.varnish.layergroupTtl || 86400;
|
|
||||||
// res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
|
||||||
// res.header('Last-Modified', (new Date()).toUTCString());
|
|
||||||
// res.header('X-Cache-Channel', cacheChannel);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// res.header('X-Layergroup-Id', layergroup.layergroupid);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return null;
|
|
||||||
// },
|
|
||||||
// function finish(err) {
|
|
||||||
// done(err);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
var TablesExtentApi = require('./api/tables_extent_api');
|
var TablesExtentApi = require('./api/tables_extent_api');
|
||||||
var tablesExtentApi = new TablesExtentApi(pgQueryRunner);
|
var tablesExtentApi = new TablesExtentApi(pgQueryRunner);
|
||||||
|
|
||||||
@ -291,32 +207,35 @@ module.exports = function(serverOptions) {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
new controller.Map(
|
new controller.Layergroup(
|
||||||
app,
|
app,
|
||||||
pgConnection,
|
|
||||||
mapStore,
|
mapStore,
|
||||||
templateMaps,
|
|
||||||
mapBackend,
|
|
||||||
tileBackend,
|
tileBackend,
|
||||||
previewBackend,
|
previewBackend,
|
||||||
attributesBackend
|
attributesBackend
|
||||||
).register(app);
|
).register(app);
|
||||||
|
|
||||||
|
new controller.Map(
|
||||||
|
app,
|
||||||
|
pgConnection,
|
||||||
|
templateMaps,
|
||||||
|
mapBackend,
|
||||||
|
metadataBackend,
|
||||||
|
queryTablesApi,
|
||||||
|
surrogateKeysCache
|
||||||
|
).register(app);
|
||||||
|
|
||||||
new controller.NamedMaps(
|
new controller.NamedMaps(
|
||||||
app,
|
app,
|
||||||
pgConnection,
|
pgConnection,
|
||||||
mapStore,
|
|
||||||
templateMaps,
|
templateMaps,
|
||||||
metadataBackend,
|
|
||||||
mapBackend,
|
|
||||||
tileBackend,
|
tileBackend,
|
||||||
previewBackend,
|
previewBackend,
|
||||||
template_baseurl,
|
|
||||||
surrogateKeysCache,
|
surrogateKeysCache,
|
||||||
tablesExtentApi
|
tablesExtentApi
|
||||||
).register(app);
|
).register(app);
|
||||||
|
|
||||||
new controller.NamedMapsAdmin(app, templateMaps, template_baseurl).register(app);
|
new controller.NamedMapsAdmin(app, templateMaps).register(app);
|
||||||
|
|
||||||
new controller.ServerInfo().register(app);
|
new controller.ServerInfo().register(app);
|
||||||
|
|
||||||
@ -857,8 +776,8 @@ module.exports = function(serverOptions) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function validateOptions(opts) {
|
function validateOptions(opts) {
|
||||||
if (!_.isString(opts.base_url) || !_.isString(opts.base_url_mapconfig)) {
|
if (!_.isString(opts.base_url) || !_.isString(opts.base_url_mapconfig) || !_.isString(opts.base_url_templated)) {
|
||||||
throw new Error("Must initialise Windshaft with: 'base_url'/'base_url_mapconfig' URLs");
|
throw new Error("Must initialise server with: 'base_url'/'base_url_mapconfig'/'base_url_templated' URLs");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Be nice and warn if configured mapnik version is != instaled mapnik version
|
// Be nice and warn if configured mapnik version is != instaled mapnik version
|
||||||
|
@ -42,6 +42,8 @@ module.exports = {
|
|||||||
//
|
//
|
||||||
base_url_mapconfig: global.environment.base_url_detached || '(?:/maps|/tiles/layergroup)',
|
base_url_mapconfig: global.environment.base_url_detached || '(?:/maps|/tiles/layergroup)',
|
||||||
|
|
||||||
|
base_url_templated: global.environment.base_url_templated || '(?:/maps/named|/tiles/template)',
|
||||||
|
|
||||||
grainstore: {
|
grainstore: {
|
||||||
map: {
|
map: {
|
||||||
// TODO: allow to specify in configuration
|
// TODO: allow to specify in configuration
|
||||||
|
@ -5,7 +5,7 @@ var cartodbServer = require('../../../../lib/cartodb/server');
|
|||||||
var serverOptions = require('../../../../lib/cartodb/server_options');
|
var serverOptions = require('../../../../lib/cartodb/server_options');
|
||||||
var StatsClient = require('windshaft').stats.Client;
|
var StatsClient = require('windshaft').stats.Client;
|
||||||
|
|
||||||
var MapController = require('../../../../lib/cartodb/controllers/map');
|
var LayergroupController = require('../../../../lib/cartodb/controllers/layergroup');
|
||||||
|
|
||||||
describe('tile stats', function() {
|
describe('tile stats', function() {
|
||||||
|
|
||||||
@ -31,14 +31,14 @@ describe('tile stats', function() {
|
|||||||
var ws = cartodbServer(serverOptions);
|
var ws = cartodbServer(serverOptions);
|
||||||
ws.sendError = function(){};
|
ws.sendError = function(){};
|
||||||
|
|
||||||
var mapController = new MapController(ws, null);
|
var layergroupController = new LayergroupController(ws, null);
|
||||||
|
|
||||||
var reqMock = {
|
var reqMock = {
|
||||||
params: {
|
params: {
|
||||||
format: invalidFormat
|
format: invalidFormat
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mapController.finalizeGetTileOrGrid('Unsupported format png2', reqMock, {}, null, null);
|
layergroupController.finalizeGetTileOrGrid('Unsupported format png2', reqMock, {}, null, null);
|
||||||
|
|
||||||
assert.ok(formatMatched, 'Format was never matched in increment method');
|
assert.ok(formatMatched, 'Format was never matched in increment method');
|
||||||
assert.equal(expectedCalls, 0, 'Unexpected number of calls to increment method');
|
assert.equal(expectedCalls, 0, 'Unexpected number of calls to increment method');
|
||||||
@ -64,9 +64,9 @@ describe('tile stats', function() {
|
|||||||
var ws = cartodbServer(serverOptions);
|
var ws = cartodbServer(serverOptions);
|
||||||
ws.sendError = function(){};
|
ws.sendError = function(){};
|
||||||
|
|
||||||
var mapController = new MapController(ws, null);
|
var layergroupController = new LayergroupController(ws, null);
|
||||||
|
|
||||||
mapController.finalizeGetTileOrGrid('Another error happened', reqMock, {}, null, null);
|
layergroupController.finalizeGetTileOrGrid('Another error happened', reqMock, {}, null, null);
|
||||||
|
|
||||||
assert.ok(formatMatched, 'Format was never matched in increment method');
|
assert.ok(formatMatched, 'Format was never matched in increment method');
|
||||||
assert.equal(expectedCalls, 0, 'Unexpected number of calls to increment method');
|
assert.equal(expectedCalls, 0, 'Unexpected number of calls to increment method');
|
||||||
|
Loading…
Reference in New Issue
Block a user