Merge branch 'master' of github.com:Vizzuality/Windshaft-cartodb
This commit is contained in:
commit
e4e08db0b4
22
NEWS.md
22
NEWS.md
@ -1,4 +1,24 @@
|
|||||||
1.6.0 -- 20YY-MM-DD
|
1.6.2 -- 2014-MM-DD
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* Fix support for long (>64k chars) queries in layergroup creation (#111)
|
||||||
|
|
||||||
|
Enhancements:
|
||||||
|
|
||||||
|
* Enhance tools/show_style to accept an environment parameter and
|
||||||
|
print XML style now it is not in redis anymore (#110)
|
||||||
|
|
||||||
|
1.6.1 -- 2014-01-15
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* Drop cache headers from error responses (#107)
|
||||||
|
* Localize external CartoCSS resources at renderer creation time (#108)
|
||||||
|
|
||||||
|
1.6.0 -- 2014-01-10
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
New features:
|
New features:
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
Windshaft-CartoDB
|
Windshaft-CartoDB
|
||||||
==================
|
==================
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/CartoDB/Windshaft-cartodb.png)](http://travis-ci.org/CartoDB/Windshaft-cartodb)
|
[![Build Status](http://travis-ci.org/CartoDB/Windshaft-cartodb.png)]
|
||||||
|
(http://travis-ci.org/CartoDB/Windshaft-cartodb)
|
||||||
|
|
||||||
This is the CartoDB map tiler. It extends Windshaft with some extra
|
This is the CartoDB map tiler. It extends Windshaft with some extra
|
||||||
functionality and custom filters for authentication
|
functionality and custom filters for authentication
|
||||||
|
@ -42,6 +42,22 @@ var CartodbWindshaft = function(serverOptions) {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override sendError to drop added cache headers (if any)
|
||||||
|
// See http://github.com/CartoDB/Windshaft-cartodb/issues/107
|
||||||
|
var ws_sendError = ws.sendError;
|
||||||
|
ws.sendError = function(res) {
|
||||||
|
// NOTE: the "res" object will have no _headers when
|
||||||
|
// faked by Windshaft, see
|
||||||
|
// http://github.com/CartoDB/Windshaft-cartodb/issues/109
|
||||||
|
//
|
||||||
|
if ( res._headers ) {
|
||||||
|
delete res._headers['cache-control'];
|
||||||
|
delete res._headers['last-modified'];
|
||||||
|
delete res._headers['x-cache-channel'];
|
||||||
|
}
|
||||||
|
ws_sendError.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to allow access to the layer to be used in the maps infowindow popup.
|
* Helper to allow access to the layer to be used in the maps infowindow popup.
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +78,15 @@ module.exports = function(){
|
|||||||
if (_.isString(api_key) && api_key != '') { qs.api_key = api_key; }
|
if (_.isString(api_key) && api_key != '') { qs.api_key = api_key; }
|
||||||
|
|
||||||
// call sql api
|
// call sql api
|
||||||
request.get({url:sqlapi, qs:qs, json:true}, function(err, res, body){
|
//
|
||||||
|
// NOTE: using POST to avoid size limits:
|
||||||
|
// Seehttp://github.com/CartoDB/Windshaft-cartodb/issues/111
|
||||||
|
//
|
||||||
|
// TODO: use "host" header to allow IP based specification
|
||||||
|
// of sqlapi address (and avoid a DNS lookup)
|
||||||
|
//
|
||||||
|
request.post({url:sqlapi, body:qs, json:true},
|
||||||
|
function(err, res, body){
|
||||||
if (err){
|
if (err){
|
||||||
console.log('ERROR connecting to SQL API on ' + sqlapi + ': ' + err);
|
console.log('ERROR connecting to SQL API on ' + sqlapi + ': ' + err);
|
||||||
callback(err);
|
callback(err);
|
||||||
@ -188,7 +196,7 @@ module.exports = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dbName = req.params.dbname;
|
var dbName = req.params.dbname;
|
||||||
var username = req.headers.host.split('.')[0];
|
var username = this.userByReq(req);
|
||||||
|
|
||||||
// strip out windshaft/mapnik inserted sql if present
|
// strip out windshaft/mapnik inserted sql if present
|
||||||
var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/);
|
var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/);
|
||||||
@ -281,7 +289,7 @@ module.exports = function(){
|
|||||||
sql = sql.join(';');
|
sql = sql.join(';');
|
||||||
|
|
||||||
var dbName = req.params.dbname;
|
var dbName = req.params.dbname;
|
||||||
var usr = req.headers.host.split('.')[0];
|
var usr = this.userByReq(req);
|
||||||
var key = req.params.map_key;
|
var key = req.params.map_key;
|
||||||
|
|
||||||
var cacheKey = dbName + ':' + token;
|
var cacheKey = dbName + ':' + token;
|
||||||
@ -577,7 +585,7 @@ console.log("Checking authorization from signer " + signer + " for resource " +
|
|||||||
if ( tksplit.length > 1 ) req.params.cache_buster= tksplit[1];
|
if ( tksplit.length > 1 ) req.params.cache_buster= tksplit[1];
|
||||||
tksplit = req.params.token.split('@');
|
tksplit = req.params.token.split('@');
|
||||||
if ( tksplit.length > 1 ) {
|
if ( tksplit.length > 1 ) {
|
||||||
req.params.signer = req.headers.host.split('.')[0];
|
req.params.signer = this.userByReq(req);
|
||||||
if ( tksplit[0] ) req.params.signer = tksplit[0];
|
if ( tksplit[0] ) req.params.signer = tksplit[0];
|
||||||
req.params.token = tksplit[1];
|
req.params.token = tksplit[1];
|
||||||
//console.log("Request for token " + req.params.token + " with signature from " + req.params.signer);
|
//console.log("Request for token " + req.params.token + " with signature from " + req.params.signer);
|
||||||
|
174
npm-shrinkwrap.json
generated
174
npm-shrinkwrap.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "windshaft-cartodb",
|
"name": "windshaft-cartodb",
|
||||||
"version": "1.6.0",
|
"version": "1.6.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-varnish": {
|
"node-varnish": {
|
||||||
"version": "0.1.1"
|
"version": "0.1.1"
|
||||||
@ -9,14 +9,14 @@
|
|||||||
"version": "1.3.3"
|
"version": "1.3.3"
|
||||||
},
|
},
|
||||||
"windshaft": {
|
"windshaft": {
|
||||||
"version": "0.14.5",
|
"version": "0.15.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"grainstore": {
|
"grainstore": {
|
||||||
"version": "0.15.2",
|
"version": "0.16.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"carto": {
|
"carto": {
|
||||||
"version": "0.9.5-cdb2",
|
"version": "0.9.5-cdb2",
|
||||||
"from": "git://github.com/CartoDB/carto.git#0.9.5-cdb2",
|
"from": "http://github.com/CartoDB/carto/tarball/0.9.5-cdb2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"underscore": {
|
"underscore": {
|
||||||
"version": "1.4.4"
|
"version": "1.4.4"
|
||||||
@ -25,7 +25,7 @@
|
|||||||
"version": "0.2.8",
|
"version": "0.2.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sax": {
|
"sax": {
|
||||||
"version": "0.5.5"
|
"version": "0.5.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -131,46 +131,136 @@
|
|||||||
"version": "0.3.8"
|
"version": "0.3.8"
|
||||||
},
|
},
|
||||||
"zipfile": {
|
"zipfile": {
|
||||||
"version": "0.4.2"
|
"version": "0.4.3"
|
||||||
},
|
},
|
||||||
"sqlite3": {
|
"sqlite3": {
|
||||||
"version": "2.1.19",
|
"version": "2.2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tar.gz": {
|
"node-pre-gyp": {
|
||||||
"version": "0.1.1",
|
"version": "0.2.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fstream": {
|
"nopt": {
|
||||||
"version": "0.1.25",
|
"version": "2.1.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rimraf": {
|
"abbrev": {
|
||||||
"version": "2.2.4"
|
"version": "1.0.4"
|
||||||
},
|
|
||||||
"graceful-fs": {
|
|
||||||
"version": "2.0.1"
|
|
||||||
},
|
|
||||||
"inherits": {
|
|
||||||
"version": "2.0.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"npmlog": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi": {
|
||||||
|
"version": "0.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "2.1.0"
|
||||||
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "0.1.18",
|
"version": "0.1.19",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.1"
|
"version": "2.0.1"
|
||||||
},
|
},
|
||||||
"block-stream": {
|
"block-stream": {
|
||||||
"version": "0.0.7"
|
"version": "0.0.7"
|
||||||
|
},
|
||||||
|
"fstream": {
|
||||||
|
"version": "0.1.25",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"commander": {
|
"tar-pack": {
|
||||||
"version": "1.1.1",
|
"version": "2.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"keypress": {
|
"uid-number": {
|
||||||
"version": "0.1.0"
|
"version": "0.0.3"
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "0.7.4"
|
||||||
|
},
|
||||||
|
"fstream": {
|
||||||
|
"version": "0.1.25",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "2.0.1"
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fstream-ignore": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"dependencies": {
|
||||||
|
"minimatch": {
|
||||||
|
"version": "0.2.14",
|
||||||
|
"dependencies": {
|
||||||
|
"sigmund": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "1.0.24"
|
||||||
|
},
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "1.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"aws-sdk": {
|
||||||
|
"version": "2.0.0-rc8",
|
||||||
|
"dependencies": {
|
||||||
|
"xml2js": {
|
||||||
|
"version": "0.2.4",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": {
|
||||||
|
"version": "0.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "0.4.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"dependencies": {
|
||||||
|
"optimist": {
|
||||||
|
"version": "0.3.7",
|
||||||
|
"dependencies": {
|
||||||
|
"wordwrap": {
|
||||||
|
"version": "0.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deep-extend": {
|
||||||
|
"version": "0.2.6"
|
||||||
|
},
|
||||||
|
"ini": {
|
||||||
|
"version": "1.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "2.2.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +329,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tilelive-mapnik": {
|
"tilelive-mapnik": {
|
||||||
"version": "0.6.4",
|
"version": "0.6.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eio": {
|
"eio": {
|
||||||
"version": "0.2.2"
|
"version": "0.2.2"
|
||||||
@ -267,10 +357,18 @@
|
|||||||
"version": "0.3.0"
|
"version": "0.3.0"
|
||||||
},
|
},
|
||||||
"redis-mpool": {
|
"redis-mpool": {
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"generic-pool": {
|
"generic-pool": {
|
||||||
"version": "2.0.4"
|
"version": "2.0.4"
|
||||||
|
},
|
||||||
|
"hiredis": {
|
||||||
|
"version": "0.1.16",
|
||||||
|
"dependencies": {
|
||||||
|
"bindings": {
|
||||||
|
"version": "1.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -280,31 +378,15 @@
|
|||||||
"lzma": {
|
"lzma": {
|
||||||
"version": "1.2.3"
|
"version": "1.2.3"
|
||||||
},
|
},
|
||||||
"strftime": {
|
|
||||||
"version": "0.6.2"
|
|
||||||
},
|
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "1.1.4"
|
"version": "1.1.4"
|
||||||
},
|
},
|
||||||
|
"strftime": {
|
||||||
|
"version": "0.6.2"
|
||||||
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"version": "0.8.6"
|
"version": "0.8.6"
|
||||||
},
|
},
|
||||||
"redis-mpool": {
|
|
||||||
"version": "0.0.2",
|
|
||||||
"dependencies": {
|
|
||||||
"generic-pool": {
|
|
||||||
"version": "2.0.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hiredis": {
|
|
||||||
"version": "0.1.15",
|
|
||||||
"dependencies": {
|
|
||||||
"bindings": {
|
|
||||||
"version": "1.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"version": "1.14.0",
|
"version": "1.14.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -338,7 +420,7 @@
|
|||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "0.2.12",
|
"version": "0.2.14",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "2.5.0"
|
"version": "2.5.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "windshaft-cartodb",
|
"name": "windshaft-cartodb",
|
||||||
"version": "1.6.0",
|
"version": "1.6.2",
|
||||||
"description": "A map tile server for CartoDB",
|
"description": "A map tile server for CartoDB",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cartodb"
|
"cartodb"
|
||||||
@ -24,7 +24,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-varnish": "0.1.1",
|
"node-varnish": "0.1.1",
|
||||||
"underscore" : "~1.3.3",
|
"underscore" : "~1.3.3",
|
||||||
"windshaft" : "~0.14.5",
|
"windshaft" : "~0.15.0",
|
||||||
"step": "0.0.x",
|
"step": "0.0.x",
|
||||||
"request": "2.9.202",
|
"request": "2.9.202",
|
||||||
"cartodb-redis": "~0.3.0",
|
"cartodb-redis": "~0.3.0",
|
||||||
|
@ -19,6 +19,14 @@ var serverOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
|||||||
var server = new CartodbWindshaft(serverOptions);
|
var server = new CartodbWindshaft(serverOptions);
|
||||||
server.setMaxListeners(0);
|
server.setMaxListeners(0);
|
||||||
|
|
||||||
|
// Check that the response headers do not request caching
|
||||||
|
// Throws on failure
|
||||||
|
function checkNoCache(res) {
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('x-cache-channel'));
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control')); // is this correct ?
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('last-modified')); // is this correct ?
|
||||||
|
}
|
||||||
|
|
||||||
suite('multilayer', function() {
|
suite('multilayer', function() {
|
||||||
|
|
||||||
var redis_client = redis.createClient(global.environment.redis.port);
|
var redis_client = redis.createClient(global.environment.redis.port);
|
||||||
@ -460,6 +468,35 @@ suite('multilayer', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Also tests that server doesn't crash:
|
||||||
|
// see http://github.com/CartoDB/Windshaft-cartodb/issues/109
|
||||||
|
test("layergroup creation fails if sql is bogus", function(done) {
|
||||||
|
var layergroup = {
|
||||||
|
stat_tag: 'random_tag',
|
||||||
|
version: '1.0.0',
|
||||||
|
layers: [
|
||||||
|
{ options: {
|
||||||
|
sql: 'select bogus(0,0) as the_geom_webmercator',
|
||||||
|
cartocss: '#layer { polygon-fill:red; }',
|
||||||
|
cartocss_version: '2.0.1'
|
||||||
|
} }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
assert.response(server, {
|
||||||
|
url: '/tiles/layergroup',
|
||||||
|
method: 'POST',
|
||||||
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||||
|
data: JSON.stringify(layergroup)
|
||||||
|
}, {}, function(res) {
|
||||||
|
assert.equal(res.statusCode, 400, res.body);
|
||||||
|
var parsed = JSON.parse(res.body);
|
||||||
|
var msg = parsed.errors[0];
|
||||||
|
assert.ok(msg.match(/bogus.*exist/), msg);
|
||||||
|
checkNoCache(res);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("layergroup with 2 private-table layers", function(done) {
|
test("layergroup with 2 private-table layers", function(done) {
|
||||||
|
|
||||||
var layergroup = {
|
var layergroup = {
|
||||||
@ -863,6 +900,71 @@ suite('multilayer', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// SQL strings can be of arbitrary length, when using POST
|
||||||
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/111
|
||||||
|
test("sql string can be very long", function(done){
|
||||||
|
var long_val = 'pretty';
|
||||||
|
for (var i=0; i<1024; ++i) long_val += ' long'
|
||||||
|
long_val += ' string';
|
||||||
|
var sql = "SELECT ";
|
||||||
|
for (var i=0; i<16; ++i)
|
||||||
|
sql += "'" + long_val + "'::text as pretty_long_field_name_" + i + ", ";
|
||||||
|
sql += "cartodb_id, the_geom_webmercator FROM gadm4 g";
|
||||||
|
var layergroup = {
|
||||||
|
version: '1.0.0',
|
||||||
|
layers: [
|
||||||
|
{ options: {
|
||||||
|
sql: sql,
|
||||||
|
cartocss: '#layer { marker-fill:red; }',
|
||||||
|
cartocss_version: '2.0.1'
|
||||||
|
} }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var errors = [];
|
||||||
|
var expected_token;
|
||||||
|
Step(
|
||||||
|
function do_post()
|
||||||
|
{
|
||||||
|
var data = JSON.stringify(layergroup);
|
||||||
|
assert.ok(data.length > 1024*64);
|
||||||
|
var next = this;
|
||||||
|
assert.response(server, {
|
||||||
|
url: '/tiles/layergroup?api_key=1234',
|
||||||
|
method: 'POST',
|
||||||
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||||
|
data: data
|
||||||
|
}, {}, function(res) { next(null, res); });
|
||||||
|
},
|
||||||
|
function check_result(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
|
var parsedBody = JSON.parse(res.body);
|
||||||
|
var token_components = parsedBody.layergroupid.split(':');
|
||||||
|
expected_token = token_components[0];
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
function cleanup(err) {
|
||||||
|
if ( err ) errors.push(err.message);
|
||||||
|
if ( ! expected_token ) return null;
|
||||||
|
var next = this;
|
||||||
|
redis_client.keys("map_style|test_cartodb_user_1_db|~" + expected_token, function(err, matches) {
|
||||||
|
if ( err ) errors.push(err.message);
|
||||||
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
||||||
|
redis_client.del(matches, function(err) {
|
||||||
|
if ( err ) errors.push(err.message);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function finish(err) {
|
||||||
|
if ( err ) errors.push('' + err);
|
||||||
|
if ( errors.length ) done(new Error(errors.join(',')));
|
||||||
|
else done(null);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
suiteTeardown(function(done) {
|
suiteTeardown(function(done) {
|
||||||
|
|
||||||
// This test will add map_style records, like
|
// This test will add map_style records, like
|
||||||
|
@ -107,7 +107,7 @@ suite('server', function() {
|
|||||||
}, function(res) {
|
}, function(res) {
|
||||||
var parsed = JSON.parse(res.body);
|
var parsed = JSON.parse(res.body);
|
||||||
assert.equal(parsed.style, _.template(default_style, {table: 'my_table'}));
|
assert.equal(parsed.style, _.template(default_style, {table: 'my_table'}));
|
||||||
assert.equal(parsed.style_version, mapnik.versions.mapnik);
|
assert.equal(parsed.style_version, mapnik_version);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -125,6 +125,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 400, res.body);
|
assert.equal(res.statusCode, 400, res.body);
|
||||||
assert.deepEqual(JSON.parse(res.body),
|
assert.deepEqual(JSON.parse(res.body),
|
||||||
{error: 'Sorry, you are unauthorized (permission denied)'});
|
{error: 'Sorry, you are unauthorized (permission denied)'});
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -142,6 +143,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
||||||
assert.deepEqual(JSON.parse(res.body),
|
assert.deepEqual(JSON.parse(res.body),
|
||||||
{error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"});
|
{error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"});
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -158,7 +160,7 @@ suite('server', function() {
|
|||||||
var parsed = JSON.parse(res.body);
|
var parsed = JSON.parse(res.body);
|
||||||
var style = _.template(default_style, {table: 'test_table_private_1'});
|
var style = _.template(default_style, {table: 'test_table_private_1'});
|
||||||
assert.equal(parsed.style, style);
|
assert.equal(parsed.style, style);
|
||||||
assert.equal(parsed.style_version, mapnik.versions.mapnik);
|
assert.equal(parsed.style_version, mapnik_version);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -212,9 +214,12 @@ suite('server', function() {
|
|||||||
url: '/tiles/my_table/style',
|
url: '/tiles/my_table/style',
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},{
|
},{
|
||||||
status: 400,
|
|
||||||
body: '{"error":"must send style information"}'
|
body: '{"error":"must send style information"}'
|
||||||
}, function() { done(); });
|
}, function(res) {
|
||||||
|
assert.equal(res.statusCode, 400);
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("post'ing bad style returns 400 with error", function(done){
|
test("post'ing bad style returns 400 with error", function(done){
|
||||||
@ -351,7 +356,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.body);
|
assert.equal(res.statusCode, 200, res.body);
|
||||||
var parsed = JSON.parse(res.body);
|
var parsed = JSON.parse(res.body);
|
||||||
assert.equal(parsed.style, style);
|
assert.equal(parsed.style, style);
|
||||||
assert.equal(parsed.style_version, mapnik.versions.mapnik);
|
assert.equal(parsed.style_version, mapnik_version);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -379,7 +384,7 @@ suite('server', function() {
|
|||||||
var parsed = JSON.parse(res.body);
|
var parsed = JSON.parse(res.body);
|
||||||
// NOTE: no transform expected for the specific style
|
// NOTE: no transform expected for the specific style
|
||||||
assert.equal(parsed.style, style);
|
assert.equal(parsed.style, style);
|
||||||
assert.equal(parsed.style_version, mapnik.versions.mapnik);
|
assert.equal(parsed.style_version, mapnik_version);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -766,6 +771,8 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
||||||
assert.deepEqual(JSON.parse(res.body),
|
assert.deepEqual(JSON.parse(res.body),
|
||||||
{error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"});
|
{error:"missing unknown_user's database_name in redis (try CARTODB/script/restore_redis)"});
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'),
|
||||||
|
"Unexpected Cache-Control: " + res.headers['cache-control']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -786,6 +793,9 @@ suite('server', function() {
|
|||||||
}, function(res) {
|
}, function(res) {
|
||||||
// 401 Unauthorized
|
// 401 Unauthorized
|
||||||
assert.equal(res.statusCode, 401, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 401, res.statusCode + ': ' + res.body);
|
||||||
|
// Failed in 1.6.0 of https://github.com/CartoDB/Windshaft-cartodb/issues/107
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'),
|
||||||
|
"Unexpected Cache-Control: " + res.headers['cache-control']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1179,6 +1189,7 @@ suite('server', function() {
|
|||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
},{}, function(res) {
|
},{}, function(res) {
|
||||||
assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body);
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1210,6 +1221,7 @@ suite('server', function() {
|
|||||||
},{}, function(res) {
|
},{}, function(res) {
|
||||||
// FIXME: should be 401 instead
|
// FIXME: should be 401 instead
|
||||||
assert.equal(res.statusCode, 500, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 500, res.statusCode + ': ' + res.body);
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1262,6 +1274,7 @@ suite('server', function() {
|
|||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
},{}, function(res) {
|
},{}, function(res) {
|
||||||
assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body);
|
||||||
|
assert.ok(!res.headers.hasOwnProperty('cache-control'));
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,31 +5,60 @@ var o = function(port, cb) {
|
|||||||
|
|
||||||
this.queries = [];
|
this.queries = [];
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
this.sqlapi_server = http.createServer(function(req,res) {
|
this.sqlapi_server = http.createServer(function(req,res) {
|
||||||
var query = url.parse(req.url, true).query;
|
//console.log("server got request with method " + req.method);
|
||||||
that.queries.push(query);
|
var query;
|
||||||
if ( query.q.match('SQLAPIERROR') ) {
|
if ( req.method == 'GET' ) {
|
||||||
res.statusCode = 400;
|
query = url.parse(req.url, true).query;
|
||||||
res.write(JSON.stringify({'error':'Some error occurred'}));
|
that.handleQuery(query, res);
|
||||||
} else if ( query.q.match('EPOCH.* as max') ) {
|
}
|
||||||
// This is the structure of the known query sent by tiler
|
else if ( req.method == 'POST') {
|
||||||
var row = {
|
var data = '';
|
||||||
'max': 1234567890.123
|
req.on('data', function(chunk) {
|
||||||
};
|
//console.log("GOT Chunk " + chunk);
|
||||||
res.write(JSON.stringify({rows: [ row ]}));
|
data += chunk;
|
||||||
} else {
|
});
|
||||||
var qs = JSON.stringify(query);
|
req.on('end', function() {
|
||||||
var row = {
|
//console.log("Data is: "); console.dir(data);
|
||||||
// This is the structure of the known query sent by tiler
|
query = JSON.parse(data);
|
||||||
'cdb_querytables': '{' + qs + '}',
|
//console.log("Parsed is: "); console.dir(query);
|
||||||
'max': qs
|
//console.log("handleQuery is " + that.handleQuery);
|
||||||
};
|
that.handleQuery(query, res);
|
||||||
res.write(JSON.stringify({rows: [ row ]}));
|
});
|
||||||
}
|
}
|
||||||
res.end();
|
else {
|
||||||
|
that.handleQuery('SQLAPIEmu does not support method' + req.method, res);
|
||||||
|
}
|
||||||
}).listen(port, cb);
|
}).listen(port, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o.prototype.handleQuery = function(query, res) {
|
||||||
|
this.queries.push(query);
|
||||||
|
if ( query.q.match('SQLAPIERROR') ) {
|
||||||
|
res.statusCode = 400;
|
||||||
|
res.write(JSON.stringify({'error':'Some error occurred'}));
|
||||||
|
} else if ( query.q.match('EPOCH.* as max') ) {
|
||||||
|
// This is the structure of the known query sent by tiler
|
||||||
|
var row = {
|
||||||
|
'max': 1234567890.123
|
||||||
|
};
|
||||||
|
res.write(JSON.stringify({rows: [ row ]}));
|
||||||
|
} else {
|
||||||
|
var qs = JSON.stringify(query);
|
||||||
|
var row = {
|
||||||
|
// This is the structure of the known query sent by tiler
|
||||||
|
'cdb_querytables': '{' + qs + '}',
|
||||||
|
'max': qs
|
||||||
|
};
|
||||||
|
var out_obj = {rows: [ row ]};
|
||||||
|
var out = JSON.stringify(out_obj);
|
||||||
|
res.write(out);
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
o.prototype.close = function(cb) {
|
o.prototype.close = function(cb) {
|
||||||
this.sqlapi_server.close(cb);
|
this.sqlapi_server.close(cb);
|
||||||
};
|
};
|
||||||
|
@ -2,28 +2,84 @@
|
|||||||
|
|
||||||
# TODO: port to node, if you really need it
|
# TODO: port to node, if you really need it
|
||||||
|
|
||||||
REDIS_PORT=6379 # default port
|
ENV='development';
|
||||||
|
BASEDIR=`cd $(dirname $0)/../; pwd`
|
||||||
|
|
||||||
if test -z "$1"; then
|
if test -z "$1"; then
|
||||||
echo "Usage: $0 <username> [<tablename>|~<token>]" >&2
|
echo "Usage: $0 [--env <environment>] <username> [<tablename>|~<token>]" >&2
|
||||||
|
echo " environment defaults to 'development'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
username=""
|
||||||
|
token=""
|
||||||
|
|
||||||
|
while test -n "$1"; do
|
||||||
|
if test "$1" = "--env"; then
|
||||||
|
shift; ENV="$1"; shift
|
||||||
|
elif test -z "$username"; then
|
||||||
|
username="$1"; shift
|
||||||
|
elif test -z "$token"; then
|
||||||
|
token="$1"; shift
|
||||||
|
else
|
||||||
|
echo "Unused option $1" >&2
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Using environment '${ENV}'"
|
||||||
|
|
||||||
|
CONFIG="${BASEDIR}/config/environments/${ENV}.js"
|
||||||
|
REDIS_PORT=`node -e "console.log(require('${CONFIG}').redis.port)"`
|
||||||
|
if test $? -ne 0; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
username="$1"
|
|
||||||
token="$2"
|
|
||||||
|
|
||||||
dbname=`redis-cli -p ${REDIS_PORT} -n 5 hget "rails:users:${username}" "database_name"`
|
dbname=`redis-cli -p ${REDIS_PORT} -n 5 hget "rails:users:${username}" "database_name"`
|
||||||
if test $? -ne 0; then
|
if test $? -ne 0; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if test -z "${dbname}"; then
|
if test -z "${dbname}"; then
|
||||||
echo "Username ${username} unknown by redis (try CARTODB/script/restore_redis?)" >&2
|
echo "Username ${username} unknown by redis on port ${REDIS_PORT} (try CARTODB/script/restore_redis?)" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Database name for user ${username}: ${dbname}" # only if verbose?
|
echo "Database name for user ${username}: ${dbname}" # only if verbose?
|
||||||
if test -n "$token"; then
|
if test -n "$token"; then
|
||||||
redis-cli get "map_style|${dbname}|${token}" | sed -e 's/\\n/\n/g' -e 's/\\//g'
|
rec=`redis-cli get "map_style|${dbname}|${token}"`
|
||||||
|
if test -z "${rec}"; then
|
||||||
|
echo "${token}: no such map style known by redis on port ${REDIS_PORT}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
#echo "${rec}"
|
||||||
|
escrec=`echo "${rec}" | sed -e 's/\\\\/\\\\\\\\/g'`
|
||||||
|
#echo "${escrec}"
|
||||||
|
node <<EOF
|
||||||
|
var x=JSON.parse('${escrec}');
|
||||||
|
console.log('style: ' + x.style);
|
||||||
|
console.log('version: ' + x.version);
|
||||||
|
|
||||||
|
global.environment = require('${CONFIG}');
|
||||||
|
var serverOptions = require('${BASEDIR}/lib/cartodb/server_options'); // _after_ setting global.environment
|
||||||
|
var grainstore = require('${BASEDIR}/node_modules/windshaft/node_modules/grainstore/lib/grainstore');
|
||||||
|
var mml_store = new grainstore.MMLStore(serverOptions.redis, serverOptions.grainstore);
|
||||||
|
var builderconfig = {dbname:'${dbname}'};
|
||||||
|
if ( '${token}'.match(/^~/) ) {
|
||||||
|
builderconfig.token = '${token}'.substring(1);
|
||||||
|
} else {
|
||||||
|
builderconfig.table = '${token}';
|
||||||
|
}
|
||||||
|
var mml_builder = mml_store.mml_builder(builderconfig,
|
||||||
|
function(err, payload) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
mml_builder.toXML(function(err, xml) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
console.log('- XML - ');
|
||||||
|
console.log(xml);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
EOF
|
||||||
|
#echo "${rec}" | sed -e 's/\\n/\n/g' -e 's/\\//g'
|
||||||
else
|
else
|
||||||
redis-cli keys "map_style|${dbname}|*"
|
redis-cli keys "map_style|${dbname}|*"
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user