diff --git a/.gitignore b/.gitignore index 040b421a..e6d5b01a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ logs/ pids/ redis.pid test.log +npm-debug.log diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..e8d605fc --- /dev/null +++ b/.jshintrc @@ -0,0 +1,92 @@ +{ +// // JSHint Default Configuration File (as on JSHint website) +// // See http://jshint.com/docs/ for more details +// +// "maxerr" : 50, // {int} Maximum error before stopping +// +// // Enforcing +// "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) +// "camelcase" : false, // true: Identifiers must be in camelCase +// "curly" : true, // true: Require {} for every new block or scope +// "eqeqeq" : true, // true: Require triple equals (===) for comparison + "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() + "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. + "immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` +// "indent" : 4, // {int} Number of spaces to use for indentation +// "latedef" : false, // true: Require variables/functions to be defined before being used + "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` + "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` +// "noempty" : true, // true: Prohibit use of empty blocks + "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. + "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment) +// "plusplus" : false, // true: Prohibit use of `++` & `--` +// "quotmark" : false, // Quotation mark consistency: +// // false : do nothing (default) +// // true : ensure whatever is used is consistent +// // "single" : require single quotes +// // "double" : require double quotes + "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) + "unused" : true, // true: Require all defined variables be used +// "strict" : true, // true: Requires all functions run in ES5 Strict Mode +// "maxparams" : false, // {int} Max number of formal params allowed per function +// "maxdepth" : false, // {int} Max depth of nested blocks (within functions) +// "maxstatements" : false, // {int} Max number statements per function + "maxcomplexity" : 8, // {int} Max cyclomatic complexity per function + "maxlen" : 120, // {int} Max number of characters per line +// +// // Relaxing +// "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) +// "boss" : false, // true: Tolerate assignments where comparisons would be expected + "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. +// "eqnull" : false, // true: Tolerate use of `== null` +// "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) +// "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) +// "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) +// // (ex: `for each`, multiple try/catch, function expression…) +// "evil" : false, // true: Tolerate use of `eval` and `new Function()` +// "expr" : false, // true: Tolerate `ExpressionStatement` as Programs +// "funcscope" : false, // true: Tolerate defining variables inside control statements +// "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') +// "iterator" : false, // true: Tolerate using the `__iterator__` property +// "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block +// "laxbreak" : false, // true: Tolerate possibly unsafe line breakings +// "laxcomma" : false, // true: Tolerate comma-first style coding +// "loopfunc" : false, // true: Tolerate functions being defined in loops +// "multistr" : false, // true: Tolerate multi-line strings +// "noyield" : false, // true: Tolerate generator functions with no yield statement in them. +// "notypeof" : false, // true: Tolerate invalid typeof operator values +// "proto" : false, // true: Tolerate using the `__proto__` property +// "scripturl" : false, // true: Tolerate script-targeted URLs +// "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` +// "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation +// "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` +// "validthis" : false, // true: Tolerate using this in a non-constructor function +// +// // Environments +// "browser" : true, // Web Browser (window, document, etc) +// "browserify" : false, // Browserify (node.js code in the browser) +// "couch" : false, // CouchDB +// "devel" : true, // Development/debugging (alert, confirm, etc) +// "dojo" : false, // Dojo Toolkit +// "jasmine" : false, // Jasmine +// "jquery" : false, // jQuery +// "mocha" : true, // Mocha +// "mootools" : false, // MooTools + "node" : true, // Node.js +// "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) +// "prototypejs" : false, // Prototype and Scriptaculous +// "qunit" : false, // QUnit +// "rhino" : false, // Rhino +// "shelljs" : false, // ShellJS +// "worker" : false, // Web Workers +// "wsh" : false, // Windows Scripting Host +// "yui" : false, // Yahoo User Interface + + // Custom Globals + "globals" : { // additional predefined global variables + "suite": true, + "suiteSetup": true, + "test": true, + "suiteTeardown": true + } +} diff --git a/Makefile b/Makefile index 32a48859..1d3c1cdd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ -srcdir=$(shell pwd) +SHELL=/bin/bash + +pre-install: + @$(SHELL) ./scripts/check-node-canvas.sh all: - npm install + @$(SHELL) ./scripts/install.sh clean: rm -rf node_modules/* @@ -15,24 +18,21 @@ config.status--test: config/environments/test.js: config.status--test ./config.status--test -check-local: config/environments/test.js - ./run_tests.sh ${RUNTESTFLAGS} \ - test/unit/cartodb/*.js \ - test/unit/cartodb/cache/model/*.js \ - test/integration/*.js \ - test/acceptance/*.js \ - test/acceptance/cache/*.js +test: config/environments/test.js + @echo "***tests***" + @$(SHELL) ./run_tests.sh ${RUNTESTFLAGS} \ + test/unit/cartodb/*.js \ + test/unit/cartodb/cache/model/*.js \ + test/integration/*.js \ + test/acceptance/*.js \ + test/acceptance/cache/*.js -check-submodules: - PATH="$$PATH:$(srcdir)/node_modules/.bin/"; \ - for sub in windshaft grainstore node-varnish mapnik; do \ - if test -e node_modules/$${sub}; then \ - echo "Testing submodule $${sub}"; \ - make -C node_modules/$${sub} check || exit 1; \ - fi; \ - done +jshint: + @echo "***jshint***" + @./node_modules/.bin/jshint lib/ -check-full: check-local check-submodules +test-all: jshint test -check: check-local +check: test +.PHONY: pre-install test diff --git a/NEWS.md b/NEWS.md index 1945ac26..eb5dd295 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,21 @@ -1.28.6 -- 2015-mm-dd +1.30.1 -- 2015-mm-dd -------------------- +1.30.0 -- 2015-03-11 +-------------------- + +Announcements: + - Upgrades windshaft to [0.40.0](https://github.com/CartoDB/Windshaft/releases/tag/0.40.0) + + +1.29.0 -- 2015-03-09 +-------------------- + +Announcements: + - Upgrades windshaft to [0.39.0](https://github.com/CartoDB/Windshaft/releases/tag/0.39.0) + + 1.28.5 -- 2015-02-20 -------------------- diff --git a/README.md b/README.md index 3cb2b036..aa2c7028 100644 --- a/README.md +++ b/README.md @@ -3,36 +3,36 @@ Windshaft-CartoDB [![Build Status](https://travis-ci.org/CartoDB/Windshaft-cartodb.svg?branch=master)](https://travis-ci.org/CartoDB/Windshaft-cartodb) -This is the CartoDB map tiler. It extends Windshaft with some extra -functionality and custom filters for authentication +This is the [CartoDB Maps API](http://docs.cartodb.com/cartodb-platform/maps-api.html) tiler. It extends +[Windshaft](https://github.com/CartoDB/Windshaft) with some extra functionality and custom filters for authentication. * reads dbname from subdomain and cartodb redis for pretty tile urls -* configures windshaft to publish ``cartodb_id`` as the interactivity layer +* configures windshaft to publish `cartodb_id` as the interactivity layer * gets the default geometry type from the cartodb redis store * allows tiles to be styled individually * provides a link to varnish high speed cache * provides a ``infowindow`` endpoint for windshaft (DEPRECATED) * provides a ``map_metadata`` endpoint for windshaft (DEPRECATED) -* provides signed template maps API - (http://github.com/CartoDB/Windshaft-cartodb/wiki/Template-maps) +* provides a [template maps API](https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Template-maps.md) Requirements ------------ + - Core + - Node.js >=0.8 + - npm >=1.2.1 + - PostgreSQL >8.3.x, PostGIS >1.5.x + - Redis >2.4.0 (http://www.redis.io) + - Mapnik 2.0.1, 2.0.2, 2.1.0, 2.2.0, 2.3.0. See Installing Mapnik. + - Windshaft: check [Windshaft dependencies and installation notes](https://github.com/CartoDB/Windshaft#dependencies) + - libcairo2-dev, libpango1.0-dev, libjpeg8-dev and libgif-dev for server side canvas support - [core] - - node-0.8.x+ - - PostgreSQL-8.3+ - - PostGIS-1.5.0+ - - Redis 2.4.0+ (http://www.redis.io) - - Mapnik 2.0 or 2.1 +- For cache control (optional) + - CartoDB-SQL-API 1.0.0+ + - CartoDB 0.9.5+ (for `CDB_QueryTables`) + - Varnish (http://www.varnish-cache.org) - [for cache control] - - CartoDB-SQL-API 1.0.0+ - - CartoDB 0.9.5+ (for ``CDB_QueryTables``) - - Varnish (http://www.varnish-cache.org) - - [for running the testsuite] - - Imagemagick (http://www.imagemagick.org) +- For running the testsuite + - ImageMagick (http://www.imagemagick.org) Configure --------- @@ -74,59 +74,16 @@ there may be out-of-sync records in there. Take a look: http://redis.io/commands -URLs ----- +Documentation +------------- -**TILES** - -[GET] subdomain.cartodb.com/tiles/:table_name/:z/:x/:y.[png|png8|grid.json] - -Args: - -* sql - plain SQL arguments -* interactivity - specify the column to use in UTFGrid -* cache_buster - Specify an identifier for the internal tile cache. - Requesting tiles with the same cache_buster value may - result in being served a cached version of the tile - (even when requesting a tile for the first time, as tiles - can be prepared in advance) -* cache_policy - Set to "persist" to have the server send an Cache-Control - header requesting caching devices to keep the response - cached as much as possible. This is best used with a - timestamp value in cache_buster for manual control of - updates. -* geom_type - override the cartodb default -* style - override the default map style with Carto +The [docs directory](https://github.com/CartoDB/Windshaft-cartodb/tree/master/docs) contains different documentation +resources, from higher level to more detailed ones: +The [Maps API](https://github.com/CartoDB/Windshaft-cartodb/blob/master/docs/Map-API.md) defined the endpoints and their +expected parameters and outputs. -**STYLE** +Examples +-------- -[GET/POST] subdomain.cartodb.com/tiles/:table_name/style - -Args: - -* style - the style in CartoCSS you want to set -* style_version - the version of the style for POST -* style_convert - request conversion to target version (both POST and GET) - - -**INFOWINDOW** - -[GET] subdomain.cartodb.com/tiles/:table_name/infowindow - -Args: - -* infowindow - returns contents of infowindow from CartoDB. - - -**MAP METADATA** - -[GET] subdomain.cartodb.com/tiles/:table_name/map_metadata - -Args: - -* infowindow - returns contents of infowindow from CartoDB. - - -All GET requests are wrappable with JSONP using callback argument, -including the UTFGrid map tile call. +[CartoDB's Map Gallery](http://cartodb.com/gallery/) showcases several examples of visualisations built on top of this. diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 2c391dd1..d6bfba7f 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -14,11 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup)' + ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' // Base url for the Inline Maps and Table Maps API ,base_url_legacy: '/tiles/:table' @@ -174,6 +174,12 @@ var config = { x: 0, y: 0 } + + // Use this as a feature flags enabling/disabling mechanism + ,enabledFeatures: { + // whether the affected tables for a given SQL must query directly postgresql or use the SQL API + cdbQueryTablesFromPostgres: true + } }; module.exports = config; diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 0d4e999a..e58aea66 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -14,11 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup)' + ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' // Base url for the Inline Maps and Table Maps API ,base_url_legacy: '/tiles/:table' @@ -183,6 +183,12 @@ var config = { x: 0, y: 0 } + + // Use this as a feature flags enabling/disabling mechanism + ,enabledFeatures: { + // whether the affected tables for a given SQL must query directly postgresql or use the SQL API + cdbQueryTablesFromPostgres: true + } }; module.exports = config; diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 0c88a9c7..8f4b0941 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -14,11 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/maps/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/maps/named|/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' // Base url for the Detached Maps API // "/api/v1/maps" is the the new API, // "/tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/maps|/tiles/layergroup)' + ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' // Base url for the Inline Maps and Table Maps API ,base_url_legacy: '/tiles/:table' @@ -183,6 +183,12 @@ var config = { x: 0, y: 0 } + + // Use this as a feature flags enabling/disabling mechanism + ,enabledFeatures: { + // whether the affected tables for a given SQL must query directly postgresql or use the SQL API + cdbQueryTablesFromPostgres: true + } }; module.exports = config; diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 67551249..64c40ffd 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -14,11 +14,11 @@ var config = { // Base url for the Templated Maps API // "/api/v1/map/named" is the new API, // "/tiles/template" is for compatibility with versions up to 1.6.x - ,base_url_templated: '(?:/api/v1/map/named|/tiles/template)' + ,base_url_templated: '(?:/api/v1/map/named|/tiles/template|/u/:user/api/v1/map/named|/u/:user/tiles/template)' // Base url for the Detached Maps API // "maps" is the the new API, // "tiles/layergroup" is for compatibility with versions up to 1.6.x - ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup)' + ,base_url_detached: '(?:/api/v1/map|/tiles/layergroup|/u/:user/api/v1/map|/u/:user/tiles/layergroup)' // Base url for the Inline Maps and Table Maps API ,base_url_legacy: '/tiles/:table' @@ -172,6 +172,12 @@ var config = { x: 0, y: 0 } + + // Use this as a feature flags enabling/disabling mechanism + ,enabledFeatures: { + // whether the affected tables for a given SQL must query directly postgresql or use the SQL API + cdbQueryTablesFromPostgres: true + } }; module.exports = config; diff --git a/docs/Map-API.md b/docs/Map-API.md index 2fe76644..c3a9a762 100644 --- a/docs/Map-API.md +++ b/docs/Map-API.md @@ -34,10 +34,10 @@ $.ajax({ type: 'POST', dataType: 'json', contentType: 'application/json', - url: 'http://documentation.cartodb.com/api/v1/map', + url: 'https://documentation.cartodb.com/api/v1/map', data: JSON.stringify(mapconfig), success: function(data) { - var templateUrl = 'http://documentation.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png' + var templateUrl = 'https://documentation.cartodb.com/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png' console.log(templateUrl); } }) @@ -79,7 +79,7 @@ To get the `URL` to fetch the tiles you need to instantiate the map, where `temp
```bash -curl -X POST 'http://{account}.cartodb.com/api/v1/map/named/:template_id' -H 'Content-Type: application/json' +curl -X POST 'https://{account}.cartodb.com/api/v1/map/named/:template_id' -H 'Content-Type: application/json' ``` The response will return JSON with properties for the `layergroupid` and the timestamp (`last_updated`) of the last data modification. @@ -96,7 +96,7 @@ Here is an example response: You can use the `layergroupid` to instantiate a URL template for accessing tiles on the client. Here we use the `layergroupid` from the example response above in this URL template: ```bash -http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png +https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png ``` ## General Concepts @@ -107,7 +107,7 @@ The following concepts are the same for every endpoint in the API except when it By default, users do not have access to private tables in CartoDB. In order to instantiate a map from private table data an API Key is required. Additionally, to include some endpoints, an API Key must be included (e.g. creating a named map). -To execute an authorized request, api_key=YOURAPIKEY should be added to the request URL. The param can be also passed as POST param. We **strongly advise** using HTTPS when you are performing requests that include your `api_key`. +To execute an authorized request, `api_key=YOURAPIKEY` should be added to the request URL. The param can be also passed as POST param. Using HTTPS is mandatory when you are performing requests that include your `api_key`. ### Errors @@ -167,7 +167,7 @@ The response includes: The ID for that map, used to compose the URL for the tiles. The final URL is: ```html - http://{account}.cartodb.com/api/v1/map/:layergroupid/{z}/{x}/{y}.png + https://{account}.cartodb.com/api/v1/map/:layergroupid/{z}/{x}/{y}.png ``` - **updated_at** @@ -183,7 +183,7 @@ The response includes:
REQUEST
```bash -curl 'http://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json +curl 'https://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application/json' -d @mapconfig.json ```
RESPONSE
@@ -201,19 +201,19 @@ curl 'http://documentation.cartodb.com/api/v1/map' -H 'Content-Type: application The tiles can be accessed using: ```bash -http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png +https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/{z}/{x}/{y}.png ``` For UTF grid tiles: ```bash -http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/{z}/{x}/{y}.grid.json +https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/{z}/{x}/{y}.grid.json ``` For attributes defined in `attributes` section: ```bash -http://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/attributes/:feature_id +https://documentation.cartodb.com/api/v1/map/c01a54877c62831bb51720263f91fb33:0/:layer/attributes/:feature_id ``` Which returns JSON with the attributes defined, like: diff --git a/docs/Routes.md b/docs/Routes.md new file mode 100644 index 00000000..0920dadf --- /dev/null +++ b/docs/Routes.md @@ -0,0 +1,128 @@ +This document list all routes available in Windshaft-cartodb Maps API server. + +## Routes list + +1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:z/:x/:y@:scale_factor?x.:format {:token(f),:z(f),:x(f),:y(f),:scale_factor(t),:format(f)} (1)` +
Notes: Mapnik retina tiles [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:z/:x/:y.:format {:token(f),:z(f),:x(f),:y(f),:format(f)} (1)` +
Notes: Mapnik tiles [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:layer/:z/:x/:y.(:format) {:token(f),:layer(f),:z(f),:x(f),:y(f),:format(f)} (1)` +
Notes: Per :layer rendering based on :format [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup) {} (1)` +
Notes: Map instantiation [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup)/:token/:layer/attributes/:fid {:token(f),:layer(f),:fid(f)} (1)` +
Notes: Endpoint for info windows data, alternative for sql api when tables are private [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup)/static/center/:token/:z/:lat/:lng/:width/:height.:format {:token(f),:z(f),:lat(f),:lng(f),:width(f),:height(f),:format(f)} (1)` +
Notes: Static Maps API [0] + +1. `GET (?:/api/v1/map|/tiles/layergroup)/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format {:token(f),:west(f),:south(f),:east(f),:north(f),:width(f),:height(f),:format(f)} (1)` +
Notes: Static Maps API [0] + +1. `GET / {} (1)` +
Notes: Welcome message + +1. `GET /version {} (1)` +
Notes: Return relevant module versions: mapnik, grainstore, etc + +1. `GET /tiles/:table/:z/:x/:y.* {:table(f),:z(f),:x(f),:y(f)} (1)` +
Notes: **[DEPRECATED]** Per :table tiles rendering + +1. `GET /tiles/:table/style {:table(f)} (1)` +
Notes: **[DEPRECATED]** Style for :table + +1. `GET (?:/api/v1/map/named|/tiles/template)/:template_id/jsonp {:template_id(f)} (1)` +
Notes: Named maps JSONP instantiation [1] + +1. `GET (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)` +
Notes: Named map retrieval (w/ API KEY) [1] + +1. `GET (?:/api/v1/map/named|/tiles/template) {} (1)` +
Notes: List named maps (w/ API KEY) [1] + +1. `GET /tiles/:table/infowindow {:table(f)} (1)` +
Notes: **[DEPRECATED]** retrieve info window template for :table + +1. `GET /tiles/:table/map_metadata {:table(f)} (1)` +
Notes: **[DEPRECATED]** retrieve map metadata for :table + +1. `GET /health {} (1)` +
Notes: Healt check + +1. `OPTIONS (?:/api/v1/map|/tiles/layergroup) {} (1)` +
Notes: CORS [0] + +1. `OPTIONS /tiles/:table/:z/:x/:y.* {:table(f),:z(f),:x(f),:y(f)} (1)` +
Notes: **[DEPRECATED]** CORS + +1. `OPTIONS /tiles/:table/style {:table(f)} (1)` +
Notes: **[DEPRECATED]** CORS + +1. `OPTIONS (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)` +
Notes: CORS [1] + +1. `POST (?:/api/v1/map|/tiles/layergroup) {} (1)` +
Notes: Map instantiation [0] + +1. `POST /tiles/:table/style {:table(f)} (1)` +
Notes: **[DEPRECATED]** Create style for :table + +1. `POST (?:/api/v1/map/named|/tiles/template) {} (1)` +
Notes: Create named map (w/ API KEY) [1] + +1. `POST (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)` +
Notes: Instantiate named map [1] + +1. `DELETE /tiles/:table/style {:table(f)} (1)` +
Notes: **[DEPRECATED]** Delete :table style + +1. `DELETE (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)` +
Notes: Delete named map (w/ API KEY) [1] + +1. `DELETE /tiles/:table/flush_cache {:table(f)} (1)` +
Notes: **[DEPRECATED]** Flush internal caches for :table + +1. `PUT (?:/api/v1/map/named|/tiles/template)/:template_id {:template_id(f)} (1)` +
Notes: Update a named map (w/ API KEY) [1] + +## Optional deprecated routes + +- [0] `/tiles/layergroup` is deprecated and `/api/v1/map` should be used but we keep it for now. +- [1] `/tiles/template` is deprecated and `/api/v1/map/named` should be used but we keep it for now. + +## How to generate the list of routes + +Something like the following patch should do the trick + +```javascript +diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js +index 477a4c2..f69eebb 100644 +--- a/lib/cartodb/cartodb_windshaft.js ++++ b/lib/cartodb/cartodb_windshaft.js +@@ -242,6 +242,20 @@ var CartodbWindshaft = function(serverOptions) { + } + }); + ++ var format = require('util').format; ++ var routesNotes = Object.keys(ws.routes.routes) ++ .map(function(method) { return ws.routes.routes[method]; }) ++ .reduce(function(previous, current) { current.map(function(r) { previous.push(r) }); return previous;}, []) ++ .map(function(route) { ++ return format("\n1. `%s %s {%s} (%d)`\n
Notes: [DEPRECATED]? ", ++ route.method.toUpperCase(), ++ route.path, ++ route.keys.map(function(k) { return format(':%s(%s)', k.name, k.optional ? 't' : 'f'); } ).join(','), ++ route.callbacks.length ++ ); ++ }); ++ console.log(routesNotes.join('\n')); ++ + return ws; + }; + + +``` diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js index f4795b05..1db18489 100644 --- a/lib/cartodb/api/query_tables_api.js +++ b/lib/cartodb/api/query_tables_api.js @@ -1,6 +1,6 @@ var sqlApi = require('../sql/sql_api'); var PSQL = require('cartodb-psql'); -var Step = require('step'); +var step = require('step'); function QueryTablesApi(pgConnection, metadataBackend) { this.pgConnection = pgConnection; @@ -78,7 +78,7 @@ QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, call var params = {}; - Step( + step( function setAuth() { self.pgConnection.setDBAuth(username, params, this); }, @@ -109,7 +109,7 @@ QueryTablesApi.prototype.runQuery = function(username, query, queryHandler, call } else { - Step( + step( function getApiKey() { self.metadataBackend.getUserMapKey(username, this); }, @@ -138,7 +138,7 @@ function prepareSql(sql) { function shouldQueryPostgresDirectly() { - return global.environment - && global.environment.enabledFeatures - && global.environment.enabledFeatures.cdbQueryTablesFromPostgres; + return global.environment && + global.environment.enabledFeatures && + global.environment.enabledFeatures.cdbQueryTablesFromPostgres; } diff --git a/lib/cartodb/backends/pg_connection.js b/lib/cartodb/backends/pg_connection.js index 37209b98..7e4aad15 100644 --- a/lib/cartodb/backends/pg_connection.js +++ b/lib/cartodb/backends/pg_connection.js @@ -1,4 +1,4 @@ -var Step = require('step'); +var step = require('step'); var _ = require('underscore'); function PgConnection(metadataBackend) { @@ -24,13 +24,13 @@ PgConnection.prototype.setDBAuth = function(username, params, callback) { var user_params = {}; var auth_user = global.environment.postgres_auth_user; var auth_pass = global.environment.postgres_auth_pass; - Step( + step( function getId() { self.metadataBackend.getUserId(username, this); }, function(err, user_id) { if (err) throw err; - user_params['user_id'] = user_id; + user_params.user_id = user_id; var dbuser = _.template(auth_user, user_params); _.extend(params, {dbuser:dbuser}); @@ -42,7 +42,7 @@ PgConnection.prototype.setDBAuth = function(username, params, callback) { }, function(err, user_password) { if (err) throw err; - user_params['user_password'] = user_password; + user_params.user_password = user_password; if ( auth_pass ) { var dbpass = _.template(auth_pass, user_params); _.extend(params, {dbpassword:dbpass}); @@ -76,7 +76,7 @@ PgConnection.prototype.setDBConn = function(dbowner, params, callback) { dbhost: global.environment.postgres.host, dbport: global.environment.postgres.port }); - Step( + step( function getConnectionParams() { self.metadataBackend.getUserDBConnectionParams(dbowner, this); }, diff --git a/lib/cartodb/cache_validator.js b/lib/cartodb/cache_validator.js index 22793603..4b3f2181 100644 --- a/lib/cartodb/cache_validator.js +++ b/lib/cartodb/cache_validator.js @@ -1,6 +1,5 @@ -var _ = require('underscore'), - Varnish = require('node-varnish'), - varnish_queue = null; +var Varnish = require('node-varnish'); +var varnish_queue = null; function init(host, port, secret) { varnish_queue = new Varnish.VarnishQueue(host, port, secret); @@ -23,4 +22,4 @@ function invalidate_db(dbname, table) { module.exports = { init: init, invalidate_db: invalidate_db -} +}; diff --git a/lib/cartodb/cartodb_windshaft.js b/lib/cartodb/cartodb_windshaft.js index bff4d0b1..10830f50 100644 --- a/lib/cartodb/cartodb_windshaft.js +++ b/lib/cartodb/cartodb_windshaft.js @@ -1,12 +1,11 @@ var _ = require('underscore'); -var Step = require('step'); +var step = require('step'); var Windshaft = require('windshaft'); -var Cache = require('./cache_validator'); var os = require('os'); var HealthCheck = require('./monitoring/health_check'); -if ( ! process.env['PGAPPNAME'] ) - process.env['PGAPPNAME']='cartodb_tiler'; +if ( ! process.env.PGAPPNAME ) + process.env.PGAPPNAME='cartodb_tiler'; var CartodbWindshaft = function(serverOptions) { // Perform keyword substitution in statsd @@ -18,8 +17,8 @@ var CartodbWindshaft = function(serverOptions) { } } - var redisPool = serverOptions.redis.pool - || require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:cartodb'})); + var redisPool = serverOptions.redis.pool || + require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:cartodb'})); var cartoData = require('cartodb-redis')({pool: redisPool}); @@ -34,18 +33,21 @@ var CartodbWindshaft = function(serverOptions) { var SurrogateKeysCache = require('./cache/surrogate_keys_cache'), NamedMapsCacheEntry = require('./cache/model/named_maps_entry'), VarnishHttpCacheBackend = require('./cache/backend/varnish_http'), - varnishHttpCacheBackend = new VarnishHttpCacheBackend(serverOptions.varnish_host, serverOptions.varnish_http_port), + varnishHttpCacheBackend = new VarnishHttpCacheBackend( + serverOptions.varnish_host, + serverOptions.varnish_http_port + ), surrogateKeysCache = new SurrogateKeysCache(varnishHttpCacheBackend); - if (serverOptions.varnish_purge_enabled) { - function invalidateNamedMap(owner, templateName) { - surrogateKeysCache.invalidate(new NamedMapsCacheEntry(owner, templateName), function(err) { - if (err) { - console.warn('Cache: surrogate key invalidation failed'); - } - }); - } + function invalidateNamedMap (owner, templateName) { + surrogateKeysCache.invalidate(new NamedMapsCacheEntry(owner, templateName), function(err) { + if (err) { + console.warn('Cache: surrogate key invalidation failed'); + } + }); + } + if (serverOptions.varnish_purge_enabled) { ['update', 'delete'].forEach(function(eventType) { templateMaps.on(eventType, invalidateNamedMap); }); @@ -85,7 +87,7 @@ var CartodbWindshaft = function(serverOptions) { } } var req = res.req; - Step ( + step ( function addCacheChannel() { if ( ! req ) { // having no associated request can happen when @@ -107,10 +109,11 @@ var CartodbWindshaft = function(serverOptions) { //console.log("Skipping cache channel in route:\n" + req.route.path); return false; } -//console.log("Adding cache channel to route\n" + req.route.path + " not matching any in:\n" + mapCreateRoutes.join("\n")); +//console.log("Adding cache channel to route\n" + req.route.path + " not matching any in:\n" + +// mapCreateRoutes.join("\n")); serverOptions.addCacheChannel(that, req, this); }, - function sendResponse(err, added) { + function sendResponse(err/*, added*/) { if ( err ) console.log(err + err.stack); ws_sendResponse.apply(that, thatArgs); return null; diff --git a/lib/cartodb/controllers/template_maps.js b/lib/cartodb/controllers/template_maps.js index 5b61ae56..452f7225 100644 --- a/lib/cartodb/controllers/template_maps.js +++ b/lib/cartodb/controllers/template_maps.js @@ -1,4 +1,4 @@ -var Step = require('step'); +var step = require('step'); var _ = require('underscore'); function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl, surrogateKeysCache, @@ -35,7 +35,7 @@ TemplateMapsController.prototype.create = function(req, res) { var cdbuser = self.serverOptions.userByReq(req); - Step( + step( function checkPerms(){ self.serverOptions.authorizedByAPIKey(req, this); }, @@ -83,7 +83,7 @@ TemplateMapsController.prototype.update = function(req, res) { var cdbuser = this.serverOptions.userByReq(req); var template; var tpl_id; - Step( + step( function checkPerms(){ self.serverOptions.authorizedByAPIKey(req, this); }, @@ -100,8 +100,7 @@ TemplateMapsController.prototype.update = function(req, res) { tpl_id = req.params.template_id.split('@'); if ( tpl_id.length > 1 ) { if ( tpl_id[0] != cdbuser ) { - err = new Error("Invalid template id '" - + req.params.template_id + "' for user '" + cdbuser + "'"); + err = new Error("Invalid template id '" + req.params.template_id + "' for user '" + cdbuser + "'"); err.http_status = 404; throw err; } @@ -142,9 +141,8 @@ TemplateMapsController.prototype.retrieve = function(req, res) { this.app.doCORS(res); var cdbuser = this.serverOptions.userByReq(req); - var template; var tpl_id; - Step( + step( function checkPerms(){ self.serverOptions.authorizedByAPIKey(req, this); }, @@ -158,10 +156,10 @@ TemplateMapsController.prototype.retrieve = function(req, res) { tpl_id = req.params.template_id.split('@'); if ( tpl_id.length > 1 ) { if ( tpl_id[0] != cdbuser ) { - var err = new Error("Cannot get template id '" - + req.params.template_id + "' for user '" + cdbuser + "'"); - err.http_status = 404; - throw err; + var templateNotFoundErr = new Error("Cannot get template id '" + req.params.template_id + + "' for user '" + cdbuser + "'"); + templateNotFoundErr.http_status = 404; + throw templateNotFoundErr; } tpl_id = tpl_id[1]; } @@ -204,9 +202,8 @@ TemplateMapsController.prototype.destroy = function(req, res) { this.app.doCORS(res); var cdbuser = this.serverOptions.userByReq(req); - var template; var tpl_id; - Step( + step( function checkPerms(){ self.serverOptions.authorizedByAPIKey(req, this); }, @@ -220,16 +217,16 @@ TemplateMapsController.prototype.destroy = function(req, res) { tpl_id = req.params.template_id.split('@'); if ( tpl_id.length > 1 ) { if ( tpl_id[0] != cdbuser ) { - var err = new Error("Cannot find template id '" - + req.params.template_id + "' for user '" + cdbuser + "'"); - err.http_status = 404; - throw err; + var templateNotFoundErr = new Error("Cannot find template id '" + req.params.template_id + + "' for user '" + cdbuser + "'"); + templateNotFoundErr.http_status = 404; + throw templateNotFoundErr; } tpl_id = tpl_id[1]; } self.templateMaps.delTemplate(cdbuser, tpl_id, this); }, - function prepareResponse(err, tpl_val){ + function prepareResponse(err/*, tpl_val*/){ if ( err ) throw err; return { status: 'ok' }; }, @@ -259,7 +256,7 @@ TemplateMapsController.prototype.list = function(req, res) { var cdbuser = this.serverOptions.userByReq(req); - Step( + step( function checkPerms(){ self.serverOptions.authorizedByAPIKey(req, this); }, @@ -299,7 +296,7 @@ TemplateMapsController.prototype.instantiate = function(req, res) { if ( req.profiler && req.profiler.statsd_client) { req.profiler.start('windshaft-cartodb.instance_template_post'); } - Step( + step( function() { if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json') { throw new Error('template POST data must be of type application/json, it is instead '); @@ -311,7 +308,7 @@ TemplateMapsController.prototype.instantiate = function(req, res) { ); }; -TemplateMapsController.prototype.options = function(req, res) { +TemplateMapsController.prototype.options = function(req, res, next) { this.app.doCORS(res, "Content-Type"); return next(); }; @@ -326,7 +323,7 @@ TemplateMapsController.prototype.jsonp = function(req, res) { if ( req.profiler && req.profiler.statsd_client) { req.profiler.start('windshaft-cartodb.instance_template_get'); } - Step( + step( function() { if ( req.query.callback === undefined || req.query.callback.length === 0) { throw new Error('callback parameter should be present and be a function name'); @@ -361,9 +358,8 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa var tpl_id = req.params.template_id.split('@'); if ( tpl_id.length > 1 ) { if ( tpl_id[0] && tpl_id[0] != cdbuser ) { - var err = new Error('Cannot instanciate map of user "' - + tpl_id[0] + '" on database of user "' - + cdbuser + '"'); + var err = new Error('Cannot instanciate map of user "' + tpl_id[0] + '" on database of user "' + cdbuser + + '"'); err.http_status = 403; callback(err); return; @@ -371,7 +367,7 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa tpl_id = tpl_id[1]; } var auth_token = req.query.auth_token; - Step( + step( function getTemplate(){ self.templateMaps.getTemplate(cdbuser, tpl_id, this); }, @@ -464,7 +460,7 @@ TemplateMapsController.prototype.finish_instantiation = function(err, response, TemplateMapsController.prototype.setDBParams = function(cdbuser, params, callback) { var self = this; - Step( + step( function setAuth() { self.pgConnection.setDBAuth(cdbuser, params, this); }, diff --git a/lib/cartodb/monitoring/health_check.js b/lib/cartodb/monitoring/health_check.js index 873cd19d..930f20a4 100644 --- a/lib/cartodb/monitoring/health_check.js +++ b/lib/cartodb/monitoring/health_check.js @@ -1,8 +1,7 @@ -var _ = require('underscore'), - dot = require('dot'), - fs = require('fs'), - path = require('path'), - Step = require('step'); +var dot = require('dot'); +var fs = require('fs'); +var path = require('path'); +var step = require('step'); function HealthCheck(metadataBackend, tilelive) { this.metadataBackend = metadataBackend; @@ -40,9 +39,9 @@ HealthCheck.prototype.check = function(config, callback) { ok: false } }; - mapnikXmlParams = config; + var mapnikXmlParams = config; - Step( + step( function getDBParams() { startTime = Date.now(); self.metadataBackend.getAllUserDBParams(config.username, this); diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index 807024a8..6bf0c32b 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -1,5 +1,5 @@ var _ = require('underscore'); -var Step = require('step'); +var step = require('step'); var QueryTablesApi = require('./api/query_tables_api'); var PgConnection = require('./backends/pg_connection'); var crypto = require('crypto'); @@ -18,6 +18,7 @@ if ( _.isUndefined(global.environment.sqlapi.domain) ) { // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ + 'user', 'sql', 'geom_type', 'cache_buster', @@ -35,8 +36,8 @@ var REQUEST_QUERY_PARAMS_WHITELIST = [ ]; module.exports = function(redisPool) { - redisPool = redisPool - || require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:server_options'})); + redisPool = redisPool || + require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:server_options'})); var cartoData = require('cartodb-redis')({ pool: redisPool }), lzmaWorker = new LZMA(), @@ -147,7 +148,7 @@ module.exports = function(redisPool) { var that = this; - Step ( + step ( function checkCached() { if ( me.channelCache.hasOwnProperty(cacheKey) ) { callback(null, me.channelCache[cacheKey]); @@ -167,7 +168,7 @@ module.exports = function(redisPool) { } var next = this; var mapStore = app.mapStore; - Step( + step( function loadFromStore() { mapStore.load(req.params.token, this); }, @@ -196,7 +197,7 @@ module.exports = function(redisPool) { // strip out windshaft/mapnik inserted sql if present var sql = req.params.sql.match(/^\((.*)\)\sas\scdbq$/); - sql = (sql != null) ? sql[1] : req.params.sql; + sql = (sql !== null) ? sql[1] : req.params.sql; return sql; }, @@ -281,14 +282,16 @@ module.exports = function(redisPool) { }; me.beforeLayergroupCreate = function(req, requestMapConfig, callback) { - mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection, function(err, layers, datasource) { - if (err) { - return callback(err); - } + mapConfigNamedLayersAdapter.getLayers(this.userByReq(req), requestMapConfig.layers, pgConnection, + function(err, layers, datasource) { + if (err) { + return callback(err); + } - requestMapConfig.layers = layers; - return callback(null, requestMapConfig, datasource) - }); + requestMapConfig.layers = layers; + return callback(null, requestMapConfig, datasource); + } + ); }; me.afterLayergroupCreate = function(req, mapconfig, response, callback) { @@ -333,7 +336,7 @@ module.exports = function(redisPool) { var dbName = req.params.dbname; var cacheKey = dbName + ':' + token; - Step( + step( function getAffectedTablesAndLastUpdatedTime() { queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); }, @@ -375,16 +378,18 @@ module.exports = function(redisPool) { me.userByReq = function(req) { var host = req.headers.host; + if (req.params.user) { + return req.params.user; + } var mat = host.match(this.re_userFromHost); if ( ! mat ) { - console.error("ERROR: user pattern '" + this.re_userFromHost - + "' does not match hostname '" + host + "'"); + console.error("ERROR: user pattern '" + this.re_userFromHost + "' does not match hostname '" + host + "'"); return; } // console.log("Matches: "); console.dir(mat); - if ( ! mat.length === 2 ) { - console.error("ERROR: pattern '" + this.re_userFromHost - + "' gave unexpected matches against '" + host + "': " + mat); + if ( mat.length !== 2 ) { + console.error("ERROR: pattern '" + this.re_userFromHost + "' gave unexpected matches against '" + host + "': " + + mat); return; } return mat[1]; @@ -409,7 +414,8 @@ module.exports = function(redisPool) { var layergroup_id = req.params.token; var auth_token = req.params.auth_token; - //console.log("Checking authorization from signer " + signer + " for resource " + layergroup_id + " with auth_token " + auth_token); + //console.log("Checking authorization from signer " + signer + " for resource " + layergroup_id + + // " with auth_token " + auth_token); var mapStore = req.app.mapStore; if (!mapStore) { throw new Error('Unable to retrieve map configuration token'); @@ -445,7 +451,7 @@ module.exports = function(redisPool) { } //console.log("given ApiKey: " + givenKey); var user = me.userByReq(req); - Step( + step( function (){ cartoData.getUserMapKey(user, this); }, @@ -469,7 +475,7 @@ module.exports = function(redisPool) { var that = this; var user = me.userByReq(req); - Step( + step( function (){ that.authorizedByAPIKey(req, this); }, @@ -545,6 +551,7 @@ module.exports = function(redisPool) { ); }; + // jshint maxcomplexity:10 /** * Whitelist input and get database name & default geometry type from * subdomain/user metadata held in CartoDB Redis @@ -559,7 +566,12 @@ module.exports = function(redisPool) { //console.log("type of req.query.lzma is " + typeof(req.query.lzma)); // Decode (from base64) - var lzma = (new Buffer(req.query.lzma, 'base64').toString('binary')).split('').map(function(c) { return c.charCodeAt(0) - 128 }); + var lzma = new Buffer(req.query.lzma, 'base64') + .toString('binary') + .split('') + .map(function(c) { + return c.charCodeAt(0) - 128; + }); // Decompress lzmaWorker.decompress( @@ -574,7 +586,7 @@ module.exports = function(redisPool) { callback(new Error('Error parsing lzma as JSON: ' + err)); } }, - function(percent) { // progress + function(/*percent*/) { // progress //console.log("LZMA decompression " + percent + "%"); } ); @@ -597,14 +609,15 @@ module.exports = function(redisPool) { if ( tksplit.length > 1 ) { req.params.signer = tksplit.shift(); if ( ! req.params.signer ) req.params.signer = user; - else if ( req.params.signer != user ) { - var err = new Error('Cannot use map signature of user "' + req.params.signer + '" on database of user "' + user + '"'); + else if ( req.params.signer !== user ) { + var err = new Error('Cannot use map signature of user "' + req.params.signer + '" on database of user "' + + user + '"'); err.http_status = 403; callback(err); return; } if ( tksplit.length > 1 ) { - var template_hash = tksplit.shift(); // unused + /*var template_hash = */tksplit.shift(); // unused } req.params.token = tksplit.shift(); //console.log("Request for token " + req.params.token + " with signature from " + req.params.signer); @@ -617,11 +630,9 @@ module.exports = function(redisPool) { // for cartodb, ensure interactivity is cartodb_id or user specified req.params.interactivity = req.params.interactivity || 'cartodb_id'; - var that = this; - if (req.profiler) req.profiler.done('req2params.setup'); - Step( + step( function getPrivacy(){ me.authorize(req, this); }, diff --git a/lib/cartodb/sql/sql_api.js b/lib/cartodb/sql/sql_api.js index 44c831e2..32885e57 100644 --- a/lib/cartodb/sql/sql_api.js +++ b/lib/cartodb/sql/sql_api.js @@ -16,7 +16,7 @@ module.exports.query = function (username, api_key, sql, callback) { var qs = { q: sql }; // add api_key if given - 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 // @@ -36,11 +36,11 @@ module.exports.query = function (username, api_key, sql, callback) { var reqSpec = { url:sqlapi, json:true, - headers:{host: sqlapihostname} + headers:{host: sqlapihostname}, // http://nodejs.org/api/http.html#http_agent_maxsockets - ,pool:{maxSockets:maxSockets} + pool:{maxSockets:maxSockets}, // timeout in milliseconds - ,timeout:maxSQLTime + timeout:maxSQLTime }; if ( sql.length > maxGetLen ) { reqSpec.method = 'POST'; diff --git a/lib/cartodb/template_maps.js b/lib/cartodb/template_maps.js index 164161a8..c10bf0f6 100644 --- a/lib/cartodb/template_maps.js +++ b/lib/cartodb/template_maps.js @@ -1,7 +1,7 @@ -var crypto = require('crypto'), - Step = require('step'), - _ = require('underscore'), - dot = require('dot'); +var crypto = require('crypto'); +var step = require('step'); +var _ = require('underscore'); +var dot = require('dot'); var EventEmitter = require('events').EventEmitter; @@ -56,7 +56,7 @@ var o = TemplateMaps.prototype; //--------------- PRIVATE METHODS -------------------------------- o._userTemplateLimit = function() { - return this.opts['max_user_templates'] || 0; + return this.opts.max_user_templates || 0; }; /** @@ -71,7 +71,7 @@ o._redisCmd = function(redisFunc, redisArgs, callback) { var that = this; var db = that.db_signatures; - Step( + step( function getRedisClient() { that.redis_pool.acquire(db, this); }, @@ -89,6 +89,7 @@ o._redisCmd = function(redisFunc, redisArgs, callback) { }; var _reValidIdentifier = /^[a-zA-Z][0-9a-zA-Z_]*$/; +// jshint maxcomplexity:15 o._checkInvalidTemplate = function(template) { if ( template.version != '0.0.1' ) { return new Error("Unsupported template version " + template.version); @@ -136,7 +137,6 @@ o._checkInvalidTemplate = function(template) { break; default: return new Error("Unsupported authentication method: " + auth.method); - break; } return false; @@ -205,7 +205,7 @@ o.addTemplate = function(owner, template, callback) { var userTemplatesKey = this.key_usr_tpl({ owner:owner }); var limit = this._userTemplateLimit(); - Step( + step( function checkLimit() { if ( ! limit ) { return 0; @@ -253,7 +253,7 @@ o.addTemplate = function(owner, template, callback) { // o.delTemplate = function(owner, tpl_id, callback) { var self = this; - Step( + step( function deleteTemplate() { self._redisCmd('HDEL', [ self.key_usr_tpl({ owner:owner }), tpl_id ], this); }, @@ -311,7 +311,7 @@ o.updTemplate = function(owner, tpl_id, template, callback) { var userTemplatesKey = this.key_usr_tpl({ owner:owner }); - Step( + step( function getExistingTemplate() { self._redisCmd('HGET', [ userTemplatesKey, tpl_id ], this); }, @@ -366,7 +366,7 @@ o.listTemplates = function(owner, callback) { // o.getTemplate = function(owner, tpl_id, callback) { var self = this; - Step( + step( function getTemplate() { self._redisCmd('HGET', [ self.key_usr_tpl({owner:owner}), tpl_id ], this); }, @@ -424,14 +424,14 @@ var _reNumber = /^([-+]?[\d\.]?\d+([eE][+-]?\d+)?)$/, _reCSSColorName = /^[a-zA-Z]+$/, _reCSSColorVal = /^#[0-9a-fA-F]{3,6}$/; -_replaceVars = function(str, params) { +function _replaceVars (str, params) { //return _.template(str, params); // lazy way, possibly dangerous // Construct regular expressions for each param Object.keys(params).forEach(function(k) { str = str.replace(new RegExp("<%=\\s*" + k + "\\s*%>", "g"), params[k]); }); return str; -}; +} o.instance = function(template, params) { var all_params = {}; var phold = template.placeholders || {}; @@ -450,16 +450,14 @@ o.instance = function(template, params) { else if ( type === 'number' ) { // check it's a number if ( typeof(val) !== 'number' && ! val.match(_reNumber) ) { - throw new Error("Invalid number value for template parameter '" - + k + "': " + val); + throw new Error("Invalid number value for template parameter '" + k + "': " + val); } } else if ( type === 'css_color' ) { // check it only contains letters or // starts with # and only contains hexdigits if ( ! val.match(_reCSSColorName) && ! val.match(_reCSSColorVal) ) { - throw new Error("Invalid css_color value for template parameter '" - + k + "': " + val); + throw new Error("Invalid css_color value for template parameter '" + k + "': " + val); } } else { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index e33b4102..4f437dd6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,11 +1,11 @@ { "name": "windshaft-cartodb", - "version": "1.28.6", + "version": "1.30.1", "dependencies": { "cartodb-psql": { "version": "0.4.0", "from": "cartodb-psql@~0.4.0", - "resolved": "https://github.com/CartoDB/node-cartodb-psql/tarball/0.4.0", + "resolved": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.4.0.tgz", "dependencies": { "pg": { "version": "2.6.2-cdb1", @@ -87,7 +87,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -95,7 +96,7 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1" + "from": "inherits@2" } } } @@ -119,7 +120,7 @@ "redis-mpool": { "version": "0.3.0", "from": "redis-mpool@~0.3.0", - "resolved": "https://github.com/CartoDB/node-redis-mpool/tarball/0.3.0", + "resolved": "https://registry.npmjs.org/redis-mpool/-/redis-mpool-0.3.0.tgz", "dependencies": { "generic-pool": { "version": "2.1.1", @@ -157,9 +158,9 @@ "resolved": "https://registry.npmjs.org/rollbar/-/rollbar-0.3.13.tgz", "dependencies": { "node-uuid": { - "version": "1.4.2", + "version": "1.4.3", "from": "node-uuid@1.4.x", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "lru-cache": { "version": "2.2.4", @@ -181,8 +182,8 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" }, "windshaft": { - "version": "0.37.5", - "from": "windshaft@~0.37.5", + "version": "0.40.0", + "from": "windshaft@~0.40.0", "dependencies": { "chronograph": { "version": "0.1.0", @@ -193,6 +194,36 @@ "version": "0.23.0", "from": "grainstore@~0.23.0", "dependencies": { + "redis-mpool": { + "version": "0.1.0", + "from": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0", + "resolved": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0", + "dependencies": { + "generic-pool": { + "version": "2.1.1", + "from": "generic-pool@~2.1.1" + }, + "redis": { + "version": "0.12.1", + "from": "redis@~0.12.1" + }, + "hiredis": { + "version": "0.1.17", + "from": "hiredis@~0.1.17", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@*" + }, + "nan": { + "version": "1.1.2", + "from": "nan@~1.1.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" + } + } + } + } + }, "carto": { "version": "0.9.5-cdb2", "from": "https://github.com/CartoDB/carto/tarball/0.9.5-cdb2", @@ -264,9 +295,9 @@ "from": "forever-agent@~0.5.0" }, "node-uuid": { - "version": "1.4.2", + "version": "1.4.3", "from": "node-uuid@~1.4.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "tough-cookie": { "version": "0.12.1", @@ -1680,7 +1711,7 @@ } }, "tilelive-mapnik": { - "version": "0.6.12", + "version": "0.6.15", "from": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb", "resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb", "dependencies": { @@ -2080,50 +2111,21 @@ } }, "canvas": { - "version": "1.1.6", - "from": "canvas@1.1.6", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-1.1.6.tgz", + "version": "1.2.1", + "from": "canvas@1.2.1", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-1.2.1.tgz", "dependencies": { "nan": { - "version": "1.2.0", - "from": "nan@~1.2.0" - } - } - }, - "redis-mpool": { - "version": "0.1.0", - "from": "redis-mpool@git://github.com/CartoDB/node-redis-mpool.git#0.1.0", - "resolved": "git://github.com/CartoDB/node-redis-mpool.git#47510b8d4525ee24aa2e5328976372274a1d144e", - "dependencies": { - "generic-pool": { - "version": "2.1.1", - "from": "generic-pool@~2.1.1" - }, - "redis": { - "version": "0.12.1", - "from": "redis@~0.12.1" - }, - "hiredis": { - "version": "0.1.17", - "from": "hiredis@~0.1.17", - "dependencies": { - "bindings": { - "version": "1.2.1", - "from": "bindings@*" - }, - "nan": { - "version": "1.1.2", - "from": "nan@~1.1.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" - } - } + "version": "1.5.3", + "from": "nan@~1.5.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" } } }, "carto": { - "version": "0.14.0", - "from": "https://github.com/CartoDB/carto/tarball/update_to_master", - "resolved": "https://github.com/CartoDB/carto/tarball/update_to_master", + "version": "0.15.1-cdb1", + "from": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1", + "resolved": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1", "dependencies": { "mapnik-reference": { "version": "6.0.5", @@ -2149,44 +2151,12 @@ } }, "step-profiler": { - "version": "0.1.0", - "from": "step-profiler@git://github.com/CartoDB/node-step-profiler.git#0.1.0", - "resolved": "git://github.com/CartoDB/node-step-profiler.git#9b97881e450445bd8a307a9cc372b5129cb4529a" + "version": "0.2.1", + "from": "step-profiler@~0.2.1" }, "torque.js": { - "version": "2.7.1", - "from": "https://github.com/CartoDB/torque/tarball/2.8", - "resolved": "https://github.com/CartoDB/torque/tarball/2.8", - "dependencies": { - "carto": { - "version": "0.15.1", - "from": "https://github.com/CartoDB/carto/archive/master.tar.gz", - "resolved": "https://github.com/CartoDB/carto/archive/master.tar.gz", - "dependencies": { - "mapnik-reference": { - "version": "6.0.5", - "from": "mapnik-reference@~6.0.2", - "resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-6.0.5.tgz" - }, - "optimist": { - "version": "0.6.1", - "from": "optimist@~0.6.0", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" - }, - "minimist": { - "version": "0.0.10", - "from": "minimist@~0.0.1" - } - } - } - } - } - } + "version": "2.11.0", + "from": "torque.js@~2.11.0" }, "request": { "version": "2.48.0", @@ -2209,7 +2179,8 @@ }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1" + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", @@ -2258,9 +2229,9 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" }, "node-uuid": { - "version": "1.4.2", + "version": "1.4.3", "from": "node-uuid@~1.4.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" }, "qs": { "version": "2.3.3", diff --git a/package.json b/package.json index 47872ea6..042cf0bf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "1.28.6", + "version": "1.30.1", "description": "A map tile server for CartoDB", "keywords": [ "cartodb" @@ -25,7 +25,7 @@ "node-varnish": "https://github.com/Vizzuality/node-varnish/tarball/0.3.0", "underscore" : "~1.6.0", "dot": "~1.0.2", - "windshaft": "https://github.com/CartoDB/Windshaft/tarball/259-remove-old-api", + "windshaft": "https://github.com/CartoDB/Windshaft/tarball/master", "step": "~0.0.5", "queue-async": "~1.0.7", "request": "~2.9.203", @@ -38,12 +38,14 @@ }, "devDependencies": { "mocha": "~1.21.4", + "jshint": "~2.6.0", "redis": "~0.8.6", "strftime": "~0.8.2", "semver": "~1.1.4" }, "scripts": { - "test": "make check" + "preinstall": "make pre-install", + "test": "make test-all" }, "engines": { "node": ">=0.8 <0.11", diff --git a/scripts/check-node-canvas.sh b/scripts/check-node-canvas.sh new file mode 100644 index 00000000..a698e412 --- /dev/null +++ b/scripts/check-node-canvas.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +if [[ "$OSTYPE" == "darwin"* ]]; then + CAIRO_PKG_CONFIG=`pkg-config cairo --cflags-only-I 2> /dev/null` + RESULT=$? + + if [[ ${RESULT} -ne 0 ]]; then + echo "###################################################################################" + echo "# PREINSTALL HOOK ERROR #" + echo "#---------------------------------------------------------------------------------#" + echo "# #" + echo "# node-canvas install error: some packages required by 'cairo' are not found #" + echo "# #" + echo -e "# Use '\033[1mmake all\033[0m', it will take care of common/known issues #" + echo "# #" + echo "# As an alternative try: #" + echo "# Try to 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig' #" + echo "# #" + echo "# If problems persist visit: https://github.com/Automattic/node-canvas/wiki #" + echo "# #" + echo "###################################################################################" + exit 1 + fi +fi diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 00000000..f596aa12 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ "$OSTYPE" == "darwin"* ]]; then + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig +fi + +npm install diff --git a/scripts/lzma2config.js b/scripts/lzma2config.js new file mode 100644 index 00000000..0d8347b8 --- /dev/null +++ b/scripts/lzma2config.js @@ -0,0 +1,18 @@ +if (process.argv.length !== 3) { + console.error('Usage: node %s lzma_string', __filename); + process.exit(1); +} + +var LZMA = require('lzma').LZMA; +var lzmaWorker = new LZMA(); +var lzmaInput = decodeURIComponent(process.argv[2]); +var lzmaBuffer = new Buffer(lzmaInput, 'base64') + .toString('binary') + .split('') + .map(function(c) { + return c.charCodeAt(0) - 128 + }); + +lzmaWorker.decompress(lzmaBuffer, function(result) { + console.log(JSON.stringify(JSON.parse(JSON.parse(result).config), null, 4)); +}); diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index 84b1e220..3af4d95a 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -22,9 +22,11 @@ serverOptions = ServerOptions(); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); +['/tiles/layergroup', '/u/localhost/tiles/layergroup'].forEach(function(layergroup_url) { [true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) { -suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function() { +var suiteName = 'multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue + ";layergroup_url=" + layergroup_url; +suite(suiteName, function() { var redis_client = redis.createClient(global.environment.redis.port); var sqlapi_server; @@ -66,7 +68,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -94,7 +96,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -135,7 +137,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/localhost@' + expected_token + ':cb0/0/0/0.png', + url: layergroup_url + '/localhost@' + expected_token + ':cb0/0/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -152,7 +154,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -170,7 +172,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -222,7 +224,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)), + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), method: 'GET', headers: {host: 'localhost'} }, {}, function(res, err) { next(err, res); }); @@ -255,7 +257,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)), + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), method: 'GET', headers: {host: 'localhost'} }, {}, function(res, err) { next(err, res); }); @@ -299,7 +301,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( ] }; assert.response(server, { - url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)), + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), method: 'GET', headers: {host: 'localhost'} }, {}, function(res) { @@ -321,7 +323,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( ] }; assert.response(server, { - url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify(layergroup)), + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), method: 'GET', headers: {host: 'localhost'} }, {}, function(res) { @@ -352,7 +354,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -379,7 +381,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb10/1/0/0.png', + url: layergroup_url + "/" + expected_token + ':cb10/1/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -418,7 +420,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb11/4/0/0.png', + url: layergroup_url + "/" + expected_token + ':cb11/4/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -457,7 +459,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/0/1/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -475,7 +477,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/0/4/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -539,7 +541,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -561,7 +563,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( + statskey + ":stat_tag:" + layergroup.stat_tag + " to be 1, got " + val); var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -620,7 +622,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( ] }; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -648,7 +650,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( ] }; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -688,7 +690,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup?map_key=1234', + url: layergroup_url + '?map_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -716,7 +718,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -737,7 +739,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json?map_key=1234', headers: {host: 'localhost' }, method: 'GET' @@ -751,7 +753,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json?map_key=1234', headers: {host: 'localhost' }, method: 'GET' @@ -766,7 +768,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -782,7 +784,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/0/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -798,7 +800,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + url: layergroup_url + "/" + expected_token + '/1/0/0/0.grid.json', headers: {host: 'localhost' }, method: 'GET' @@ -849,7 +851,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup?map_key=1234', + url: layergroup_url + '?map_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -878,7 +880,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -908,7 +910,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?map_key=1234', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1044,7 +1046,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -1068,7 +1070,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1120,7 +1122,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup?api_key=1234', + url: layergroup_url + '?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -1146,7 +1148,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( if ( err ) throw err; var next = this; assert.response(server, { - url: '/tiles/layergroup/' + expected_token + ':cb0/0/0/0.png?api_key=1234', + url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?api_key=1234', method: 'GET', headers: {host: 'localhost' }, encoding: 'binary' @@ -1211,7 +1213,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( assert.ok(data.length > 1024*64); var next = this; assert.response(server, { - url: '/tiles/layergroup?api_key=1234', + url: layergroup_url + '?api_key=1234', method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: data @@ -1268,7 +1270,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -1310,7 +1312,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( { var next = this; assert.response(server, { - url: '/tiles/layergroup', + url: layergroup_url, method: 'POST', headers: {host: 'localhost', 'Content-Type': 'application/json' }, data: JSON.stringify(layergroup) @@ -1334,7 +1336,7 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( } var layergroupTtlRequest = { - url: '/tiles/layergroup?config=' + encodeURIComponent(JSON.stringify({ + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify({ version: '1.0.0', layers: [ { options: { @@ -1442,3 +1444,4 @@ suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue, function( }); }); +});